Code snippets for symfony 1.x

Navigation

Refine Tags

Snippets tagged "propel subclasses"

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