Sep262007

CakePHP 1.2 tip of the day: be mindful of Model::set

Even if Model::set seems to have a defined functionality, it wouldn’t be insane that you get stuck with a common developer mistake: forget what you should expect of a method. Consider the following code running on a controller (where Model is an example model, and assume validates() always returns true):

$this->data = array('Model' => array('field1' => 'value1', 'field2' => 'value2'));
if ($this->Model->set($this->data) && $this->Model->validates()) {
	unset($this->data['field1']);
	$this->Model->set($this->data);
	$this->Model->save();
}

Would you be expecting that field1 gets saved to the Model table, or not? The answer is: it will, since calling Model::set() WILL NOT empty your previously set data, but instead do a merge (so does the Controller::set method, so it’s not a CakePHP mistake, but a common coder’s misunderstanding). The solution is: if you need to set your model data making sure that you start with a “fresh” copy of the model instance, then change your set() call to create(), like so:

$this->data = array('Model' => array('field1' => 'value1', 'field2' => 'value2'));
if ($this->Model->set($this->data) && $this->Model->validates()) {
	unset($this->data['field1']);
	$this->Model->create($this->data);
	$this->Model->save();
}


Leave a Comment

6 Comments to "CakePHP 1.2 tip of the day: be mindful of Model::set"

  1. Sep302007 at 9:04 am

    Daniel Hofstetter [Visitor] wrote:

    Well, I think if something is a common misunderstanding then it is probably the framework’s fault. If I see a set method then I expect it sets the provided data, but not that it merges them with some existing data (then the method should be named “add” for example). So to me the set method you showed simply violates the convention for set methods.

  2. Sep302007 at 2:40 pm

    mariano.iglesias [Member] wrote:

    @Daniel: I completely disagree. But then again you know that already, and for some reason you are only but complaining lately so I think there’s no need for a debate. In any way, Model::set behaves exactly as Controller::set. And what you are asking is that in controller if you do:

    $this->set(‘var1′, ‘value1′);

    and then later on:

    $this->set(‘var2′, ‘value2′);

    Then only var2 will be available in the view. Ask ANY baker in the world and they’ll say THAT’S CRAP, regardless of what YOU deem as adequate for the method.

  3. Oct012007 at 6:05 am

    Daniel Hofstetter [Visitor] wrote:

    That’s not what I am saying. What I am saying is that I don’t expect that the arrays get merged if I have something like:

    $this->set($arrayA);
    $this->set($arrayB);

    The semantic is not correct and so people get it wrong. But if I have something like

    $this->set(‘var1′, $value1);
    $this->set(‘var2′, $value2);

    then I expect both variables in the view.

    If you want to see my comments as complaining, then see it as complaining, even though it is meant as feedback.

  4. Oct182007 at 5:58 pm

    PHPSC [Visitor] wrote:

    I have to say i agree with Daniel. If there is something which is generally misunderstood by everyone then maybe it should be named better.

    Regarding using the “create” function that can be a problem when u want to update the data after validation instead of inserting a new record. Thats because in 1.2 “create” also retrieves the default values set for a field from the table definition. So it will update a field with default value even if i don’t want to. I am still an amateur in cakePHP so please correct me if i am wrong.

  5. Jun212011 at 10:27 am

    Ahmad wrote:

    u save my live :)

  6. Dec162012 at 11:39 am

    cakeUser wrote:

    old post but a damn good trick, this explains to me a lot.
    Thanx

 
Powered by Wordpress and MySQL. Clauz's design for by Cricava