I'm trying to save data to two models (a model and related hasMany) simultaneously, and have had some success in a number of places in my app, however this approach doesn't seem to be working with tables/models which have underscored names, i.e.
//View Code
echo $this->Form->create('Product');
echo $this->Form->input('name',array('between' => '<br />'));
echo $this->Form->input('Component.0.text',array('between' => '<br />'));
echo $this->Form->end(__('Submit'));
//Controller Code
if ($this->Product->saveAssociated($this->request->data)) {
$this->Session->setFlash(__('The product has been saved'));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The product could not be saved. Please, try again.'));
}
The above works fine, however I have a model ProductComponent (db table product_components)
//View Code
echo $this->Form->create('Product');
echo $this->Form->input('name',array('between' => '<br />'));
echo $this->Form->input('ProductComponent.0.text',array('between' => '<br />'));
echo $this->Form->end(__('Submit'));
//Controller Code
if ($this->Product->saveAssociated($this->request->data)) {
$this->Session->setFlash(__('The product has been saved'));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The product could not be saved. Please, try again.'));
}
The form is picking this up correctly as it's showing a Textarea rather than a standard input, however when saveAssociated is run, I get the response:
Database table product__components for model ProductComponent was not found.
Why is cake looking for a table with a double underscored name?
Any ideas?
Update for Issem Danny:
public $hasMany = array(
'ProductComponent' => array(
'className' => 'Product_Component',
'foreignKey' => 'product_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
A few things:
If you have these three models: Product, Component, ProductComponent, it seems to me you're trying to setup hasAndBelongsToMany relations. Check out the cakephp docs.
Using Component as or in a model name seems confusing to me..
If you have a model for a table product_components: your model should be named "ProductComponent" without an underscore (cake will add that automatically). If you dont follow cake's conventions you can declare the "useTable" property. Your model should look like this:
Code:
// model
class ProductComponent extends AppModel {
public $name = "ProductComponent";
// Only needed when not following cake's conventions
public $useTable = "product_components";
// rest of model code ...
}
// And the hasmany relation
public $hasMany = array(
'ProductComponent' => array(
'className' => 'ProductComponent',
'foreignKey' => 'product_id'
)
);
Hope that helps, good luck.
Have you tried to use
$this->Product->saveAll($this->data))
Try this link SaveAll
Related
What I'm trying to reach is to register a User and a Firm at once. So I would need to insert into 3 tables: users, firms, and firms_users. CakePHP should do this automatically, because I've set the $hasAndBelongsToMany associtation in the models. But during the registration, only the users table gets written. Am I missing something?
registration form
<div class="users form">
<?php echo $this->Form->create('User'); ?>
<fieldset>
<legend><?php echo __('Add User'); ?></legend>
<?php
echo $this->Form->input('User.email', array('type' => 'email')); //standard HTML5 email validation
echo $this->Form->input('User.password');
echo $this->Form->input('Firm.0.name');
echo $this->Form->input('Firm.0.zipcode');
?>
</fieldset>
<?php echo $this->Form->end(__('Submit')); ?>
</div>
the relevant part of User model
public $hasAndBelongsToMany = array(
'Firm' => array(
'className' => 'Firm',
'joinTable' => 'firms_users',
'foreignKey' => 'user_id',
'associationForeignKey' => 'firm_id',
'unique' => 'keepExisting',
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'finderQuery' => '',
),
and the relevant part of Firm model
class Firm extends AppModel {
public $hasAndBelongsToMany = array('User'=>array('className'=>'User'));
finally the UsersController / show_reg_form action
public function show_reg_form(){
if ($this->request->is('post')) {
$this->loadModel('Firm');
$this->User->create();
$this->Firm->create();
if ($this->User->saveAll($this->request->data)) {
$this->Session->setFlash(__('The user has been saved'));
return $this->redirect(array('action' => 'loggedin','loggedin'));
}
$this->Session->setFlash(
__('The user could not be saved. Please, try again.')
);
}
}
I think this code will work
public function show_reg_form(){
if ($this->request->is('post')) {
$this->User->create();
if ($this->User->save($this->request->data)) {
$this->Firm->create();
if($this->Firm->save($this->request->data))
$this->Session->setFlash(__('The user has been saved'));
return $this->redirect(array('action' => 'loggedin','loggedin'));
}
else{
$this->Session->setFlash(
__('The user could not be saved. Please, try again.')
);
}
}
}
It should be
echo $this->Form->input('Firm.name');
echo $this->Form->input('Firm.zipcode');
In order to save with hasAndBelongsToMany association you should have the array like this to save the records
Array
(
[User] => Array
(
[field_1] => 1
[field_2] => 2
[field_3] => 3
[field_4] => 4
)
[Firm] => Array
(
[0] => 5
[1] => 8
[2] => 4
)
)
where 5, 8, 4 are the record ids of firm table
I think This is not the case you're looking for,
I would suggest you to go through the
hasMany association if User has many firms public $hasMany = array('Firm');
hasOne association if User has only one firm public $hasOne = array('Firm');
so that it will add a Firm when a user is created
You can not save data in all three tables using only one saveAll.
First you need to save firm record then assign the new generated firm id as hidden field in $this->data and save user model data with saveAll. Then data will enter in third table named firms_users.
You can check the below link for more information
http://book.cakephp.org/2.0/en/models/saving-your-data.html#saving-related-model-data-habtm
I'm Using cakePHP 2.3.8
I have two tables: application, computer_application. The relationship is one application hasMany computer_application, foreign key is application_id
in my ComputerApplication model:
class ComputerApplication extends AppModel{
public $name = "ComputerApplication";
public $useTable = "computer_application";
var $belongsTo = array(
'Computer' => array(
'className' => 'Computer',
'foreignKey' => 'computer_id',
'dependent' => true
),
'Application' => array(
'className' => 'Application',
'foreignKey' => 'application_id',
'dependent' => true
)
);
}
In my ComputerApplication controller. HERE I INITIALIZE THE POPULATION OF DROPDOWN in **add** function
public function add($id=null) {
if (!$id) {
throw new NotFoundException(__('Invalid post'));
}
$this->set('computerApplications',
$this->ComputerApplication->Application->find('list',
array('fields' => array('description') ) ) );
}
Now In my Add View
echo $this->Form->create("computerApplication");
echo $this->Form->input('application_id',array('empty'=>''));
echo $this->Form->end('Save Post');
My problem is that it won't populate the select input. This is the first time I used 2 words in table [computer_application] using cake since I don't have problem populating other table with just one word. Just help me identify which I need to tweak for it to populate.
$this->set('applications', ...
and not
$this->set('computerApplications', ...
OKay so i have two tables Employee and User
my employee model looks like this:
class Employee extends AppModel{
public $name = 'Employee';
public $primaryKey = "employee_id";
public $actsAs = array('Containable');
public $belongsTo = array(
'User' => array(
'className' => 'User',
'dependent' => false,
'foreignKey' => 'user_id'
)
);
}
And my user model looks like this:
App::uses('AuthComponent', 'Controller/Component');
class User extends AppModel {
// ...
public function beforeSave($options = array()) {
if (isset($this->data[$this->alias]['password'])) {
$this->data[$this->alias]['password'] = AuthComponent::password($this->data[$this->alias]['password']);
}
return true;
}
public $validate = array(
'username' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'A username is required'
)
),
'password' => array(
'required' => array(
'rule' => array('notEmpty'),
'message' => 'A password is required'
)
),
'role' => array(
'valid' => array(
'rule' => array('inList', array('employee', 'client')),
'message' => 'Please enter a valid role',
'allowEmpty' => false
)
)
);
}
In my employee controller i have an action that allows employees to add other employees the action looks like this:
public function add() {
if ($this->request->is('post')) {
$this->Employee->User->create();
if ($this->Employee->User->save($this->request->data)) {
$this->Session->setFlash(__('The user has been saved'));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The user could not be saved. Please, try again.'));
}
}
}
My employee table looks like this
employee_id user_id
Now whenever i add a user the user is correctly added in my user table and a row is also added in my employee table however there are two mistakes in the employee table:
The employee_id is an auto increment this does not happen and it seems it keeps overriting 1. (so that every user i try to create is employee_id = 1)
the user_id is always 0 however in the user table the user_id is for example 21.
Can anyone tell me why this is happening and how i can fix it?
update
My add action in my employee controller now looks like this:
public function add() {
if ($this->request->is('post')) {
$this->Employee->User->create();
if ($this->Employee->User->saveAll($this->request->data)) {
$this->Session->setFlash(__('The user has been saved'));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The user could not be saved. Please, try again.'));
}
}
}
ive added a hasMany to my user model:
public $hasMany = array(
'Employee' =>array(
'className' => 'Employee',
'dependent' => true,
'foreignKey' => 'user_id'
)
);
Still no change
A few issues...
1) Your primary key for employees table should be id, not employee_id. Primary keys are always named id, according to cakephp conventions - http://book.cakephp.org/2.0/en/getting-started/cakephp-conventions.html
2) Just as you've got a belongsTo in your Employee model, you should also add a hasOne relationship to your user model - see http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#hasone
3) In order to save a record, along with it's related data, the method you want is saveAll - check out the documentation here: http://book.cakephp.org/2.0/en/models/saving-your-data.html#model-saveall-array-data-null-array-options-array
I am having trouble understanding how to save Related Model Data in Cakephp 1.3. I have a model called Policy and a Model called Declinations. Policy hasMany Declinations. Declinations belongsTo Policy. All I want to do is save the policy_id in the Policy table in a field called policy_id in the Declinations table. So the question is how do I grab the Policy_Id from the corresponding model? Do I need to set the Policy_Id first in the Declination model or controller and then pass it to a hidden field in the view?
Here is my declination model
public $belongsTo = array(
'Policy' => array(
'className' => 'Policy',
'foreignKey' => 'policy_id'
My Policy Model is as follows
public $hasMany = array(
'Declination' => array(
'className' => 'Declination',
'foreignKey' => 'policy_id',
'dependent' => true
)
Here is my controller
public function add($id = null) {
if (!empty($this->data)) {
$this->Declination->create();
if ($this->Declination->saveAll($this->data['Declination'])) {
$this->Session->setFlash(__('Declinations saved.', true));
$this->redirect(array(
'controller' => 'coverages',
'action' => 'view',
$id
));
} else {
$this->Session->setFlash(__('Declinations failed to save.', true));
}
}
$reasons = $this->Declination->Reason->find('list');
$contactTypes = $this->Declination->ContactType->find('list');
$this->set(compact('id', 'reasons', 'contactTypes'));
}
Here is my view
<?php echo $this->UiForm->input("Declination.{$i}.first_name"); ?>
<?php echo $this->UiForm->input("Declination.{$i}.last_name"); ?>
<?php echo $this->UiForm->input("Declination.{$i}.company"); ?>
<?php echo $this->UiForm->input("Declination.{$i}.contact_type_id"); ?>
<?php echo $this->UiForm->input("Declination.{$i}.phone_number"); ?>
<?php echo $this->UiForm->input("Declination.{$i}.reason_id"); ?>
<?php echo $this->UiForm->input("Declination.{$i}.other", array(
'label' => 'If other, please supply a reason'
)); ?>
<?php echo $this->UiForm->input("Declination.{$i}.dated", array(
'type' => 'text',
'readonly' => 'readonly',
'data-datepicker' => ''
)); ?>
Any input would be greatly appreciated! Thanks!
Somehow, you must know WHICH Policy id you want to save - so you can either add that as a field in your view:
echo $this->UiForm->input("Declination.{$i}.policy_id", array('value'=>$policyId));
Or you can set it in your Controller before you save:
$this->request->data['Declination']['policy_id'] = $policyId;
Either way will work - use whichever makes more sense for your site.
How and where you GET the policy id is also up to you. You can use a find() in the Controller, then set() it so it's accessible in the view. Or, you can use a find() and retrieve it just before the save. Without knowing what data you have available where, it's hard to give more detail than that.
I have these models:
class Prefix extends AppModel {
public $displayField = 'prefix';
public $hasMany = array(
'State' => array(
'className' => 'State',
'foreignKey' => 'prefix_id',
'dependent' => false,
),
);
}
class State extends AppModel {
public $displayField = 'name';
public $belongsTo = array(
'Prefix' => array(
'className' => 'Prefix',
'foreignKey' => 'prefix_id',
),
);
}
Then I have this admin_add method, from the automatic scaffolder:
public function admin_add() {
if ($this->request->is('post')) {
$this->Peefix->create();
if ($this->Prefix->save($this->request->data)) {
$this->redirect(array('action' => 'index'));
} else {
// Error message
}
}
$states = $this->Prefix->State->find('list');
$this->set(compact('states'));
}
I also have the list of them in my form:
<?php echo $this->Form->input('State', array('multiple' => 'checkbox', 'type' => 'select',)); ?>
Now I can set the States for the Prefix. However, when I submit the form, the selection disappears. It is not saved in the database.
What did I do wrong?
You linked the models as if there is only one state per prefix, and many prefixes "assigned" to one state. That means you cannot use 'multiple' => 'checkbox'. So either remove this or change model associations to HABTM.
First, both foreign keys for hasMany and belongsTo must be the same. If in the parent model you provided invoice_circle_id as the key, then the same must be provided in the child model also. Obviously, that field must exist in the child table. See this for more info http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html
Second - you might want to use the saveAll() or saveAssociated() method for linked model data saving. Again - http://book.cakephp.org/2.0/en/models/saving-your-data.html contains all the ifnormation you need.
As for naming the input fields for hasMany, you name them like this:
$this->Form->input('ParentModel.fieldname');
$this->Form->input('ChildModel.0.fieldname');