= 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['arguments'][0], $event['arguments'][1]); 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 [wiki: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 [wiki: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.