Associations in CakePHP - cakephp

I have 2 db tables : Users & Projects.
Fields of Users table are :
id, name, username, password, email, address, phone.
Fields of Projects table are :
id, name, description, user_id, deadline, budget.
What I need is that, I'll have 1 form, where there will be all fields from these 2 tables. And, when I submit the form, these fields will be saved in these 2 tables.
For example, my form will be like this :
<?php
echo $this->Form->create('User');
echo $this->Form->input('name',array('type'=>'text','div'=>false));
echo $this->Form->input('username',array('type'=>'text','div'=>false));
echo $this->Form->input('password',array('type'=>'password','div'=>'false));
echo $this->Form->input('email',array('type'=>'email','div'=>false));
echo $this->Form->input('address',array('type'=>'textarea','div'=>false));
echo $this->Form->input('phone',array('type'=>'tel','div'=>false));
echo $this->Form->input('name',array('type'=>'text','div'=>false));
echo $this->Form->input('description',array('type'=>'text','div'=>false));
echo $this->Form->input('deadline',array('type'=>'date','div'=>false));
echo $this->Form->input('budget',array('type'=>'num','div'=>false));
echo $this->Form->submit('Save');
echo $this->Form->end();
?>
Now, I want that when I submit the form, the fields will be saved in the corresponding tables; Users table will receive & save its fields, and Projects table will receive & save its fields.
For this, I tried hasMany association between Users & Projects tables, means, each user from Users table will have many projects from Projects table.
In User.php, I tried this :
class User extends AppModel{
public $hasMany=array(
'Project'=>array(
'className'=>'Project')
);
}
I thought it'd work, but it didn't, only Users table get its values, no value goes to Project table. What is the problem here ? What should I do ?
Thanks.

try this in your view
echo $this->Form->create('User');
echo $this->Form->input('name',array('type'=>'text','div'=>false));
echo $this->Form->input('username',array('type'=>'text','div'=>false));
echo $this->Form->input('password',array('type'=>'password','div'=>false));
echo $this->Form->input('email',array('type'=>'email','div'=>false));
echo $this->Form->input('address',array('type'=>'textarea','div'=>false));
echo $this->Form->input('phone',array('type'=>'tel','div'=>false));
echo $this->Form->input('Project.0.name',array('type'=>'text','div'=>false));
echo $this->Form->input('Project.0.description',array('type'=>'text','div'=>false));
echo $this->Form->input('Project.0.deadline',array('type'=>'date','div'=>false));
echo $this->Form->input('Project.0.budget',array('type'=>'num','div'=>false));
echo $this->Form->submit('Save');
echo $this->Form->end();
And in your controller you have to use
$this->User->saveAssociated($data);
see the manual about how to save associated data

At first, add the model names User and Project as prefix to your form fields to separate them:
View:
<?php
echo $this->Form->create('User');
echo $this->Form->input('User.name',array('type'=>'text','div'=>false));
echo $this->Form->input('User.username',array('type'=>'text','div'=>false));
echo $this->Form->input('User.password',array('type'=>'password','div'=>false));
echo $this->Form->input('User.email',array('type'=>'email','div'=>false));
echo $this->Form->input('User.address',array('type'=>'textarea','div'=>false));
echo $this->Form->input('User.phone',array('type'=>'tel','div'=>false));
echo $this->Form->input('Project.name',array('type'=>'text','div'=>false));
echo $this->Form->input('Project.description',array('type'=>'text','div'=>false));
echo $this->Form->input('Project.deadline',array('type'=>'date','div'=>false));
echo $this->Form->input('Project.budget',array('type'=>'num','div'=>false));
echo $this->Form->submit('Save');
echo $this->Form->end();
At second, use the separation to save your data into different models. Do not forget to add an associated column user_id to your table projects.
Controller
class UserController extends AppController
{
function create()
{
$this->loadModel('Project');
if($this->request->is('post', 'put'))
{
$this->User->getDataSource()->begin($this); // Starts transaction
if($this->User->save($this->request->data['User']))
{
// Success, save project now
$this->request->data['Project']['user_id'] = $this->User->getLastInsertId();
if($this->Project->save($this->request->data['Project']))
{
$this->User->getDataSource()->commit($this); // Commit
// success
} else {
$this->User->getDataSource()->rollback($this); // Rollback
}
} else {
$this->User->getDataSource()->rollback($this); // Rollback
}
}
}
}
I tested this code → works.

Your question is not very clear to me but what I see is you need to save data using associations.
But an association is a connection between two Active Record models. Associations are created to maintain Primary Key-Foreign Key information between instances of the two models.
You will need to save your USERS table data first and get the primary ID of last saved and use it as user_id for PROJECTS table and save PROJECT table information creating a PROJECT instance.

view:
<?php
echo $this->Form->create('User');
echo $this->Form->input('name',array('type'=>'text','div'=>false));
echo $this->Form->input('username',array('type'=>'text','div'=>false));
echo $this->Form->input('password',array('type'=>'password','div'=>'false));
echo $this->Form->input('email',array('type'=>'email','div'=>false));
echo $this->Form->input('address',array('type'=>'textarea','div'=>false));
echo $this->Form->input('phone',array('type'=>'tel','div'=>false));
// adding associate model name to every field..
echo $this->Form->input('Project.name',array('type'=>'text','div'=>false));
echo $this->Form->input('Project.description',array('type'=>'text','div'=>false));
echo $this->Form->input('Project.deadline',array('type'=>'date','div'=>false));
echo $this->Form->input('Project.budget',array('type'=>'num','div'=>false));
echo $this->Form->submit('Save');
echo $this->Form->end();
Note: You can disable all 'div' on form creation.. Look documentation for details...
User model:
class User extends AppModel{
public $hasMany=array('Project');
}
UsersController:
public function add(){
if($this->request->is('post')){
$this->User->create();
if($this->User->save($this->request->data)){// if you association is correct, all associated data will save automatically.
$this->Session->setFlash('saved');
$this->redirect('where you wants to redirect');
}else{
$this->Session->setFlash('Something went wrong. Try again');
}
}
}

Easy way with saveAll
<!-- View -->
<?php
echo $this->Form->create('User');
echo $this->Form->input('name',array('type'=>'text','div'=>false));
echo $this->Form->input('username',array('type'=>'text','div'=>false));
echo $this->Form->input('password',array('type'=>'password','div'=>false));
echo $this->Form->input('email',array('type'=>'email','div'=>false));
echo $this->Form->input('address',array('type'=>'textarea','div'=>false));
echo $this->Form->input('phone',array('type'=>'tel','div'=>false));
echo $this->Form->input('Project.0.name',array('type'=>'text','div'=>false));
echo $this->Form->input('Project.0.description',array('type'=>'text','div'=>false));
echo $this->Form->input('Project.0.deadline',array('type'=>'date','div'=>false));
echo $this->Form->input('Project.0.budget',array('type'=>'num','div'=>false));
echo $this->Form->submit('Save');
echo $this->Form->end();
?>
<!-- Controller -->
<?php
class UserController extends AppController
{
function create()
{
if($this->request->is('post', 'put'))
{
if($this->User->saveAll($this->request->data))
{
// Success - set your flashMessage
} else {
// Error - set your flashMessage
}
}
}
}
?>

Related

Trying to add data to database but getting "Error: Call to a member function save() on boolean"

I'm new to cakephp and I'm trying to add data to my coupon table with the following code.
In my UsersController I have:
public function addCoupon() {
if ($this->request->is('post')) {
if ($this->Coupon->save($this->request->data)) {
$this->Session->setFlash(__('The data has been saved'));
} else {
$this->Session->setFlash(__('The data could not be saved. Please, try again.'));
}
}
}
In my add_coupon.cpt I have:
<?php
echo $this->Form->create('Coupon',['url' => ['action' => 'addCoupon']]);
echo $this->Form->input('coupon_code');
echo $this->Form->input('expiration_date');
echo $this->Form->input('discount_amount');
echo $this->Form->input('usage_limit');
echo $this->Form->input('domain_limit');
echo $this->Form->input('description');
echo $this->Form->input('type');
echo $this->Form->button('Submit');
echo $this->Form->end();
?>
What is wrong with my code?
If your model is, in fact, named Coupon (singular) rather than Coupons (plural), try adding the following line of code anywhere before $this->Coupon->save(this->request->data):
$this->loadModel('Coupon');
But if it's actually named Coupons as convention would prescribe, change $this->Coupon->save(this->request->data) to $this->Coupons->save(this->request->data)
and add this line instead:
$this->loadModel('Coupons');
By default, the Users controller will only load the Users model. If you use any other models, you need to load them manually. Alternatively, you could move all of this to the Coupons controller, where it probably belongs anyways.

How can I use the same form in multiple views

I am using CakePHP 2.4. I have a blog where I can add and edit posts. When I implemented my edit.ctp, I recognized, that I have the same code in the view add.ctp:
<?php
echo $this->Form->create();
echo $this->Form->input('headline');
echo $this->Form->input('text', array('type' => 'textarea');
echo $this->Form->end('Save');
?>
(simplified code)
Regarding CakePHP´s recommendation, I want to keep my code DRY. What is the best way to define the form only one time and use it in both views?
Create a view in the folder Element with the form code
// app/View/Elements/postForm.ctp
<?php
echo $this->Form->create();
echo $this->Form->input('headline');
echo $this->Form->input('text', array('type' => 'textarea');
echo $this->Form->end('Save');
?>
Then include it in your desired views
echo $this->element('postForm');

Changing table field using 2 different models

I have an IT query system were by users can add their queries, when they add their query the IT department then replies/comments on the query.
How is should work is when the user adds a query it must change the query_type field in the it_queries table to OPEN and when the IT department views the query they reply/comment on it and must change query_type field from OPEN to PENDING then finally when the user has been helped/assisted they should be able to mark the query as closed using a checkbox, that will then change the status from PENDING TO CLOSE.
Not sure if they is a way of setting the constants in the add views and insert in the table.
Obviously i am learning and can someone please guide me on the steps i must take.
Here is my code for the add it_query for the users
<?php echo $this->Form->create('ItQuery'); ?>
<fieldset>
<legend><?php echo __('Add It Query'); ?></legend>
<?php
echo $this->Form->hidden('hr_employee_id',array('value'=>$loggedInId));
echo $this->Form->input('it_query_type_id');
echo $this->Form->input('comment');
echo $this->Form->hidden('status_type', array('value'=>OPEN));
?>
</fieldset>
<?php echo $this->Form->end(__('Submit')); ?>
Here is the code for my comments for IT Department
<?php echo $this->Form->create('ItQueryComment'); ?>
<?php echo __('Add It Query Comment'); ?>
<?php
echo $this->Form->input('it_query_id');
echo $this->Form->input('comment');
echo $this->Form->input('close_query');
?>
<?php echo $this->Form->end(__('Submit')); ?>
Here is the code for my ItQueryComments
public function add() {
if ($this->request->is('post')) {
$this->ItQueryComment->create();
if ($this->ItQueryComment->save($this->request->data)) {
$this->Session->setFlash(__('The it query comment has been saved'));
$this->redirect(array('controller' => 'it_queries','action' => 'view', $this->request->data['ItQueryComment']['it_query_id']));
} else {
$this->Session->setFlash(__('The it query comment could not be saved. Please, try again.'));
}
}
$itQueries = $this->ItQueryComment->ItQuery->find('list');
$hrEmployees = $this->ItQueryComment->HrEmployee->find('list');
$this->set(compact('itQueries', 'hrEmployees'));
}
While saving a comment for a particular Itquery , in your add function of Comments Controller after adding comment to database get its id by using $this->getLastInsertID();
and call function updateAll for Itquery Model and change status of that particular Query to "Pending".

Cakephp : Sort by a displayed value

I have a table in my view in which one of the columns is returned by a Helper.
How can I sort by this column?
Thanks
Edit
Controller
$this->set('myArray', $this->paginate('MyModel'));
View
foreach($myArray as $line) {
echo $line['MyModel']['col1'];
echo $line['MyModel']['col2'];
echo $line['MyModel']['col3'];
echo $line['MyModel']['col4'];
echo $this->MyModel->someHelper($line['MyModel']['id']);
}
I want to sort the table by the $this->MyModel->someHelper($line['MyModel']['id']);
If your data comes via pagination, use.
echo $this->Paginator->sort('you_field_name');
in your table head.

Validating multiple fields with the same name

I have a view file that looks like this:
<?php
echo $this->Form->create('ModelName');
echo $this->Form->input('ModelName.0.firstField');
echo $this->Form->input('ModelName.0.secondField');
echo $this->Form->input('ModelName.1.firstField');
echo $this->Form->input('ModelName.1.secondField');
echo $this->Form->end();
?>
My question is, how do I validate this data? I'm not saving, so it seems pointless to me to call the save or saveAll methods. I just want to validate the data before I process it and display the results to the user.
What happens currently using:
<?php
if ($this->request->is('post')) {
$this->ModelName->set($this->request->data);
if ($this->ModelName->validates()) {
echo $this->Session->setFlash('Success');
} else {
echo $this->Session->setFlash('Failure');
}
}
?>
Is it succeeds all the time even when I'm putting in data that should definitely fail.
I have also tried:
<?php
if ($this->request->is('post')) {
if ($this->ModelName->validateMany($this->request->data)) {
echo $this->Session->setFlash('Success');
} else {
echo $this->Session->setFlash('Failure');
}
}
?>
And that return success all the time as well, but that may be due to the fact that I don't know how to properly use validateMany.
Model::set is used for assigning a single set/record of data to the current instance of the Model. So it may be possible that you are only validating the first set of data in your POST data. You would have to iterate through each record in the POST data, Model::set it to the Model data, and then call Model::validates.
Instead of the above method or Model::validateMany, try using Model::saveAll without actually saving.
http://api20.cakephp.org/class/model#method-ModelsaveAll
validate: Set to false to disable validation, true to validate each record before saving, 'first' to validate all records before any are saved (default), or 'only' to only validate the records, but not save them.
<?php
if ($this->request->is('post')) {
if ($this->ModelName->saveAll($this->request->data, array('validate' => 'only'))) {
echo $this->Session->setFlash('Success');
} else {
echo $this->Session->setFlash('Failure');
}
}
?>

Resources