# sfPropelEventsPlugin Add a number of symfony 1.1 events to your Propel objects (compatible with both symfony 1.0 and 1.1). ## Installation Download the plugin over the symfony PEAR channel: $ ./symfony plugin-install sfPropelEventsPlugin Update the following two directive in your project's `propel.ini` file: propel.builder.peer.class = plugins.sfPropelEventsPlugin.lib.builder.SfPropelEventsPeerBuilder propel.builder.object.class = plugins.sfPropelEventsPlugin.lib.builder.SfPropelEventsObjectBuilder Also in `propel.ini`, make sure the `addBehaviors` directive is switched on: propel.builder.addBehaviors = true Now rebuild your model classes: $ ./symfony propel-build-model ## Propel events Once `propel.ini` is updated and the model rebuilt, the following events will have been added to your OM classes: * `BaseXXX.pre_delete` * `BaseXXX.post_delete` * `BaseXXX.pre_save` * `BaseXXX.post_save` * `BaseXXX.method_not_found` * `BaseXXX.set_fk` * `BaseXXX.get_fk` * `BaseXXX.init_fk_coll` * `BaseXXX.add_fk` * `BaseXXX.count_fks` * `BaseXXX.get_fks` * `BaseXXX.get_fks_join` ## Creating event-based Propel behaviors All of these events can be utilized in Propel behaviors. For the purpose of this documentation let's assume you're creating a new symfony plugin. With the addition of Propel events, you can now register your behavior logic in three ways: 1. `sfPropelBehavior::registerHooks()` 2. `sfPropelBehavior::registerMethods()` 3. `sfPropelEventsBehavior::registerListeners()` Use of the third method would look something like this, in your plugin's `config.php` file: [php] <?php sfPropelEventsBehavior::registerListeners('my_behavior', array( 'method_not_found' => array( array('myBehavior', 'listenForMethodNotFound'), ), 'pre_save' => array( array('myBehavior', 'listenForPreSave'), ), )); ### Modifying protected variables If you want to modify a protected member of a Propel object, you can do this by calling the `modifyObject()` method on the event object (a method of `sfPropelEvent`). [php] <?php class myBehavior { static public function listenForMethodNotFound(sfPropelEvent $event) { switch ($event['method']) { // ->setProtectedVar(string $varName, mixed $value) case 'setProtectedVar': $event->modifyObject($event[$event['arguments'][1]('arguments'][0],)); return true; } } } A user of your plugin can now add this behavior to a model class. This works slightly different in symfony 1.0 and symfony 1.1. ### Adding behaviors in symfony 1.1 Adding the behavior to `schema.yml` will also activate these event listeners. In other words, users don't need to do anything special to install your plugin if they're using symfony 1.1. [yaml] classes: Item: columns: id: ~ # more columns... behaviors: my_behavior: param1: foobar ### Adding behaviors in symfony 1.0 In symfony 1.0, users will need to call `sfPropelEventsBehavior::add()` in place of `sfPropelBehavior::add()`. For example: [php] <?php class Item extends BaseItem { } sfPropelEventsBehavior::add('Item', array( 'my_behavior' => array('param1' => 'foobar'), )); **Note:** This plugin has not been tested alongside [sfPropelAlternativeSchemaPlugin](/plugins/sfPropelAlternativeSchemaPlugin) in symfony 1.0. ### Testing the dependency If your plugin depends on Propel events, include the following code in `config/config.php`: [php] <?php if (!class_exists('sfPropelEvent')) { throw new sfException('sfFoobarPlugin requires that sfPropelEventsPlugin be installed.'); } ## Maintainers Kris Wallsmith ## Roadmap * Peer events * Play nice with [sfPropelAlternativeSchemaPlugin](/plugins/sfPropelAlternativeSchemaPlugin) (symfony 1.0) ## Changelog ### Version 0.4.0-alpha * Nested all method arguments in an `arguments` event parameter * Added parameters to FK methods * Modified `->doSave()` logic to address Propel cascading save bug * Addressed bug in how `sfPropelEventsToolkit` fetches the dispatcher ### Version 0.3.0-alpha * All internal collections, foreign key objects, and last-used criteria are now exposed to the `method_not_found` event * Propel objects now dispatch `sfPropelEvent` objects, which can carry modifications to protected BaseXXX members ### Version 0.2.0-alpha * Added symfony 1.0 support ### Version 0.1.0-alpha * Initial release *---- ## Event reference Each event will include a set of parameters specific to that event. Also, each event object will elicit different reactions from the object once it returns, depending on the return value set by your listener. ### `pre_delete` This `notifyUntil` event includes the following parameters: * `arguments` * `modified_columns` If your listener sets a return value for the event that evaluates as true, the standard Propel delete routine will not run. [php] <?php function listen_for_pre_delete(sfEvent $event) { // this will prevent Propel from deleting the object from the database $event->setReturnValue(true); return true; } ### `post_delete` This `notify` event includes the following parameters: * `arguments` * `modified_columns` ### `pre_save` This `notifyUntil` event includes the following parameters: * `arguments` * `modified_columns` If your listener gives the event an integer return value, the standard Propel save routing will not run. [php] <?php function listen_for_pre_save(sfEvent $event) { // this will prevent Propel from saving the object to the database $event->setReturnValue(0); return true; } ### `post_save` This `notify` event includes the following parameters: * `arguments` * `was_new` whether the object was new before being saved * `affected_rows` * `modified_columns` those columns marked as modifed before the object was saved ### `method_not_found` This `notifyUntil` event includes the following parameters: * `method` * `arguments` * `fk_objects` * `collections` * `last_criteria` * `modified_columns` [php] <?php function listen_for_method_not_found(sfEvent $event) { $parameters = $event->getParameters(); switch ($parameters['method']) { case 'getModifiedColumns': $event->setReturnValue($parameters['modified_columns']); return true; } } ### `set_fk` This `notifyUntil` event includes the following parameters: * `method` * `arguments` * `column` * `related_class` * `in_object` * `in_object_var` * `modified_columns` If your listener gives the event a return value of `null` or an instance of the `related_class`, the return value will be stored to the object. [php] <?php function listen_for_set_fk(sfEvent $event) { // this prevents any object from being place in this FK $event->setReturnValue(null); return true; } ### `get_fk` This `notifyUntil` event includes the following parameters: * `method` * `arguments` * `column` * `related_class` * `in_object` The instance of `related_class` or `null` currently stored in the object * `in_object_var` * `modified_columns` If your listener gives the event a return value of `null` or an instance of the `related_class`, the event's return value will be returned to the calling script. [php] <?php function listen_for_get_fk(sfEvent $event) { $parameters = $event->getParameters(); $class = $parameters['related_class']; $event->setReturnValue(new $class); return true; } ### `init_fk_coll` This `notifyUntil` event includes the following parameters: * `method` * `arguments` * `related_class` * `in_object` The current value of the internal FK collection * `in_object_var` * `last_criteria` The last Criteria used to query this FK * `modified_columns` If your listener gives the event an array return value, the object's internal collection will be initalized with that value. ### `add_fk` This `notifyUntil` event includes the following parameters: * `method` * `arguments` * `related_class` * `added_value` * `in_object` The internal FK collection * `in_object_var` * `last_criteria` The last Criteria used to query this FK * `modified_columns` If your listener sets a return value for the event that evaluates as true, the standard Propel add routine will not run. ### `count_fks` This `notifyUntil` event includes the following parameters: * `method` * `arguments` * `related_class` * `in_object` The internal FK collection * `in_object_var` * `last_criteria` The last Criteria used to query this FK * `modified_columns` If your listener sets an integer return value for the event, this value will be returned to the calling script instead of Propel querying the database. ### `get_fks` This `notifyUntil` event includes the following parameters: * `method` * `arguments` * `related_class` * `in_object` The internal FK collection * `in_object_var` * `last_criteria` The last Criteria used to query this FK * `modified_columns` If your listener sets an array return value for the event, this value will be returned to the calling script in place of Propel's default behavior. ### `get_fks_join` This `notifyUntil` event includes the following parameters: * `method` * `arguments` * `middle_class` * `related_class` * `in_object` * `in_object_var` * `last_criteria` * `modified_columns` If your listener sets an array return value for the event, this value will be returned to the calling script in place of Propel's default behavior.