I'm confused. Please have a look at the code below. It's the default robots/parts setup, with a hasManyToMany from robots to parts. I can add parts to a robot just fine. But if I query the parts just before adding new parts, nothing happens. I commented the code to illustrate what goes wrong. I'm not sure if this is expected behaviour or a bug related to i.e. the Model's dirtyState.
The models are stored in MySQL tables with cascading foreign keys. Here are the 3 model classes:
These are the model classes and my test code:
<?php
class Robot extends \Phalcon\Mvc\Model
{
public $id;
public $name;
public function initialize()
{
$this->setSource('robots');
$this->hasManyToMany('id', RobotsParts::class, 'robot_id', 'part_id', Part::class, 'id', ['alias' => 'parts']);
}
}
<?php
class RobotsParts extends \Phalcon\Mvc\Model
{
public $id;
public $robot_id;
public $part_id;
}
<?php
class Part extends \Phalcon\Mvc\Model
{
public $id;
public $name;
public function initialize()
{
$this->setSource('parts');
}
}
<?php
use Phalcon\Cli\Task;
class MainTask extends Task
{
public function initAction()
{
Robot::find()->delete();
Part::find()->delete();
// RobotsParts has cascading foreign keys,
// so they will be deleted by MySQL.
$part1 = new Part;
$part1->name = "arm";
$part2 = new Part;
$part2->name = "leg";
$robot = new Robot;
$robot->name = "bob";
$robot->parts = [$part1, $part2];
$robot->save(); // Works as expected
}
public function addAction()
{
$part3 = new Part;
$part3->name = "hand";
$part4 = new Part;
$part4->name = "foot";
$robot = Robot::findFirstByName("bob");
$robot->parts = [$part3, $part4];
$robot->save(); // Works as expected, Bob now has 4 parts.
}
// Basically the same as addAction()
public function bugAction()
{
$part5 = new Part;
$part5->name = "finger";
$part6 = new Part;
$part6->name = "toe";
$robot = Robot::findFirstByName("bob");
$temp = $robot->parts; // Query the parts, for some reason. Not used here.
$robot->parts = [$part5, $part6];
var_dump($robot->save()); // Returns true, but nothing is added to the db.
foreach ($robot->getMessages() as $message) {
printf("%s\n", $message); // No messages either...
}
}
public function testAction()
{
$this->initAction();
$this->addAction();
$this->bugAction();
$robot = Robot::findFirstByName("bob");
foreach ($robot->parts as $part) {
printf("%s (id %d)\n", $part->name, $part->id);
}
}
}
$ php app/cli.php test
/home/gerben/public_html/link/app/tasks/MainTask.php:52:
bool(true)
arm (id 68)
leg (id 69)
hand (id 70)
foot (id 71)
Why are the $part5 and $part6 ignored? Is this a bug or expected behavior?