Development

HowToExtendPropelPluginModel (diff)

You must first sign up to be able to contribute.

Changes from Version 1 of HowToExtendPropelPluginModel

Show
Ignore:
Author:
hartym (IP: 62.240.242.149)
Timestamp:
11/28/07 17:43:53 (10 years ago)
Comment:

getOMClass

Legend:

Unmodified
Added
Removed
Modified
  • HowToExtendPropelPluginModel

    v0 v1  
     1== The problem == 
     2 
     3Some plugins like sfGuardPlugin were upgraded recently to allow flexible model extension by adding an additional level of class inheritance. Let me explain. 
     4 
     5Traditionnaly, model is built like the following: 
     6 
     7 
     8{{{ 
     9BaseMyObject     <--inherits-- MyObject 
     10BaseMyObjectPeer <--inherits-- MyObjectPeer 
     11}}} 
     12 
     13If you want to extend your model, it's usually done easily by editing the child classes, and that's their only purpose. 
     14 
     15Now let's imagine you want to do the same in a plugin. You create a schema.yml in plugins/MyPlugin/config/, and define your schema by adding a 'package' parameter to describe where propel generators should write their classes: 
     16 
     17{{{ 
     18package: plugins.MyPlugin.lib.model 
     19}}} 
     20 
     21This will say "ok dude, send your crap in /plugins/MyPlugin/lib/model/". But the plugin should not be modified by the end user, or you'd loose all its avantages. Update will become impossible, and the D.R.Y principle would be completely laughed at. Still it is possible to create the child classes in your project to extends them, but you'd have either to copy the code or admit plugin has no model operation, so it's about ok 0% of the time. Last case which was proposed on mailing list and applied to sfGuardPlugin for example, was to use a proxy class pair, called pluginMyObject/pluginMyObjectPeer which comes on the scene like this: 
     22 
     23{{{ 
     24BaseMyObject     <--inherits-- pluginMyObject     <--inherits-- MyObject 
     25BaseMyObjectPeer <--inherits-- pluginMyObjectPeer <--inherits-- MyObjectPeer 
     26}}} 
     27 
     28The leaf classes are simple empty classes that are only present in case you want to extend the model. The two-cents howto is to copy thoose in your own /lib, clear the cache, and start coding. But in some case you'll notice an annoying bug, that will simply bypass your methods.  
     29 
     30== The solution == 
     31 
     32The culprit is propel, which defines some autoloading magic in its classes. After some tracking, here are the relevant parts we found in BasesfGuardSecurityUser: 
     33 
     34{{{ 
     35const CLASS_DEFAULT = 'plugins.sfGuardPlugin.lib.model.sfGuardUser'; 
     36 
     37..... 
     38 
     39$cls = sfGuardUserPeer::getOMClass(); 
     40$cls = Propel::import($cls); 
     41 
     42..... 
     43 
     44public static function getOMClass() 
     45{ 
     46  return sfGuardUserPeer::CLASS_DEFAULT; 
     47} 
     48}}} 
     49 
     50Let's simplify by admitting that Propel::import is the Propel autoloader, replacinc dots by slashes in package and loading the matching file. It will (auto)load the plugin sfGuardUserClass instead of your own. 
     51 
     52To override this stupid Propel behaviour (did I say I love Doctrine?), just override the getOMClass method: 
     53{{{ 
     54class sfGuardUserPeer extends PluginsfGuardUserPeer 
     55{ 
     56 
     57  public static function getOMClass() 
     58  { 
     59    return 'lib.model.sfGuardPlugin.sfGuardUser'; 
     60  } 
     61} 
     62}}} 
     63 
     64This will be used by Propel import to load your very own class. Hallelujah!