Reputation: 429
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
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
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
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:
all other available eventes: http://phalcon-php-framework-documentation.readthedocs.org/en/latest/reference/models.html#events-and-events-manager
Upvotes: 0