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

Conditional related models

I have 1 table/model: Persons. Each Person is of a type ("student","employee","instructor"). Each of these types has extra pieces of information, so I have person_student, person_employee, person_instructor tables (and associated models) as well.

I know I can set up a relationship between my Person model and PersonStudent/PersonEmployee/PersonInstructor model, but I was wondering if there was a way in the ORM to set up a relationship so that I could refer to the additional models using 1 single alias, regardless of what additional model is actually being related.

So for example, if I have a student record, I'd like to be able to reference $Person->Additional and have Additional refer to a PersonStudent record. Similarly if I have an employee record, I'd like to have $Person->Additional refer to a PersonEmployee record.

I'm pretty sure I could do this in straight PHP, by overriding __get(), or possibly just using $Person->Additional(), and having the Additional() method reference the respective objects. Still - I'm wondering if Phalcon has anything that could help me.

edited Jul '15

Without seeing your schema, the only way I can think of this working at the moment would be to set the property up on afterFetch(); eg.

class Person extends \Phalcon\Mvc\Model{

    //...

    public function afterFetch()
    {
        switch($this->type){
            case 'student':
                $this->Additional = $this->getRelated('PersonStudent', ['limit' => 1])->getFirst();
                break;

            case 'employee':
                $this->Additional = $this->getRelated('PersonEmployee', ['limit' => 1])->getFirst();
                break;

            case 'instructor':
                $this->Additional = $this->getRelated('PersonEmployee', ['limit' => 1])->getFirst();
                break;
        }
    }
}

Your solution looks like it would work pretty well. I would need to have matching logic in beforeSave() as well - but that might work.

In case you have a better idea, here's the representative schema:

person

+--------------+-------------------------------------------------------------+------+-----+---------+-------+
| Field        | Type                                                        | Null | Key | Default | Extra |
+--------------+-------------------------------------------------------------+------+-----+---------+-------+
| username     | varchar(20)                                                 | NO   | PRI |         |       |
| gender       | enum('M','F')                                               | YES  |     | NULL    |       |
| first_name   | varchar(30)                                                 | YES  |     | NULL    |       |
| middle_name  | varchar(30)                                                 | YES  |     | NULL    |       |
| last_name    | varchar(30)                                                 | YES  |     | NULL    |       |
| phone_number | varchar(15)                                                 | YES  |     | NULL    |       |
| email        | varchar(255)                                                | YES  |     | NULL    |       |
| role         | enum('student','instructor','supervisor','contact','staff') | YES  |     | NULL    |       |
| active       | tinyint(1)                                                  | NO   |     | 1       |       |
+--------------+-------------------------------------------------------------+------+-----+---------+-------+

person_student

+-----------------+-------------+------+-----+---------+-------+
| Field           | Type        | Null | Key | Default | Extra |
+-----------------+-------------+------+-----+---------+-------+
| username        | varchar(20) | NO   | PRI |         |       |
| csl_certificate | tinyint(1)  | YES  |     | 0       |       |
| image_consent   | tinyint(1)  | YES  |     | 0       |       |
+-----------------+-------------+------+-----+---------+-------+

person_student.username has a foreign key constraint to person.username.