hlasso
hlasso

Reputation: 429

PhalconPHP Framework - How to update a model object and the related object

I am working with PhalconPHP and so far I have had little problems.

The framework is very good.

However, I've run into a problem that I haven't been able to sort out. It's probably a very simple thing but I've been running in circles, and couldn't find any reference to this problem.

The problem is I cannot update a model object if I also update a related entity.

For example, let's suppose I have a couple of model classes.

Contact:

class Contact extends \Phalcon\Mvc\Model
{
    public function initialize()
    {
        $this->belongsTo('email_id', 'Email', 'id', ['alias' => 'Email']);
    }
}

And Email:

class Email extends \Phalcon\Mvc\Model
{
    public function initialize()
    {
        $this->hasMany('id', 'Contact', 'email_id', ['alias' => 'Contacts']);
    }
}

When I try to create a new Contact and Email the following works:

$contact = new Contact();
// ... assign other fields here (i.e. name)
$email = new Email();
// ... assign other email fields here (i.e. address)
$contact->setEmail($email); // or $contact->email = $email;
$contact->save();
// record created

However, when I try to update a Contact and change the Email relation, the information is just not updated:

// Only update other fields
$contact->name = 'Some other name';
$contact->save();    // This works

// Update the related object
$contact->name = 'A new name';
$contact->setEmail($anotherValidEmail);
$contact->save();    // This doesn't work! Not even the name field is updated

I have tried using update() instead of save().

I have tried using $contact->email = $newEmailObject as well, but I get the same results.

Have anyone ran into this problem? What am I doing wrong?

I'm using Mac OS X, PhalconPHP 1.2.3

I've also tested it on Windows 8, with PhalconPHP 1.1.0

Any help is appreciated.

updated

I have printed the results of $contact->getMessages() after save(), but I get no results. It's as if save() was successful, however, no SQL statement is executed.

LAST UPDATE: Problem replicated and Workaround found!

We have been able to replicate the problem. We are doing this:

$contact = Contact::findFirst(123);
if ($contact->email->emailaddress != $newaddress) {
    $email = new Email();
    $email->emailaddress = $newaddress;

    $contact->email = $email;
    $contact->save();
}

This DOES NOT WORK! Once we compare the emailaddress field from the email related object, to the string for the new address saving does not work.

However, if we modify the code a little bit and do this:

  $contact = Contact::findFirst(123);
  if ($contact->email->emailaddress != $newaddress) {
    $email = new Email();
    $email->emailaddress = $newaddress;

    // Load the record (again!)
    $contact = Contact::findFirst(123);
    $contact->email = $email;
    $contact->save();
  }

This actually works.

I guess that loading the related object affects the ability to update that particular field, and finding the contact object again, flushes the related object.

So, we have a workaround that I hope will help other people facing the same problem.

Upvotes: 6

Views: 10681

Answers (3)

user2877596
user2877596

Reputation: 31

When you use $contact->setEmail($anotherValidEmail);, you must have a set and get method in the Contact model Contact. For example:

Class Contact
{

  public $email;

  public function setEmail($email)
  {
  }
  public function getEmail()
  {
    return $this->email
  }
}

Upvotes: 1

Zahid Khowaja
Zahid Khowaja

Reputation: 66

Actually, your model should look like as below

class Contact extends \Phalcon\Mvc\Model
{

  public $id;
  public $name;
  public $email;

  public function initialize()
  {
     $this->belongsTo('email_id', 'Email', 'id', ['alias' => 'Email']);
  }

  public function columnMap()
  {
      return array(
        'id' => 'id', 
        'name' => 'name', 
        'email' => 'email'
      );
  }

}

Then,

$contact = new Contact();

$success = $contact->save($this->request->getPost(), array('name', 'email'));

Upvotes: 0

Lukas Liesis
Lukas Liesis

Reputation: 26403

there is an answer in official doumentation, you should try it (add flag ACTION_CASCADE):

<?php

namespace Store\Models;

use Phalcon\Mvc\Model,
    Phalcon\Mvc\Model\Relation;

class Robots extends Model
{

    public $id;

    public $name;

    public function initialize()
    {
        $this->hasMany('id', 'Store\\Models\Parts', 'robots_id', array(
            'foreignKey' => array(
                'action' => Relation::ACTION_CASCADE
            )
        ));
    }

}

http://docs.phalconphp.com/en/latest/reference/models.html#cascade-restrict-actions

The above code set up to delete all the referenced records (parts) if the master record (robot) is deleted.

You can also use beforeDelete or afterDelete functions and add any code required:

http://phalcon-php-framework-documentation.readthedocs.org/en/latest/reference/models.html#deleting-records

all other available eventes: http://phalcon-php-framework-documentation.readthedocs.org/en/latest/reference/models.html#events-and-events-manager

Upvotes: 0

Related Questions