Uploading multiple pictures from the same form in CakePHP 1.2 - cakephp

I have a one-to-many relationship where one House can have many Pictures. The models that I have are "House" and "Picture". I am using CakePHP 1.2 and I can upload one picture successfully by using this:
echo $form->input('Picture.filename', array('type' => 'file', 'label' => __l('Image')));
In my houses_controller.php file, I have this code to save the picture and corresponding association with its house:
$this->House->Picture->save($this->data['Picture']);
But I need to save several pictures now. I read the documentation at https://book.cakephp.org/1.2/en/The-Manual/Core-Helpers/Form.html and based on that information, I am trying to use this:
echo $form->input('Picture.0.filename', array('type' => 'file', 'label' => __l('Image 1'));
echo $form->input('Picture.1.filename', array('type' => 'file', 'label' => __l('Image 2'));
Then my houses_controller.php file has this:
$this->House->Picture->saveAll($this->data['Picture']);
I see that one new record is saved in my pictures table, but I was expecting to see two new entries in my table because I should have added two pictures, not only one. Any ideas about why this may not be saving two pictures for me? Thank you.

Solution:
$this->Deal->Picture->save($this->data['Picture'][0]);
$this->Deal->Picture->save($this->data['Picture'][1]);
Using $this->data['Picture'] was not sufficient because the array was returning multiple elements, so I had to reference each with the corresponding index such as $this->data['Picture'][0] for the first element, $this->data['Picture'][1] for the second one, etc.
NOTE: It was not saving two records for me, even thought I was using save() twice. But that was another issue. You can read the answers at Save multiple times in Cakephp for the corresponding solution. Basically you need to use create() before you use save().

Related

CakePHP - Manage multiple file upload fields and handle them correctly

i've been bothering and looking for a solution for quite a while now.
I'm planning an offer database for holidays with CakePHP. Data relations work fine to this point. Now i've got a mask "Add Offer" where it should be possible to upload several images in different fields, for example there are those fields available :
Name:
Location:
Image 1:
Image 2:
Image 3:
Image 4:
How would i handle a file upload for each field provided and insert it back in the correct field into the database? I've thought about a multiple upload field but the customer doesn't want it that way. Is there a possible solution with a switch case?
Any advice would be greatly appreciated.
Just create multiple fields like the client ask.
But store them in $this->data as an array but doing the following.
echo $this->Form->input('image.' , array('type' => 'file' , 'label' => 'image 1'));
echo $this->Form->input('image.' , array('type' => 'file' , 'label' => 'image 2'));
Do not forget the dot after image
Now when you pr($this->data) you will get something like the following
Model => {
image => {
[1] =>{image info error etc}
[2] =>{image info error etc}
}}

Settings page and multi edit rows

I would like to make a configuration page like this for my CMS
http://img4.hostingpics.net/pics/72087272ok.png
I want this page (admin/settings/index) gets me the various settings (ID 1 to 21) came to my table and in case of change, I can, in this form, do an update
After 3 days of not especially fruitful research I found something. I put in my SettingsController:
admin_index public function () {
if (!empty($this->data)) {
$this->Setting->saveAll($this->request->data['Setting']);
} else {
$this->request->data['Setting'] = Set::combine($this->Setting->find('all'),
'{n}. Setting.id', '{n}. Setting');
}
}
and my view:
<?php
echo $this->Form->create('Setting', array ('class' => 'form-horizontal'));
foreach($this->request->data['Setting'] as $key => $value) {
echo $this->Form->input('Setting.' . $key . '.pair');
echo $this->Form->input('Setting.' . $key . '.id');
}
echo $this->Form->end(array('class' => 'btn btn-primary', 'label' => 'Save',
'value' => 'Update!', 'div' => array ('class' => 'form-actions')));
?>
he is recovering well all my information, I can even update. The trouble is that I do not really know how I can do to get the same result as my first screenshot. He puts everything in the textarea while in some cases I want the checkbox and / or drop-down.
please help me or explain to me how to make a page that retrieves configuration information from my table and allows me to edit without use an address like admin/settings/edit/ID
My table settings is something like this here
http://img4.hostingpics.net/pics/724403settings.png
If you are asking about how to format the output to produce a "settings" page, you will need to do it manually or add some kind of metadata to your table schema, such as "field_type".
Now Cake will automatically generate a checkbox for a boolean or tiny int, for example, but as you have varchars, ints, texts and so on, this won't work for you (pair is presumably varchar or text to allow for the different possible values.
You cannot really automagically generate the outputs you want without telling Cake.
One option would be to add a field_type to the table, so:
key value field
site_name My Site input
site_online 1 checkbox
meta_desc [some text] textarea
and something like
foreach($settings as $setting) {
echo $this->Form->{$setting['field']}($setting['key'],
array('value' => $setting['value']));
}
might do what you are after.
Or if($key=='site_name') // output a textbox
but this is not exactly ideal.

Multiple models and uploading files

At first - I'm new to the Yii Framework. I did some research on my own but I couldn't find a precise solution to my issue.
Assume there are two related models - Product and Image. A single Product may have multiple Images assigned. What is the best approach at creating the create / update forms that would be able to manage this kind of scheme?
The Image model consists of various fields, along with a path to the image file, so it's not just a "container" for the path itself. What's more - I need to have a thumbnail generated for every uploaded image and its path stored within the same model.
What I need to achieve is pretty much similar to the admin inline functionality known from Django - there should be a section in the Product create / update form which would allow users to add / modify / delete Images.
I tried the multimodelform extension but I couldn't get file uploading to work. What's the best way of getting it done and not having to build the whole file-upload-enabled-multiple-model-form structure manually?
The detailed solution depends on if you are using CActiveForm or CHtml form. Since you have 2 related models I assume you are using CActiveForm and will point out some thing you need to keep in mind.
For this example i am gonna assume some definitions
Product with fields id, name
Product with ONE to MANY relation to 'images' on ProductImage
ProductImage with fields id, productId, path
I also assume there gonna be 1 upload / edit, but multi delete
Here's the view:
$form = $this->beginWidget(
'CActiveForm',
array(
'id' => 'upload-form',
'enableAjaxValidation' => false,
'htmlOptions' => array('enctype' => 'multipart/form-data'),
)
);
echo $form->labelEx($product, 'name');
echo $form->fileField($product, 'name');
echo $form->error($product, 'name');
echo $form->checkBoxList($product, 'path', $product->images);
echo $form->labelEx($productImage, 'path');
echo $form->fileField($productImage, 'path');
echo $form->error($productImage, 'path');
$this->endWidget();
And your action
public function actionUpdate($productId) {
$product = Product::model()->findByPk($productId)->with('images');
$productImage = new ProductImage();
if(isset($_POST['Item']))
{
$product->attributes=$_POST['Product'];
foreach($product->images as $im) {
if(in_array($im->path, $_POST['Item']['Image']))
$im->delete();
}
$productImage->image=CUploadedFile::getInstance($productImage,'path');
if($productImage->save())
{
$productImage->image->saveAs('some/new/path');
// redirect to success page
}
}
$this->render('update', array(
'product'=>$product,
'productImage'=>$productImage,
));
}
Now note that this solution is not tested so there will be bugs, but it should give you an idea on how to write your own form.
Resources:
http://www.yiiframework.com/wiki/2/how-to-upload-a-file-using-a-model/
http://www.yiiframework.com/wiki/384/creating-and-updating-model-and-its-related-models-in-one-form-inc-image

CakePHP: Retrieve multiple records from a single model to be edited in one form

Good day,
I have a model called ProjectRequirement which belongsTo Project, so Project hasMany ProjectRequirements
When I created the ProjectRequirement entries, I made use of this method:
<?php
echo $this->Form->inputs(array(
'legend => false,
'fieldset' => false,
'ProjectRequirement.1.description' => ...
'ProjectRequirement.2.description' => ...
'ProjectRequirement.3.description' => ...
));
?>
I did this so that I could make use of the saveMany() method to save multiple records at the same time. However, when I want to edit these records again on the same form, I cannot see, to be able to do it. I have kept the same field naming structure and tried to set the data as follows:
<?php
$this->request->data = $this->ProjectRequirement->find('all', array('conditions' => ...));
?>
A pr(); shows that the records are being returned, but they are not populating the form fields. If I remove the numbers and just have a single field like this:
<?php
echo $this->Form->inputs(array(
'legend => false,
'fieldset' => false,
'ProjectRequirement.description' => ...
));
?>
It works fine. How can I set the data so that multiple records from ProjectRequirement are set on multiple inout fields? Or can't I?
To reiterate: I do NOT have a problem saving multiple records, I have a problem retrieving multiple records to display.
Regards,
Simon
When you create the form to SAVE many fields, you name the fields like this:
ProjectRequirement.1.name...
ProjectRequirement.2.name...
ProjectRequirement.3.name...
...
However, when retrieving data, it is not the same scenario, and the general rules of arrays and how indexing works are applied here. So simply changing my fields to be like this:
ProjectRequirement.0.name...
ProjectRequirement.1.name...
ProjectRequirement.2.name...
...
Worked because I was only testing with one record in the database, and that row would have been at index 0, not 1.

CakePHP AutoComplete Question

I am working on a book review application and I am using autoComplete to search for titles in when creating a review. The review model has an associated book_id field and the relationship is setup as the review hasOne book and a book hasMany reviews.
I am trying to pass the Book.id (into the book_id field), but I want to display Book.name for the user to select from. With the default setup (accomplished via CakePHP's tutorial), I can only pass Book.name. Is it possible to display the name and pass the id?
Also, I am passing it via the following code in the create() action of the review controller:
$this->data['Review']['book_id'] = $this->data['Book']['id'];
Is that the proper way to do it in CakePHP? I know in Ruby on Rails, it is automatic, but I can't seem to make it work automagically in CakePHP. Finally, I am not using the generator because it is not available in my shared hosting environment... so if this is the wrong way, what do I need other than associates in my models to make it happen automatically?
Thanks for the help and I promise this is my question for awhile...
UPDATE- I tried the following, but it is not working. Any ideas why?
function autoComplete() {
$this->set('books', $this->Book->find('all', array(
'conditions' => array(
'Book.name LIKE' => $this->data['Book']['name'].'%'
),
'fields' => array('id','name')
)));
$this->layout = 'ajax';
}
The problem is that when I use the code above in the controller, the form submits, but it doesn't save the record... No errors are also thrown, which is weird.
UPDATE2:
I have determine that the reason this isn't working is because the array types are different and you can't change the array type with the autoComplete helper. As a workaround, I tried the follow, but it isn't working. Can anyone offer guidance why?
function create() {
if($this->Review->create($this->data) && $this->Review->validates()) {
$this->data['Review']['user_id'] = $this->Session->read('Auth.User.id');
$this->Book->find('first', array('fields' => array('Book.id'), 'conditions' => array('Book.name' => $this->data['Book']['name'])));
$this->data['Review']['book_id'] = $this->Book->id;
$this->Review->save($this->data);
$this->redirect(array('action' => 'index'));
} else {
$errors = $this->Review->invalidFields();
}
}
FINAL UPDATE:
Ok, I found that the helper only takes the find(all) type or array and that the "id" field wasn't passing because it only applied to the autoComplete's LI list being generated. So, I used the observeField to obtain the information and then do a database lookup and tried to create a hidden field on the fly with the ID, but that didn't work. Finally, the observeField would only take the characters that I put in instead of what I clicked, due to an apparent Scriptaculous limitation. So, I ended up going to a dropdown box solution for now and may eventually look into something else. Thanks for all of the help anyway!
First of all, $this->data will only contain ['Book']['id'] if the field exists in the form (even if it's hidden).
To select something by name and return the id, use the list variant of the find method, viz:
$selectList = $this->Book->find('list', array(
'fields' => array(
'id',
'name'
)));
$this->set('selectList', $selectList);
In the view, you can now use $selectList for the options in the select element:
echo $form->input('Book.id', array('type' => 'hidden'));
echo $form->input('template_id', array(
'options' => $selectList,
'type' => 'select'
));

Resources