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

Extending a Model

Hi all,

First of all, thanks for all the hard work. Love Phalcon and we're just starting to use it on a big project. There is one problem I can't easily work around.

How would one make a child-parent relationship between Phalcon MVC models? This is a DB schema I have in mind:

```sql explain show; +---------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+--------------+------+-----+---------+-------+ | id | int(11) | NO | PRI | NULL | | | length | int(11) | NO | | NULL | | | title | varchar(100) | NO | | NULL | | +---------+--------------+------+-----+---------+-------+

explain show_episode; +---------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+--------------+------+-----+---------+-------+ | show_id | int(11) | NO | PRI | NULL | | | season | int(11) | NO | | NULL | | | episode | int(11) | NO | | NULL | | +---------+--------------+------+-----+---------+-------+```

Each element in show_episode is also present in show table, however there are show records which are only present in show.

The idea is to have two Phalcon Model classes:

```php class Show extends Phalcon\Mvc\Model { public $id; public $length; public $title; }

class ShowEpisode extends Show { public $season; public $episode; }``` How would I need to configure those models to be able to retrieve and save episode records like this:

```php// retrieve $episode = ShowEpisode::findFirst(array("id"=>333)); echo $episode->season; echo $episode->title;

// save $episode->title = "New Title"; $episode->season = 3; $episode->save();```

Thanks for the help!

Best, Matej



51.2k

You don't need to extend. Leave them as 2 separate models:

 class Show extends Phalcon\Mvc\Model
{
  public $id;
  public $length;
  public $title;

  public function initialize()
  {
        $this->hasMany('id', 'ShowEpisode', 'show_id', array(
            'alias' => 'episodes'
        ));
  }
}

class ShowEpisode extends Phalcon\Mvc\Model
{
  public $season;
  public $episode;

  public function initialize()
  {
        $this->belongsTo('show_id', 'Show', 'id', array(
            'alias' => 'show'
        ));
  }
}

Hi Chalin,

thank you for your answer. It seems that you misunderstood the question, though. The point of this (example) DB schema is that each episode is also a show.

So, when you create a new episode, you should be able to do it like that:

$episode = new ShowEpisode();
$episode->title = "Episode title";
$episode->length = 30;
$episode->season = 1;
$episode->episode = 3;
$episode->save();

This should result in two records, one in "show" and one in "show_episode" table. It is a 0..1 to 1 relationship.

Until I figure out a better way, I solved it by placing this code into the child model. Obviously it is bad in terms of optimisation and it doesn't solve fetching, just the saving part.


class ShowEpisode extends Show
{
   /* ... */

    protected function _getShow()
    {
        return $this->getRelated("show");
    }

    public function initialize()
    {
    $this->hasOne("id", "Show", "id", array("alias"=> "show", "foreignKey"=>true));
        parent::initialize();
    }

    public function save($data=null, $whiteList=null)
    {
        $reflect = new \ReflectionClass($this);
        $properties = $reflect->getProperties();

        // create parent object
        $show = $this->_getShow();

        if (!$show) {
            $show = new Show();
        }

        // assign child variables to parent
        foreach ($properties as $prop) {
            if ($prop->class == "Show") {
                $show->{$prop->name} = $this->{$prop->name};
            }
        }

        $show->save();
        $this->id = $show->getId();

        parent::save($data, $whiteList);
    }
}

Are there any other ways to achieve the same?