How to deal with inheritance in models

Hi everyone,

I was wondering what the prefered way is of dealing with inheritance structures in models.

for example may have a site the administrates videos and pictures. both would extend from content items.

in ContentItem I would store width, height and filesize as these attributes are common to both types. A video would for exapmle also have duration implemented.

Is there a way to implement class table or single table inheritance with Yii?

thanks

Marc

I don't understand what you're going to approach, but you can do something like this with your models:

POJO (Plain Old Java Objects) by extending CActiveRecord.

ContentItem class:

<?php


class ContentItem extends CActiveRecord


{


	public static function model($className=__CLASS__)


	{


		return parent::model($className);


	}





	public function tableName()


	{


		return 'contentItems';


	}


        


        public function rules()


        {


              return array(); //replace with what the class needs to be validated


        }





        public function relations()


        {


            return array(


                  'videos' => array(self::HAS_MANY, 'Video', 'contentItemId'),


                  'photos' => array(self::HAS_MANY, 'Photo', 'contentItemId')


            );


        }


}

Video class:

<?php


class Video extends CActiveRecord


{


	public static function model($className=__CLASS__)


	{


		return parent::model($className);


	}





	public function tableName()


	{


		return 'videos';


	}





        public function rules()


        {


              return array(); //replace with what the class needs to be validated


        }





        public function relations()


        {


            return array(


                  'contentItems' => array(self::BELONGS_TO, 'ContentItem', 'contentItemId')


            );


        }


}

Photo class:

<?php


class Photo extends CActiveRecord


{


	public static function model($className=__CLASS__)


	{


		return parent::model($className);


	}





	public function tableName()


	{


		return 'photos';


	}


       


        public function rules()


        {


              return array(); //replace with what the class needs to be validated


        }





        public function relations()


        {


            return array(


                  'contentItems' => array(self::BELONGS_TO, 'ContentItem', 'contentItemId')


            );


        }


}

The Manager Classes is where you actually do your structure models:

ContentManager class:

<?php


class ContentManager


{


   public function createAction(ContentItem $contentItem)


   {


      $contentItem->save();


   }





    public function updateAction(ContentItem $contentItem)


    {


         $contentItem->update();


    }





    public function deleteAction(ContentItem $contentItem)


    {


        $contentItem->delete();       


    }





    public function getContent($id)


    {


        return ContentItem::model()->findByPk($id);


    }


}

VideoManager class:

<?php


class VideoManager extends ContentManager


{


   public function createAction(ContentItem $contentItem, Video $video)


   {


      $transaction = $contentItem->dbConnection->beginTransaction();


      try {


          $contentItem->save();


          $video->save();


          $transaction->commit();


      } catch (Exception $e)


      {


          echo '<p>'.$e->getMessage().'</p>';


          $transaction->rollback();


      }


   }





    public function updateAction(ContentItem $contentItem, Video $video)


    {


         $transaction = $contentItem->dbConnection->beginTransaction();


         try {


             $contentItem->update();


             $video->update();


             $transaction->commit();


         } catch (Exception $e)


         {


             echo '<p>'.$e->getMessage().'</p>';


             $transaction->rollback();


         }


    }





    public function deleteAction(ContentItem $contentItem, Video $video)


    {


        $contentItem->delete();       


        $video->delete();


    }





    public function getVideos($id)


    {


        $video= ContentItem::model()->with('videos', 'videos.duration')->findByPk($id);


    }


}

Also for the PhotoManager would be the same like VideoManager. I have not tested those just a quick scratchy codes.

thanks for your reply.

What I was actually looking for was something like single table inheritance which is described here

http://www.martinfow…nheritance.html

In my case I'd basically have one table called content_items which has a type column that is either video or picture.

The table would have to columns id, type, width, height, filesize, duration

for pictures duration would stay NULL.

I would then have the classes Video and Picture which are both subclasses of ContentItem.

ContentItem would have their shared functions and then I can overwrite or add some functions in the two subclasses.

When I do Picture::model()->findAll(); it should access the content items table and automatically add the type = 'picture' condition.

Similarily when calling $picture->save() the type attribute shuold be set automatically.

CakePHP, Ruby on Rails and I believe Kohana have built in behaviours to implement single table inheritance or class table inheritance which is described here

http://www.martinfow…nheritance.html

I was looking for something similar in Yii since my application has a number of inherited models

Right now the only support is the instantiate() method in AR which you can override to create concrete child class instance when calling find() method. You will also need to override beforeSave() method to set the "type" column. We plan to improve the support for this in 1.1 release.

thanks for your answer qiang

I'm looking forward to 1.1