I am trying to make change password option by using ajax. Here I have tried below code in controller
if ($this->request->is(array('post', 'put'))){
$id=$this->Auth->user('id');
$changePass=$_POST['cpass'];
$cpasss=AuthComponent::password($changePass);
echo $cpasss;
$up=$this->User->updateAll(
array('User.password'=>"$cpasss"),
array('User.id'=>"$id")
);
}
Here hash is working fine,I have seen by firebug but the problem is here password not updating in database.If I remove
$cpasss=AuthComponent::password($changePass);
then password is updating fine but without hash.May anybody help me to solve this problem ?
There is no need to use updateAll() here. Instead just save the data using save() and remember to pass the primary key with the save data:-
if ($this->request->is(array('post', 'put'))) {
$id = $this->Auth->user('id');
$changePass = $this->request->data['User']['cpass'];
$data = array(
'id' => $id,
'password' => AuthComponent::password($changePass)
);
$this->User->save($data);
}
If you do use updateAll() it needs to be used with caution as it does not escape the passed fields. From the docs:-
The $fields array accepts SQL expressions. Literal values should be
quoted manually using DboSource::value().
Update your code to:
if ($this->request->is(array('post', 'put'))){
$id=$this->Auth->user('id');
$changePass= $this->request->data['cpass'];
$cpasss=AuthComponent::password($changePass);
$up=$this->User->updateAll(
array('User.password'=> $cpasss),
array('User.id'=> $id)
);
}
Changes:
$_POST[] is not the proper way of taking form data in cakephp.
No need to include the variables in double quotes(").
Related
When I've Search my listing i'm getting some results with pagination, but when i go for second page my search is
breaking as it was a get request where i'm getting the search results via post method.
Note: For getting search results I don't want to submit the form via get request (i.e. Query string params) and also don't want to store the form data in session
Is there any way to get the results which satisfy the above conditions ?
You want to implement the PRG Pattern.
Post/Redirect/Get (PRG) is a web development design pattern that
prevents some duplicate form submissions, creating a more intuitive
interface for user agents (users). PRG implements bookmarks and the
refresh button in a predictable way that does not create duplicate
form submissions.
The CakeDC Search plugin makes that pretty easy to do in CakePHP.
It would be very hard to do it using only "POST" calls. You'll need to transfor your POST into a GET call.
Check this post i made or clone it from github
Hope this helps
EDIT:
Using my git repo. If you want url querystrings instead of named parameters:
in this line, instead of the foreach build the querystring and pass it to the redirect
in this line, get the parameters from the query string ($GET)
and in this line add page, sort and direction to this->paginate
I haven't tested it, but it should be something like that
We can do it with a patch.
In Views :
create search form :
$this->Form->create('Search', array('url' => array('controller' => 'controller', 'action' => 'index', substr(time(), 2,rand(1, 7) ))) );
Note : A random number appended at the end of the form action. This will let us know when to clear session.
in Controller :
public function index( $search = null)
{
$conditions = array(1 => 1);
if( !empty($this->data['Search']['keyword']) && $search)
{
$conditions = array('Model.field like' => $this->data['Search']['keyword'] . '%');
// store search array in session
$this->Session->write('conditions', $this->data['Search']);
}
if ($search)
{
$this->request->data['Search'] = $this->Session->read('conditions');
$conditions = array('Model.field like' => $this->data['Search']['keyword'] . '%');
}
else
{
$conditions = array(1 => 1);
$this->Session->delete('conditions');
}
$this->paginate= array('limit'=> 10, 'conditions' => $conditions);
$lists = $this->Paginate('Model');
}
Hope you understand the logic behind.
I got a problem with my cake validation.
The user enters e.g. "20€" in a form field and I only want to get the number "20" with stripped out Euro-sign. But the validation methods only allow checking if something is what it´s supposed to be.
I´m about to create a function in my rule-set but I´m struggling going further because what the function returns in cake context is either true or false, not a modified variable like I need ...
'rule-3' => array(
'rule' => 'checkEuro',
'message' => 'don´t need one because it should be a conversion only :-('
)
public function checkEuro($data) {
$data = str_replace('€','',$data);
return preg_replace('/[^0-9]/','', html_entity_decode($data));
}
I hope you can help.
Thanks in advance
If you only need to store the amount itself inside the database and not the euro-sign, you should strip the Euro-sign before validating.
You can do this inside the beforeValidate() callback of your model;
public function beforeValidate(array $options = array())
{
if (!empty($this->data[$this->alias]['FIELDNAME']) {
// Strip the euro-sign
// NOTE: should also take plain, non-entity € into account here?
$this->data[$this->alias]['FIELDNAME'] = str_replace(
'€', '', $this->data[$this->alias]['FIELDNAME']
);
}
return parent::beforeValidate($options);
}
(Of course, replace FIELDNAME with the actual fieldname)
After stripping the currency-symbol, validate the value using the decimal or numeric validation rule
note
If you do want to store the value including the currency-symbol, use the core money validation rule.
I am new to Cake and tried to find the best solution to retrieve a specific field belonging to an $id:
This is my view function in my Post controller
function view($id = null) {
if (!$id) {
$this->Session->setFlash(__('Invalid post', true));
$this->redirect(array('action' => 'index'));
}
$this->set('post', $this->Post->read(null, $id));
}
In the post table, there is a user_id foreign key. I need to retrieve this specific field belonging to this Post $id.
I read about functions as find('All), read() or just drop an unconventional session in the view through:
$session->write('example') = $post['Post']['user_id];
What is the best way to do this, my preference is to retrieve the field in the controller. Thanks!
CakePHP has a field function which should do just that.
$this->Post->id = $id;
$user_id = $this->Post->field('user_id');
For more information on using field, see: http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#model-field
A second option is to use the find function and returning only a few fields if you do not want the entire Post object. Also shown below is using a condition instead of setting the current Post.
$this->Post->find('first', array(
'conditions'=>array('id'=>$id),
'fields'=>array('user_id')
));
More information on find is available at: http://book.cakephp.org/2.0/en/models/retrieving-your-data.html
$this->Post->id = $id;
$this->Session->write('example',$this->Post->field('user_id'));
In CakePHP 3, you can use $this->Model->get() to get the Entity, and then reference the required field directly.
$fieldValue = $this->ModelName->get($id)->fieldName;
Try this one, since I don't know which field(s) you need I provide an example field array set using Magic Find Types:
$fields = ['title', 'body', 'created'];
$record = $this->Post->findById($id, $fields);
or multiple records
$recordSet = $this->Post->findAllByTitle('The title', $fields);
*Note the the second example doesn't make a lot of sense unless there are multiple titles with the name 'The title' in the the posts.title column.
In one of my models, I have a "LONGTEXT" field that has a big dump of a bunch of stuff that I never care to read, and it slows things down, since I'm moving much more data between the DB and the web app.
Is there a way to specify in the model that I want CakePHP to simply ignore that field, and never read it or do anything with it?
I really want to avoid the hassle of creating a separate table and a separate model, only for this field.
Thanks!
Daniel
As #SpawnCxy said, you'll need to use the 'fields' => array(...) option in a find to limit the data you want to retrieve. If you don't want to do this every time you write a find, you can add something like this to your models beforeFind() callback, which will automatically populate the fields options with all fields except the longtext field:
function beforeFind($query) {
if (!isset($query['fields'])) {
foreach ($this->_schema as $field => $foo) {
if ($field == 'longtextfield') {
continue;
}
$query['fields'][] = $this->alias . '.' . $field;
}
}
return $query;
}
Regarding comment:
That's true… The easiest way in this case is probably to unset the field from the schema.
unset($this->Model->_schema['longtextfield']);
I haven't tested it, but this should prevent the field from being included in the query. If you want to make this switchable for each query, you could move it to another variable like $Model->_schemaInactiveFields and move it back when needed. You could even make a Behavior for this.
The parameter fields may help you.It doesn't ignore fields but specifies fields you want:
array(
'conditions' => array('Model.field' => $thisValue), //array of conditions
'fields' => array('Model.field1', 'Model.field2'), //list columns you want
)
You can get more information of retrieving data in the cookbook .
Another idea:
Define your special query in the model:
function myfind($type,$params)
{
$params['fields'] = array('Model.field1','Model.field2',...);
return $this->find($type,$params);
}
Then use it in the controller
$this->Model->myfind($type,$params);
Also try containable behaviour will strip out all unwanted fields and works on model associations as well.
Containable
class Post extends AppModel { <br>
var $actsAs = array('Containable'); <br>
}
where Post is your model?
You can add a beforeFilter function in your Table and add a select to the query
Excample:
public function beforeFind(Event $event, Query $query){
$protected = $this->newEntity()->hidden;
$tableSchema = $event->subject()->schema();
$fields = $tableSchema->columns();
foreach($fields as $key => $name){
if(in_array($name,$protected)){
unset($fields[$key]);
}
}
$query->select($fields);
return $event;
}
In this excample I took the hidden fields from the ModelClass to exclude from result.
Took it from my answer to a simular question here : Hidden fields are still listed from database in cakephp 3
My debug value is set to 2, and it's displaying all the queries, except the one I need.
I have an Items controller method that is calling this method in the User model (Item belongsTo User):
function add_basic($email, $password) {
$this->create();
$this->set(array(
'email' => $email,
'password' => $password
));
if($this->save()) {
return $this->id;
}
else {
return false;
}
}
I have confirmed that $email and $password are being passed into the function correctly (and are populated with legit data). email and password are the names of the fields in the User model.
I have also confirmed that on $this->save() it is returning false, but when I view the page where this occurs, the query is not being printed in the debug, and there is no error being thrown, so I have no idea whats going wrong.
Any ideas on how I can see the error, or why the query doesn't seem to be getting executed?
It's weird, cause right after this, I have another model saving data to it in the exact same fashion, it goes off without a hitch.
This will probably give you the info you need (assuming it's not saving because of invalid data, of course):
if(!$this->save()){
debug($this->validationErrors); die();
}
Have you got a beforeValidate() or beforeSave() method in the model or app model? Ifso, are they returning true? Failing that, use a debugger, set a break point in your IDE at the top of cake/libs/models/model.php save() method and step through the code until it returns false. Failing that add die('here'); calls.
Try this:
if ($this->save()) {
return $this->id;
}
else {
var_dump($this->invalidFields());
return false;
}
#cakePHP 3.6 and above: By default, the request data will be validated before it is converted into entities. If any validation rules fail, the returned entity will contain errors. It can be read by getErrors() method.
The fields with errors will not be present in the returned entity:
Say, you have an entity
use App\Model\Entity\Article;
$entity = $this->ModelName->newEntity([
'id' => 1,
'title' => 'New Article',
'created' => new DateTime('now')
]);
$result = $this->ModelName->save($entity);
\Cake\Log\Log::debug($entity->getErrors());
If you’d like to disable validation when converting request data, set the validate option to false:
$article = $articles->newEntity(
$this->request->getData(),
['validate' => false]
);
Ref: https://book.cakephp.org/3/en/orm/validation.html
Make sure to check your tables:
Does ID have auto increment enabled?
Is id your primary key?
the auto_increment issues killed me.
Easy way to check: if any of your rows have ID = 0, auto_increment is likely disabled.
CakePHP 3.6
$entity = $this->Model->newEntity([
'account_id' => $id,
'gallery_id' => $gallery_id
]);
$result = $this->Model->save($entity);
print_r($entity->getErrors());
The other situation where CakePHP fails to report any $this->Model->validationErrors and no other errors is potentially when $this->request->data isn't as Cake expects and is simply ignoring your data, not saving, no validation errors. For example if your data was provided by DataTables you might see this format $this->request->data[0]['Model']['some_field'].
$this->Model->save($this->request->data[0]) will work however.