CakePHP: beforeSave not working with saveMany? - cakephp

So, for some reason, anything I do to data in the beforeSave callback, though it works on single records, does not work when using saveMany.
What gives? If I do the following:
public function beforeSave() {
$this->data['foo'] = 'bar'
die($this->data);
}
I can see that in fact $this->data does DOES get changed, but saveMany just ignores it and saves the original data instead.

Make sure you include the model name when manipulating $this->data, e.g. $this->data['Event']['foo'] = bar. Be sure the method returns true as well or the save will fail.
Edit
I whipped up a quick example and it seems to be working for me, see the code below. My suspicion is that maybe you are calling saveMany incorrectly and passing it the whole $this->request->data object but it's hard to guess without seeing your call as well.
View
<?php echo $this->Form->create('ParentTable'); ?>
Record 1: <br />
<?php echo $this->Form->input('ParentTable.0.name'); ?>
Record 2: <br />
<?php echo $this->Form->input('ParentTable.1.name'); ?>
<?php echo $this->Form->end('Submit'); ?>
Controller
public function index() {
if ($this->request->data) {
$this->ParentTable->saveMany($this->request->data['ParentTable']);
}
}
Model
public function beforeSave() {
$this->data['ParentTable']['name'] .= ' modified';
return true;
}

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.

cakephp getLastInsertId not working

