Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

Stuck at storing related records with bidirectional relations

Hello,

I'm currently stuck at storing related records and I'll be glad for every idea that might help solve my issue.

The logic behind this is almost self-explaining:
Users can send in questions which can be answered by experts.
Users <> Questions <> Answers <> Experts

Users.php

<?php
class Users
{
    public $id;
    public $name;
    public $email;

    // Initialize
    public function initialize()
    {
        // Establish relation to questions model
        $this->hasMany('id', 'Questions', 'userId', array(
            'alias' => 'questions'  
        ));

    }

}

Questions.php

<?php
class Questions
{
    public $id;
    public $userId;
    public $text;

    // Initialize
    public function initialize()
    {
        // Establish relation to users model
        $this->belongsTo('userId', 'Users', 'id');
        $this->hasOne('userId', 'Users', 'id', array(
            'alias' => 'user'
        ));

        // Establish relation to answers model
        $this->belongsTo('id', 'Answers', 'questionId');
        $this->hasOne('id', 'Answers', 'questionId', array(
            'alias' => 'answer'
        ));

    }

}

Answers.php

<?php
class Answers
{
    public $id;
    public $questionId;
    public $expertId;
    public $text;

    // Initialize
    public function initialize()
    {
        // Establish relation to experts model
        $this->belongsTo('expertId', 'Experts', 'id');
        $this->hasOne('expertId', 'Experts', 'id', array(
            'alias' => 'expert'
        ));

        // Establish relation to questions model
        $this->belongsTo('questionId', 'Questions', 'id');
        $this->hasOne('questionId', 'Questions', 'id', array(
            'alias' => 'question'
        ));

    }

}

Experts.php

<?php
class Experts
{
    public $id;
    public $firstName;
    public $lastName;
    public $nickname;
    public $email;

    // Initialize
    public function initialize()
    {
        // Establish relation to Questions model
        $this->hasMany('id', 'Answers', 'expertId', array(
            'alias' => 'answers'
        ));

    }

}

The following code is adapted from the documentation found at http://docs.phalconphp.com/en/latest/reference/models.html#storing-related-records
but obviously doesn't work…

<?php
$user = Users::findFirstById(1);

$question = new Questions();
$question->text = 'Lorem ipsum';
$question->user = $user;

if (!$question->save())
{
    foreach($question->getMessages() as $message)
    {
        echo $message->getMessage() . '<br>';

    }

}

Instead it returns the following message:

userId is required

Same happens If I try to save other related objects and the worst thing I found out is, that the following lines both store new records for Experts as well as Questions instead of referencing the relations as virtual foreign keys:

<?php
$question  = Questions::findFirstById(1);
$expert = Experts::findFirstById(1);

$answer = new Answer();
$answer->question = $question;
$answer->expert = $expert;
$answer->text = 'Hello world';

if (!$answer->save())
{
    foreach($answer->getMessages() as $message)
    {
        echo $message->getMessage() . '<br>';

    }

}

Any ideas of what's wrong with my code?

Thanks,
Cedric

Try this:

class Questions
{
    public $id;
    public $userId;
    public $text;

    // Initialize
    public function initialize()
    {
        // Establish relation to users model
        $this->belongsTo('userId', 'Users', 'id', [
            'alias' => 'users'
        ]);

        // Establish relation to answers model
        $this->hasOne('id', 'Answers', 'questionId', array(
            'alias' => 'answer'
        ));
    }

}

A question belongs to an user but does not own it, I think so

edited Mar '15

Thanks I'll try that, but I'm sure this will break my bidirectional attempt to access all Questions via Users object and vice versa. The documentation clearly stated that bidirectional access is possible.

Edit: Still not working, same error message as before: userId is required

You are right, I did not know.

I ve revised the code and seems fine... are Users.id and Questions.userId in your database the same field type? and have you defined all the properties in models?

The message is generated here https://github.com/phalcon/cphalcon/blob/master/ext/mvc/model.c#L3221, I think.



1.3k
Accepted
answer
edited Mar '15

Okay, I got it. I "accidentially" used the full namespace and model name in my hasMany() and belongsTo() relation statements instead of the plain model name. For simplification, I haven't put this into my examples above.

Before (won't work):

$this->hasMany('id', 'My\Namespace\Questions', 'users_id', array('alias' => 'questions'));

After (works):

$this->hasMany('id', 'Questions', 'users_id', array('alias' => 'questions'));