We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Two ORM issues

There are 2 issues with ORM that have been bothering me for a while and I'm wondering if there's any solution.

1) toArray() method does not always set the ID's of the related records. Here's the entire code to reproduce the problem:

<?php

$di = new Phalcon\DI\FactoryDefault();
$di->set('db', function() {
    return new \Phalcon\Db\Adapter\Pdo\Mysql(array(
        "host" => 'localhost',
        "username" => 'root',
        "password" => '',
        "dbname" => 'testing'
    ));
    });

class TheParent extends \Phalcon\Mvc\Model
{
    public function initialize()
    {
        $this->hasMany('ID', 'Child', 'parentID', array('alias' => 'Children'));
    }
}

class Child extends \Phalcon\Mvc\Model
{
    public function initialize()
    {
        $this->belongsTo('parentID', 'TheParent', 'ID', array('alias' => 'Parent'));
    }
}

$parent = new TheParent();
$parent->name = 'The parent';
$parent->save();

$child = new Child();
$child->parent = $parent;

var_dump('Parent', $parent->toArray());

var_dump('Child', $child->toArray());

Output:

string(6) "Parent"
array(2) {
  ["ID"]=>
  string(1) "9"
  ["name"]=>
  string(10) "The parent"
}
string(5) "Child"
array(3) {
  ["ID"]=>
  NULL
  ["parentID"]=>
  NULL
  ["name"]=>
  NULL
}

Expected output for the second var_dump would be:

string(5) "Child"
array(3) {
  ["ID"]=>
  NULL
  ["parentID"]=>
  string(1) "9"
  ["name"]=>
  NULL
}

Any reason why the parentID field would remain NULL?

The second issue is adding related records. If I add this code after what is posted above:

$parent->children[] = $child;

I get this exception: Fatal error: Uncaught exception 'Phalcon\Mvc\Model\Exception' with message 'Cursor is an immutable ArrayAccess object' in /var/www/test.php:42 Stack trace: #0 /var/www/test.php(42): Phalcon\Mvc\Model\Resultset->offsetSet(NULL, Object(Child)) #1 {main} thrown in /var/www/test.php on line 42

Also, here's the SQL code for setting up the database tables:

CREATE TABLE IF NOT EXISTS `child` (
  `ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `parentID` int(10) unsigned NOT NULL,
  `name` varchar(100) NOT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

CREATE TABLE IF NOT EXISTS `the_parent` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) NOT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=10 ;


125.8k
Accepted
answer

Issue 1: I don't know, but I'd guess it's because of the fact you haven't saved the record yet. Really all you've done is set the child's parent property. I would guess Phalcon doesn't do the work of setting the parentID property until the child is saved.

Issue 2: I've run into this in the past. I think you have to do this:

$children = [$child];
$parent->children = $children

Finally - 2 questions in 1 post isn't ideal as the conversation could get hard to follow. In the future, please put each question in a separate post. I understand they're related, but they are separate issues. We don't mind you posting multiple times with different problems.

Thank you for replying. Yes, I should have made 2 threads, if the moderators are up to splitting them, I won't mind. My apologies.

Issue 1: I specifically do not want to save the record in this case. I guess I'll have to override the toArray() function to check for missing related record ID's.

Issue 2: OK, I see. After playing with it for a bit, I realized that assigning a new array with one item will append it to the list of children and won't affect existing children.

Thank you for replying. Yes, I should have made 2 threads, if the moderators are up to splitting them, I won't mind. My apologies.

Phosphorum is really young, so moderation tools like that don't exist yet. Not a big deal - just education.

Issue 1: I specifically do not want to save the record in this case. I guess I'll have to override the toArray() function to check for missing related record ID's.

Why don't you just set $child->parentID?

Setting parentID appears to work, although it does seem more like a workaround than a solution. But it would work for now, so thank you for this suggestion.