I have two models "Ficha" and "Perigo":
class Ficha extends AppModel {
var $primaryKey = 'id_ficha';
public $validate = array(
'nome_produto' => array(
'rule' => 'notEmpty'
),
'versao' => array(
'rule' => 'notEmpty'
),
'data_ficha' => array(
'rule' => 'notEmpty'
)
);
}
class Perigo extends AppModel {
var $belongsTo = array(
'Ficha' => array(
'className' => 'Ficha',
'foreignKey' => 'id_fichas'
)
);
}
As you can see they are "linked". Now, in the code i have a form for Ficha that the method "add()" of FichasController redirects to my Perigo Model:
add() (of FichaController)
public function add() {
//pr($this->request->data); // to get the data from the form
if ($this->request->is('post')) {
$this->Ficha->create();
if ($this->Ficha->save($this->request->data)) {
$this->Session->setFlash('Your post has been saved.');
//$last_id=$this->Ficha->getLastInsertID();
//$this->redirect(array('action' => 'preencher_ficha'),$last_id);
$this->redirect(array('controller'=>'perigos', 'action' => 'add'),$last_id);
} else {
$this->Session->setFlash('Unable to add your post.');
}
}
}
The redirection is made to a form that exists in PerigosController.
add.ctp (of Perigo)
echo $this->Form->create('Perigo');
echo $this->Form->input('class_subst', array('label' => 'Classificação da substância ou mistura:'));
echo $this->Form->input('simbolos_perigo', array('label' => 'Símbolos de Perigo:'));
echo $this->Form->input('frases_r', array('label' => 'Frases R:'));
echo $this->Form->end('Avançar');
add() (of PerigoController)
public function add() {
if ($this->request->is('post')) {
$this->Perigo->create();
if ($this->Perigo->save($this->request->data)) {
$this->Session->setFlash('Your post has been saved.');
$this->redirect(array('controller'=>'perigos', 'action' => 'index'));
} else {
$this->Session->setFlash('Unable to add your post.');
}
}
}
but there's something i don't know how to do it. Since the models are relational, and the same happens with the two tables on the database (the table perigos has a foreignkey that is the primary key of the table "fichas", how can i insert the data on table perigos in database? I mean, how can i get the key of the Ficha inserted in the first form and insert her in the foreign key of "perigos" when i submit this second form?
As #mark says, your redirection is bad, it should include the id in the URL array:
$this->redirect(array('controller'=>'perigos', 'action' => 'add', $last_id));
Like this you are passing the parameter by URL.
In the add action of your PerigosController you should have an $idFicha param at the method:
//PerigosController.php
public function add($idFicha){
//here you can use $idFicha
...
//when submiting the Perigos form, we add the foreign key.
if($this->request->is('post')){
//adding the foreign key to the Perigo's array to add in the DB.
$this->request->data['Perigo']['ficha_id'] = $idFicha;
if ($this->Ticket->save($this->request->data)) {
//...
}
}
}
Data submitted by POST method in a form will be always contained in an array of this type: $this->request->data['Model_name']. In your case:
$this->request->data['Perigo']
Another way to do this, is using sessions if you prefer to hide the id value:
http://book.cakephp.org/2.0/en/core-libraries/components/sessions.html#sessions
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
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');
I have controller with an add action.
public function add() {
$this->layout = 'manage';
$this->set($this->Restaurant->fetchRelatedData());
if ($this->request->is('post')) {
$this->Restaurant->create();
if ($this->Restaurant->save($this->request->data)) {
$this->Session->setFlash('ok!');
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash('Error!');
}
}
}
View for this action created with Form and Js helpers:
echo $this->Form->create('Restaurant');
// some fields
echo $this->Form->input('district_id', array('label' => 'District'));
echo $this->Form->input('street_id', array('label' => 'Street'));
// other fields
echo $this->Form->end(array('label' => 'Add'));
$this->Js->get('#RestaurantDistrictId')->event('change',
$this->Js->request(array(
'controller'=>'streets',
'action'=>'getByDistrict'
), array(
'update'=>'#RestaurantStreetId',
'async' => true,
'method' => 'post',
'dataExpression'=>true,
'data'=> $this->Js->serializeForm(array(
'isForm' => true,
'inline' => true
))
))
);
Js helper shows list with streets that are in choosen district.
StreetsController -> getByDistrict action:
public function getByDistrict(){
$district_id = $this->request->data['Restaurant']['district_id'];
$streets = $this->Street->find('list', array(
'conditions' => array('Street.district_id' => $district_id),
'fields' => array('street'),
'order' => array('Street'),
'recursive' => -1,
));
$this->set('streets', $streets);
$this->layout = 'ajax';
}
Everything worked fine until I added the administrative prefix to this action.
If action is named public function add() – all things works.
If action is named *public function admin_add()* – Js helper stops updating streets list on district change.
I'm not 100% sure on this, but I believe that the JS helper is preserving the admin prefix when it makes the AJAX request. When in add() it would call getByDistrict(). When in admin_add() it would call admin_getByDistrict(). Try passing 'admin' => false into Js->request.