Here I have used cakephp js helper to send data,After insert One data I need this last id for farther work.Here I have tried bellow code in Addcontroller
if ($this->Patient->save($this->request->data)) {
$lastid=$this->Patient->getLastInsertId();
$patient=$this->Patient->find('all',array(
'conditions'=>array('Patient.id'=>$lastid ),
'recursive' => -1
));
$this->set('patient', $patient);
}
In add.ctp I have tried bellow code but I haven't get last id here.
<?php foreach ($patient as $patient): ?>
<?php echo h($patient['Patient']['id']); ?>
<?php endforeach; ?>
Method getLastInsertId() return id of just saved records.
If you need this id in your view just after save, you must first set that variable in your controller like $this->set(compact('lastid','patient'); and then use in view <?php echo $lastid; ?>
use
if ($this->Patient->save($this->request->data)) {
$id = $this->Patient->id;
$patient=$this->Patient->find('all',array('conditions'=>array('Patient.id'=>$id),'recursive' => -1));
$this->set->('patient', $patient);
//If you are saving the record with ajax which it looks like you
//might be from your question you will need the following instead
//of $this->set->('patient', $patient); try:
return json_encode($patient);
You will then also need to update your js ajax call, you will have a json array to decode so parse it with jquery and append it back into your view.
Cake will always give you the id of record you have just saved, by simply adding $id = $this->MyModel->id; You can use the id to query for the record.
Try below code:
In controller:
$lastid=$this->Patient->getLastInsertId();
$this->set(compact('lastid','patient');
Then use $lastid in View file.
In controller:
$lastid=$this->Patient->getLastInsertId();
$patient['Patient']['last_id'] = $lastid;
then use $patient['Patient']['last_id'] in your view file.

how to access a function defined in app_controller from a ctp

I have function in app_controller.php.The function is like:
function globalSum($Var1,$Var2)
{
$Var3 = $Var1 + $Var2;
return $Var3;
}
Now I want to access this function from any CTP file to get the value after sum.when I call this function the arments will be send from the ctp file.
So,anybody can tell me how to call this function with arguments from the ctp file??
Thanks in advance..
The way you're trying to do this probably isn't the best, seeing as it's working against the MVC architecture that CakePHP uses.
In MVC, the ctp file is your view and should only act as a template, to the greatest extent possible, with any values that you need in the view should be passed to it from the controller.
You have a number of simple solutions to your problem.
One is simply to do the addition in the view:
index.ctp
<?php
echo $var1 + $var2
?>
For such a simple operation, why bother with a separate function?
If your function is more complicated, you can put it in the AppController and then set the view variable in the controller that the action belongs to. For example:
app_controller.php
<?php
function globalSum($Var1,$Var2) {
$Var3 = $Var1 + $Var2;
return $Var3;
}
?>
posts_controller.php
<?php
function index() {
$this->set('var3', $this->globalSum($var1,$var2));
}
?>
index.ctp
<?php
echo $var3;
?>
Hope that helps.

CakePHP question: How can i call a view of one controller from another controller?

This is posts/index.php =>
<?php foreach ($allposts as $post) {
echo '<tr class="class_row">';
echo '<td>';
echo $this->Html->link($post['Post']['title'],
array('controller'=>'posts','action'=>'view',$post['Post']['id']),
array('id'=>'id_anchor_title','class'=>'class_anchor_title') );
echo '<tr>';
echo '<td>';
}
?>
I want to call this posts/index.ctp from products/index.ctp => It will be a generic/common index.ctp for all controller. How can i do this ?
In posts/index.ctp the $allposts is used. It's set in posts/index action. But when i will call posts/index.ctp from products/index action different variable is set there. Suppose $this->set('allproducts',$allproducts); is set in products/index action. Now how can i use that allproducts variable in posts/index.ctp ?
As #Vins stated, you can use $this->render('view_name'); at the end of your controller action to render a different view (In your case it should be $this->render('/posts/index');)
In terms of using the variable you want, there are a couple things you can do. One would be to change your set function in each controller to use a common name. For example the posts controller could have $this->set('results',$allposts); and the products controller could have $this->set('results',$allproducts); Doing this, you can always reference $results in your view file. You might also want to set another variable, $pageModel. $this->set('pageModel','Product'); in your products controller for example. Then your posts/index.php file could do something like this:
<?php foreach ($results as $result) {
echo '<tr class="class_row">';
echo '<td>';
echo $this->Html->link($result[$pageModel]['title'],
array('controller'=>$this->controller,'action'=>'view',$result[$pageModel]['id']),
array('id'=>'id_anchor_title','class'=>'class_anchor_title') );
echo '<tr>';
echo '<td>';
}
?>
notice that I replaced 'controller' => 'posts' with 'controller' => $this->controller This will make your view dynamic so the links will always point to the view action of the correct controller.
I hope this helps!
We can use $this->render('view_name'); to use the another view for some other action. I'm not sure how exactly you're going to achieve your goal.
if you want to render posts/index.ctp instead of products/index.ctp, use $this->render('/posts/index');
Or you may want to put that in an element (that's the same idea of generic/common index.ctp).

Cakephp Validation

I am using an Account Controller which doesnt have its own table but uses User Model.
All works fine except - when I validate any form. It says validation fails (when I try to fail the validation to check) but doesnt throw the error below the field
View
<?php echo $this->Form->input('id'); ?>
<label for="UserPassword">New Password:</label>
<?php echo $this->Form->text('password', array('type' => 'password', 'value' => 'harsha')); ?><em>Password must be min 6 characters.</em> <?php echo $form->error('password'); ?>
Controller Action
if($this->User->saveField('password', $this->data['User']['password'], array('validate' => 'first'))) {
$this->Session->setFlash('Password has been changed.', 'flash-success');
} else {
$this->Session->setFlash('There was some problem with our system. Please try after some time.', 'flash-warning');
}
Try debug()ing the contents of $this->validationErrors in your view, as well as $this->data in your controller just after a form submission. This should give you a lot more information to work from.
I suspect that your problem is Cake is building form inputs based on the wrong model -- building form fields for Account.id and Account.password instead of User.id and User.password. This is because FormHelper takes its default model from the controller/view it's invoked from, which in your case appears AccountsController.
In order to generate the User.id and User.password fields your controller's submission handling expects, you'll need to prepend User. in your FormHelper calls. Thus:
$this->Form->input('User.id');
$this->Form->text('User.password');
Have you tried:
echo $session->flash();
Note that whatever the manual says, it returns, not echoes. I logged this a while back and it has been changed in the 1.3 manual, but not the 1.2.
Hi you who's asking If you want to show error-message that return from UserModel's validate So you can add line code bellow after input form password
<?php
if ($this->Form->isFieldError('password')) {
echo $this->Form->error('password', array('class' => 'error'));
?>
and if you want to show error-message that set by method setFlash
you must redirect page and then use $this->Session->flash('flash-name') in page you want to show it
<?php
//in UsersController
$this->Session->setFlash('message here', 'flash-name');
//in view
echo $this->Session->flash('flash-name');
?>
Good luck!

Resources