Code snippets for symfony 1.x

Navigation

Refine Tags

Snippets tagged "propel inheritance"

Listing sub-classes

When you use class inheritance in Propel, it can be quite useful to get a sorted array of all the descendant classes of any base class in your model.

First we need a simple method to determine whether a particular class inherits from a base class. We do this by ascending the class inheritance tree until we either a) find the base class we're looking for or b) reach the top of the tree

  function inheritsFrom($AClass,$ABaseClass)
  {
    $bIsSubClass=false;   
    $strClass=$AClass;                           
    while (($strClass!='') and !$bIsSubClass)
    {                                         
      $bIsSubClass=(get_parent_class($strClass)==$ABaseClass);
      $strClass=get_parent_class($strClass);                
    }
 
    return $bIsSubClass;     
  }  
 

Then we can extend the sfCore class, as shown below, to generate an array of sub-classes, that exist in the "model". I've added a couple of extra options, to allow class names to be converted to class key constants, and abstract classes to be ignored, if desired.

class EnhancedCore extends sfCore
{   
  public static function subClassesOf($AClass,$AKeyField='',$AIgnoreAbstractClasses=false)
  {
    $modelDir=sfConfig::get('sf_model_lib_dir');
    $intPathLength=strlen($modelDir);
    $arrClasses=array();    
    foreach(self::$classes as $strClass => $strPath)
    {
      //ignore classes outside the "model" library folder   
      if (substr($strPath,0,$intPathLength)==$modelDir)
      {       
        if (inheritsFrom($strClass,$AClass))
        {          
          $bIgnoreClass=false;
          if ($AIgnoreAbstractClasses)
          {
            $reflector=new ReflectionClass($strClass);
            $bIgnoreClass=$reflector->isAbstract();                        
          }
 
          if (!$bIgnoreClass)
          {
            $strKey=$strClass;
            if ($AKeyField!='')
            {
              $peerReflector=new ReflectionClass($AClass.'Peer');                      
              $strConstant=strtoupper($AKeyField).'_'.strtoupper($strClass);
              if (array_key_exists($strConstant,$peerReflector->getConstants()))
              {           
                $strKey=$peerReflector->getConstant($strConstant);
              }               
            }
 
            $arrClasses[$strKey]=$strClass;             
          }
        }        
      }    
    }
 
    asort($arrClasses);     
    return $arrClasses;
  }
}
 

So how about a simple example, in order to demonstrate its use. Let's say we have a schema.xml file like so:

<table name="person" 
    <column name="id" type="INTEGER" required="true" autoIncrement="true" primaryKey="true" />
    <column name="name" type="VARCHAR" size="50" required="true"/>            
    <column name="classkey" type="INTEGER" required="true" inheritance="single">    
      <inheritance key="1" class="Employee" extends="person"/>
      <inheritance key="2" class="Customer" extends="person"/>
      <inheritance key="3" class="Manager" extends="Employee"/>                        
    </column>
  </table>  
 

Symfony produces one base class (Person) and one peer class (PersonPeer) from this schema, as well as three sub-classes (Employee,Customer,Manager). Then the following simple code

$classes=EnhancedCore::subClassesOf('Person','classkey'); 
var_dump($classes) 
 

outputs >>>

array(3) {
    [2]=>
    string(8) "Customer"
    [1]=>
    string(8) "Employee"
    [3]=>
    string(7) "Manager"
    }
 
by Todd Martin on 2008-01-21, tagged inheritance  propel  subclasses 

propel behavior to extend classes with separate tables

I needed to have many subclasses inherited from a main class.

To do that with propel, you need to have all your classes in one big table. I wanted to have separate tables.

Then I discovered the propel behaviors and it does that very well !

Let's see an example with a master class "element" and a subclass "subElement" :

by Vincent Texier on 2007-08-13, tagged behavior  inheritance  model  propel 
(7 comments)

propel behavior to extend classes with separate tables

I needed to have many subclasses inherited from a main class.

To do that with propel, you need to have all your classes in one big table. I wanted to have separate tables.

Then I discovered the propel behaviors and it does that very well !

Let's see an example with a master class "element" end a subclass "subElement" :

by whoknows on 2007-08-13, tagged behavior  inheritance  model  propel 

How to use the admin generator along with propel inheritance

The problem

Say that you have a model object Son that inherits from the model object Father, via propel inheritance. You want to create an admin generator interface for the object Son. The problem is that propel does not generate a SonPeer class, so you'll have to call:

symfony propel-init-admin Father

but the list function will list all the Father objects instead of the Son objects only. Same problem with the create function that will create a Father object, not a Son object.

The solution

Here is a solution. You will have to overload getFatherOrCreate and addFiltersCriteria:

// add this in the actions.class.php of your admin module
  protected function addFiltersCriteria(&$c)
  {
    $c->add(FatherPeer::CLASS_KEY, FatherPeer::CLASSKEY_SON);
    parent::addFiltersCriteria($c);
  }  
 
  protected function getFatherOrCreate ($id = 'id')
  {
    $son = parent::getFatherOrCreate($id);
 
    if ($son->isNew()) // if it is a new one then we create a Son object
      $son = new Son();
   else
     $this->redirect404Unless($son->isSon()); // we check that we really got a son object
 
   return $son;
  }

Now everything will work as if you were using the Son object.

by Olivier Verdier on 2006-05-25, tagged admin  generator  inheritance  propel 
(2 comments)