You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The problem was when model used more than one belongs to relations with virtual foreign keys. In some cases, when saving the model, check of the first virtual foreign key influences the check of other key. And instead of standard Phalcon message generated on the model, PDOException is thrown with error like this:
PDOException: SQLSTATE[23503]: Foreign key violation: 7 ERROR: insert or update on table <table-name> violates foreign key constrain
Here are the steps to reproduce this behaviour. It's the minimal example I could get to work.
Let's have these 3 tables:
CREATE TABLE public.robot (
id SERIAL,
PRIMARY KEY (id)
);
CREATE TABLE public.head (
id SERIAL,
PRIMARY KEY (id)
);
CREATE TABLE public.part (
id SERIAL,
robot_id INT,
head_id INT,
PRIMARY KEY (id),
FOREIGN KEY (robot_id) REFERENCES public.robot(id) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY (head_id) REFERENCES head(id) ON DELETE CASCADE ON UPDATE CASCADE
);
And 3 models for these tables:
_Robot.php_
<?php
namespace App\Model;
class Robot extends \Phalcon\Mvc\Model
{
protected $id;
public function initialize()
{
$this->setSchema('public');
$this->setSource('robot');
}
public function columnMap()
{
return [
'id' => 'id',
];
}
public function setId($value)
{
$this->id = $value;
return $this;
}
public function getId()
{
return $this->id;
}
}
_Head.php_
<?php
namespace App\Model;
class Head extends \Phalcon\Mvc\Model
{
protected $id;
public function initialize()
{
$this->setSchema('public');
$this->setSource('head');
}
public function columnMap()
{
return [
'id' => 'id',
];
}
public function setId($value)
{
$this->id = $value;
return $this;
}
public function getId()
{
return $this->id;
}
}
and _Part.php_
<?php
namespace App\Model;
class Part extends \Phalcon\Mvc\Model
{
protected $id;
protected $robotId;
protected $headId;
public function initialize()
{
$this->setSchema('public');
$this->setSource('part');
$this->belongsTo(
'robotId',
'\App\Model\Robot',
'id',
[
'alias' => 'robot',
"foreignKey" => [
"allowNulls" => true,
"message" => "Robot does not exists"
]
]
);
$this->belongsTo(
'headId',
'\App\Model\Head',
'id',
[
'alias' => 'head',
"foreignKey" => [
"allowNulls" => true,
"message" => "Head does not exists"
]
]
);
}
public function columnMap()
{
return [
'id' => 'id',
'robot_id' => 'robotId',
'head_id' => 'headId',
];
}
public function setId($value)
{
$this->id = $value;
return $this;
}
public function getId()
{
return $this->id;
}
public function setRobotId($value)
{
$this->robotId = $value;
return $this;
}
public function getRobotId()
{
return $this->robotId;
}
public function setHeadId($value)
{
$this->headId = $value;
return $this;
}
public function getHeadId()
{
return $this->headId;
}
}
And here comes the funny part. Let's have EXACTLY these records in the database:
Robot:
1/ id = 1
2/ id = 2
Head:
1/ id = 1
2/ id = 2
Part:
1/ id = 1, robot_id = 1, head_id = NULL
The NULL in the part table is pretty important.
Now, let's have this controller:
public function testAction()
{
$part = \App\Model\Part::findFirst();
$part->setHeadId(9999); // Invalid ID
if (!$part->save()) {
return [
'error' => $part->getMessages()[0]->getMessage()
];
}
return [
'error' => false
];
}
When head_id is originally NULL, PDOException with foreign key violation message is thrown.
But when you use this call instead, everything is fine.
$part->setRobotId(9999); // Also invalid ID
When you change the order of the calls to the belongsTo(...) methods and you register first the relation for the head table it works as well (that should be the problem of assigning value to validateWithNulls only once outside of the for loop).
The text was updated successfully, but these errors were encountered:
Hi,
I am reopening the issue for 3.0.x branch.
The problem was when model used more than one belongs to relations with virtual foreign keys. In some cases, when saving the model, check of the first virtual foreign key influences the check of other key. And instead of standard Phalcon message generated on the model, PDOException is thrown with error like this:
Here are the steps to reproduce this behaviour. It's the minimal example I could get to work.
Let's have these 3 tables:
And 3 models for these tables:
_Robot.php_
_Head.php_
and _Part.php_
And here comes the funny part. Let's have EXACTLY these records in the database:
The NULL in the part table is pretty important.
Now, let's have this controller:
When head_id is originally NULL, PDOException with foreign key violation message is thrown.
But when you use this call instead, everything is fine.
When you change the order of the calls to the belongsTo(...) methods and you register first the relation for the head table it works as well (that should be the problem of assigning value to
validateWithNulls
only once outside of the for loop).The text was updated successfully, but these errors were encountered: