I am writing a function within the php of the model. Is there any issue with using
$this->field('something)
while inside the model? I can use other things like $this->saveField(...) fine but for some reason this is not returning me the value in the table correctly. Just wanted to make sure, thanks!
You have to specify the conditions first, like so:
$this->field('field_name', $conditions);
Or, I think you can also try setting the id first
$this->id = $id;
$this->field('field_name');
Related
I want to create a whitelist of fields that I want to be updatable in CakePHP. I know that I can pass a fieldList array in the call to Model::save(), but this isn't what I'm looking for. What I want is that every model "publish" a list of the valid fields, so if I call the Model::save() method without a fieldList and with data that mustn't be updatable (like the ownerId) this won't be updated.
What can I do to get this behavior? Maybe override the Model::save method in every Model to call at the "original" Model::save with the whitelist? I think this is a good idea, because I don't pollute all the controllers with lots of duplicated whitelists...
Thanks for your help!
Well, thanks you all for your answers, but I was wrong: I don't need to add this functionality.
The problem I was trying to solve was a security problem, I was trying to avoid form tampering (I've discovered the name just now), and as I am a novice CakePHP user, I didn't know that CakePHP already manages this problem.
The answer to my question is very easy: I must use CakePHP's Security Plugin and use the Form Tampering prevention (http://book.cakephp.org/2.0/en/core-libraries/components/security-component.html#form-tampering-prevention).
Can‘t say I’ve ever needed to do this in CakePHP, but CakePHP only saves the fields you pass it.
If you really need to create a white-list and you’re certain you only ever want these fields saving and never any others in your database (although I don’t understand why you have columns for them if you never touch them) then you could emulate this behavior in a model callback method:
<?php
class User extends AppModel {
public function beforeSave($options = array()) {
$whitelist = array('first_name', 'last_name', 'email');
foreach ($this->data[$this->alias] as $field => $value) {
if (!in_array($field, $whitelist)) {
unset($this->data[$this->alias][$field]);
}
}
return true;
}
}
This will just unset any data not in the $whitelist array, but if you really don’t want a column being updated then don’t pass a value for it.
Any ideas on how to debug a modified field that is not being updated? The created field works fine.
I'm not sure what code you would need to look at so let me know!
Thanks
Like Anh Pham said, the modified and created field need to be DATETIME and they also need to default to NULL, as explained in the CakePHP book about the subject.
Most likely you are overwriting the field, unset the field from the object before saving it like this:
unset($user['User']['modified']);
Now you can save it:
$this->User->save($user);
You should try checking if you didn't use
$this->ModelName->read(NULL, $id);
before saving your data, if you think you didn't - double check it
That field should be named 'modified' with 'datetime' type. Cake should update the field automatically for you. If you want to check, just query it, or look into the database.
I got the same problem today and found out the modified field is only updated if any changes have been made, otherwise the field will not be touched.
The problem might also arise if you use manual update queries. The field is updated only when you use Cake's own functions.
In AppModel.php, just write the following code.
public function beforeSave($options = array()) {
parent::beforeSave();
if (isset($this->data[$this->alias]['modified'])) {
unset($this->data[$this->alias]['modified']);
}
if (isset($this->data[$this->alias]['created'])) {
unset($this->data[$this->alias]['created']);
}
}
This will work for all models. But we can do that for individual MODELS too.
Since we have used parent::beforeSave(); as our first line therefore this can be overwritten in each individual MODEL.
Thanks to inheritance.
How can I filter Results by County,District,City with dropdown select.
Is there a way to do it in Cake way, because currently I'm doing it classic way, by passing Id to url, like:
/sort/county_id/1/district_id/5
But this is very bad hack, because I have to explode $this->here and not good thing. I don't know if there is uri class like in codeigniter, so I can play with $this->uri->segment().
In fact my problem is that I need to see if isset then pass it.
Have you considered named parameters?
Add/remove Cake named URL parameter for a link
I want to create a model that has SOME attributes that are not stored in a database. For example, I want to maintain an "age" field in the model, but I only store birthday information in the database (I can calculate "age" once the DOB info has been loaded). I tried adding a simple attribute to a model extension, but as far as I can tell, it's ignored by CakePHP. What's the proper way to go about accomplishing this?
I'm a CakePHP novice, so forgive me if I'm missing something obvious.
I'd do it using the afterFind callback method in the model.
It's been a while since I dealt with Cake, but why not just implement a getAge() method?
If you are using CakePHP 1.3, you could use the 'virtual field':
http://book.cakephp.org/view/1608/Virtual-fields
[Cookbook 3.7.10]
[edit] It also works in CakePHP 2.x:
http://book.cakephp.org/2.0/en/models/virtual-fields.html
The main advantage of this approach is that the virtual field is added in the model. That way, the MVC principles are respected.
example (MySQL):
var $virtualFields = array(
'age' => "YEAR(NOW()) - YourModelHere.dob"
);
There are two ways of doing it with cake.
Use virtual fields http://book.cakephp.org/2.0/en/models/virtual-fields.html
Use call back function afterFind() http://changelog.in/2012/07/alternative-to-cakephps-virtual-fields-which-is-far-less-restrictive/
Use the class Cache:
$parametrs = array('age'=>21, 'name'=>'aziz');
Cache::write('myOptions', $parameters);
Cache::read('myOptions');
I'm using CakePHP 1.2 and I'm just wondering if there is any side affect on passing the $this->data to the View from the Controller.
Ex:
// inside PostsController, I have this code:
$this->data['Posts'] = $this->Post->find('all');
instead of :
$posts = $this->Post->find('all');
$this->set(compact('posts'));
// inside the /posts/view, I access it like this:
<?php foreach ($this->data['Posts'] as $post) {....};?>
By doing this, I skipped the $this->set() from the controller all together. Does this violate any MVC pattern or any security issue that I might have overlook? I saw that using the Auth Component, $this->data contains the [_Token] array.
Thanks
You need to be aware of the different places that Cake Helpers automagically look for data, since that is were it makes a real difference. The Form Helper will fill in fields automatically based on the contents of $this->data. That's how form data persists when validation fails. OTOH, a <select> elements options array is automatically taken from the pluralized field name,
e.g. $form->select('Model.foo_id') will take its options from $foos if set.
As such, $this->data has its special place and shouldn't be used lightly, just as named variables have their use and shouldn't be ignored. Use both as appropriate. If you don't want to auto-set Form Helper content, set() your variables. IMHO it's also more readable to assign a variable name that hints at the data it contains. All your views operating on $this->data is less clear than one view operating on $foo and another on $bar.
In CakePHP 2.x you should use $this->request->data instead if plain $this->data, otherwise you might end up getting this error:
Indirect modification of overloaded property View::$data has no effect
$controller->data is meant for data posted to the control from view file.
$view->data is for general data.
I would avoid doing it to keep myself sane. besides you are typing more in view.
There is no good reason for setting $this->data directly except when working with forms.
Why break convention - Controller:set is there for a reason. If you want to pass data to the view for display or display logic purposes you should use the function provided instead of trying to co-opt Controller:data for unintended purposes.
Everything is easier from within CakePHP if you follow the rules and do things the expected, correct way.
In cakephp version 2.*, error occurs when you try to set data on $this->data