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

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.

Related

Uploading multiple pictures from the same form in CakePHP 1.2

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().

Saving a model with no data in CakePHP (just create id in db)

My CakePHP Cart model/table has only one field: id.
It hasMany LineItems.
I am not having success saving the Cart model alone:
$this->Cart->create();
$this->Cart->save();
Or, by passing it a $data array structured as follows and using saveAssociated():
$data = array(
'Cart' => array(),
'LineItem' => array(
array(
'item_id' => $item_id,
'qty' => $qty,
'price_option_id' => $price_option_id
)
)
);
If I add a useless_field to the Cart table/model, and pass some data in it saves. So obviously the problem lies in my having a model with a table with just a single id field and not passing in any other data to save. It won't create what it must be assuming is an 'empty' record.
I have passed 'validate' => false into the saveAssociated call but it doesn't make a difference (and there are no validations for this model to ignore).
Is there a way to do this? Am I missing something? Please enlighten me!
CakePHP tables require created and modified fields, or for you to define your own fields (ie you can call them whatever you want but they do the same thing).
In this instance you would use
$this->Cart->set($data);
$this->Cart->saveAll();

CakePHP hasMany checkbox

I have two tables: Ingredients and Customers. The relationship between them is that Customers hasMany Ingredients. By default when doing the cakebake using the console, the only way to change them is by assigning an ingredient to the customer in the Ingredients page. However, I want to have in Customers page a checkbox list of Ingredients that can be assigned. Is it possible to do this? If yes, how?
edit:
What I have done until now is that I add this code to my add.ctp:
echo $this->Form->input('Ingredient',
array('label'=>'',
'type'=>'select',
'multiple'=>'checkbox',
'options'=>$ingredients));
However, it gives me "Undefined variable: ingredients" error when I tried to open the add view.
You want and need a HABTM relationship. Different customers can access and use the same ingredients. Look at the docs here yours would be very similar to different Posts using same Tags.
If you are getting this error:
"Undefined variable: ingredients"
It sounds like you haven't declared this variable in your controller, and set it so that the view can use it. Without knowing your code, you would probably need do do something like this (please note I am guessing what your application structure looks like and have not tested this code).
CustomersController.php
// The controller action for your view
public function view() {
// Get the ID and name of all your ingredients
$ingredients = $this->Ingredient->find('all', array(
'fields' => array('id', 'name'),
'order' => 'name',
'recursive' => -1
));
// We will use this array to store all the HTML select options
$ingredientOptions = array();
// Loop through all the ingredients and add them to the select
// options in a format that is suitable for CakePHP to use in
// the view to build your HTML select menu.
foreach ($ingredients as $i) {
$ingredient = $i['Ingredient'];
$ingredientOptions[$ingredient['id']] = $ingredient['name'];
}
// Make the variable available to the view
$this->set('ingredients', $ingredientOptions);
}

Checking boxes with associated with HABTM in CakePHP

So, I have models associated via HABTM. In one view, I'm using checkboxes to save associations. I can save data no problem. But what I can't determine is how cleanly check boxes of pre-existing associations, say, when I go onto an Edit page and want to edit associations.
In this case, I have a User model and a Survey model.
Here's the code for my view:
foreach ($users as $user) {
echo $this->Form->input('User.User.', array('type' => 'checkbox', 'value' => $user['User']['id'], 'hiddenField' => false, 'label' => false )) . ' ' . $user['User']['username'];
}
There must be a way to simply mark boxes as selected where appropriate.

CakePHP HABTM: Editing one item casuses HABTM row to get recreated, destroys extra data

I'm having trouble with my HABTM relationship in CakePHP.
I have two models like so: Department HABTM Location. One large company has many buildings, and each building provides a limited number of services. Each building also has its own webpage, so in addition to the HABTM relationship itself, each HABTM row also has a url field where the user can visit to find additional information about the service they're interested and how it operates at the building they're interested in.
I've set up the models like so:
<?php
class Location extends AppModel {
var $name = 'Location';
var $hasAndBelongsToMany = array(
'Department' => array(
'with' => 'DepartmentsLocation',
'unique' => true
)
);
}
?>
<?php
class Department extends AppModel {
var $name = 'Department';
var $hasAndBelongsToMany = array(
'Location' => array(
'with' => 'DepartmentsLocation',
'unique' => true
)
);
}
?>
<?php
class DepartmentsLocation extends AppModel {
var $name = 'DepartmentsLocation';
var $belongsTo = array(
'Department',
'Location'
);
// I'm pretty sure this method is unrelated. It's not being called when this error
// occurs. Its purpose is to prevent having two HABTM rows with the same location
// and department.
function beforeSave() {
// kill any existing rows with same associations
$this->log(__FILE__ . ": killing existing HABTM rows", LOG_DEBUG);
$result = $this->find('all', array("conditions" =>
array("location_id" => $this->data['DepartmentsLocation']['location_id'],
"department_id" => $this->data['DepartmentsLocation']['department_id'])));
foreach($result as $row) {
$this->delete($row['DepartmentsLocation']['id']);
}
return true;
}
}
?>
The controllers are completely uninteresting.
The problem:
If I edit the name of a Location, all of the DepartmentsLocations that were linked to that Location are re-created with empty URLs. Since the models specify that unique is true, this also causes all of the newer rows to overwrite the older rows, which essentially destroys all of the URLs.
I would like to know two things:
Can I stop this? If so, how?
And, on a less technical and more whiney note: Why does this even happen? It seems bizarre to me that editing a field through Cake should cause so much trouble, when I can easily go through phpMyAdmin, edit the Location name there, and get exactly the result I would expect. Why does CakePHP touch the HABTM data when I'm just editing a field on a row? It's not even a foreign key!
From the CookBook the 1st problem is:
By default when saving a
HasAndBelongsToMany relationship, Cake
will delete all rows on the join table
before saving new ones.
I am not quite sure why Cake is trying to save the HABTM data even though you don't have a foreign key in your data, but there is an easy solution for that. Simply destroy the association for the save call:
$this->Location->unbindModel(
array('hasAndBelongsToMany' => array('Department'))
);
I'm thinking of one reason why this might be happening. When you retrieve Location, you also retrieve locations_departments data. And when you do a save($this->data) it looks for models in the array and saves them.
A way to solve this is setting the recursive attribute (of a model) to -1 or 0 (try, I'm not sure, just print out the data to see what comes out). You can set it in the model: var $recursive = -1; or in the controller method (action): $this->ModelName->recursive = -1;
More about recursive: http://book.cakephp.org/view/439/recursive
It's really similar to what harpax suggested, just if you don't need that data, tell it to Cake, so that it won't fetch it.
Trouble is that when saving your Location, you gave the save method an array containing all the DepartmentsLocations too. Thus CakePHP destroys everything and try to recreate it.
This is a common mistake with cake since it will often pull far too many results for you.
Be sure to pass only the data that needs to be saved, or better to fetch only the datas you need.

Resources