![]() |
|
Snippets |
|
I wanted to add created_by and updated_by columns to my Doctrine schema. But the existing templates doesn't support that, so i've rewritten the Timestampable template.
Now Doctrine can automatically update these fields to the specific username oder userid.
ExampleUser:
tableName: example_user
columns:
id:
primary: true
autoincrement: true
type: integer(4)
name:
type: string(255)
password:
type: string(255)
actAs:
Userid:
created:
name: created_by
type: integer
updated:
name: updated_by
type: string
If you are writing integer as type the template will call $sf_user->getId(), if you write string it will call $sf_user->getUsername().
So the above example will write the ID to created_by column and the username to updated_by column.
<?php /* * $Id$ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * This software consists of voluntary contributions made by many individuals * and is licensed under the LGPL. For more information, see * <http://www.phpdoctrine.org>. */ /** * Doctrine_Template_Userid * * Easily add created and updated by ids or usernames to your doctrine records * * @package Doctrine * @subpackage Template * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.phpdoctrine.org * @since 1.0 * @version $Revision$ * @author Thomas Boerger <tb@mosez.net> */ class Doctrine_Template_Userid extends Doctrine_Template { /** * Array of userid options * * @var string */ protected $_options = array( 'created' => array( 'name' => 'created_by', 'type' => 'integer', 'disabled' => false, 'expression' => false, 'options' => array() ), 'updated' => array( 'name' => 'updated_by', 'type' => 'integer', 'disabled' => false, 'expression' => false, 'onInsert' => true, 'options' => array() ) ); /** * __construct * * @param string $array. * @return void */ public function __construct(array $options) { $this->_options = Doctrine_Lib::arrayDeepMerge($this->_options, $options); } /** * setTableDefinition * * @return void */ public function setTableDefinition() { if(!$this->_options['created']['disabled']) { $this->hasColumn( $this->_options['created']['name'], $this->_options['created']['type'], null, $this->_options['created']['options'] ); } if(!$this->_options['updated']['disabled']) { $this->hasColumn( $this->_options['updated']['name'], $this->_options['updated']['type'], null, $this->_options['updated']['options'] ); } $this->addListener(new Doctrine_Template_Listener_Userid($this->_options)); } }
<?php /* * $Id$ * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * This software consists of voluntary contributions made by many individuals * and is licensed under the LGPL. For more information, see * <http://www.phpdoctrine.org>. */ /** * Doctrine_Template_Listener_Userid * * @package Doctrine * @subpackage Template * @license http://www.opensource.org/licenses/lgpl-license.php LGPL * @link www.phpdoctrine.org * @since 1.0 * @version $Revision$ * @author Thomas Boerger <tb@mosez.net> */ class Doctrine_Template_Listener_Userid extends Doctrine_Record_Listener { /** * Array of userid options * * @var string */ protected $_options = array(); /** * __construct * * @param string $options. * @return void */ public function __construct(array $options) { $this->_options = $options; } /** * preInsert * * @param object $Doctrine_Event. * @return void */ public function preInsert(Doctrine_Event $event) { if(!$this->_options['created']['disabled']) { $createdName = $this->_options['created']['name']; $event->getInvoker()->$createdName = $this->getUserId('created'); } if(!$this->_options['updated']['disabled'] && $this->_options['updated']['onInsert']) { $updatedName = $this->_options['updated']['name']; $event->getInvoker()->$updatedName = $this->getUserId('updated'); } } /** * preUpdate * * @param object $Doctrine_Event. * @return void */ public function preUpdate(Doctrine_Event $event) { if( ! $this->_options['updated']['disabled']) { $updatedName = $this->_options['updated']['name']; $event->getInvoker()->$updatedName = $this->getUserId('updated'); } } /** * getUserId * * Gets the userid or username depending on field format * * @param string $type. * @return void */ public function getUserId($type) { $options = $this->_options[$type]; if ($options['expression'] !== false && is_string($options['expression'])) { return new Doctrine_Expression($options['expression']); } elseif (!class_exists("pakeApp")) { switch($options['type']) { case 'integer': if (class_exists('sfGuardUser')) { return sfContext::getInstance()->getUser()->getAttribute('user_id', null, 'sfGuardSecurityUser'); } else { return sfContext::getInstance()->getUser()->getId(); } break; case 'string': return sfContext::getInstance()->getUser()->getUsername(); break; default: return 'n/a'; break; } } } }
Comments on this snippet
I modified your snippet to provide some more features:
symfony doctrine-build-all-reloadto get this working i had to change one function in lib/doctrine/Doctrine/Template/Listener/Userid.php:
Nice work, i will add it directly to the snippet.
This not work in Symfony 1.2
When using CLI-mode data-load, the sfContext::getInstance() will through exception.
#
The "default" context does not exist.
#
As mentioned by Kary Leong, this will not work on cli mode, which includes:
this is a recurring problem with sfContext, and you should avoid using it anyway.
One possible solution could be, before using sfContext, checking if the created_by and updated_by are already (this let the dev the chance to fill them, avoiding the sfContext exception) and/or to check for a context using sfContext::hasInstance();
As a side note, the "type: string" parameter would better trigger a __toString() call as this is the standard way to get a string representation from an object
Thanks for your "snippet"
These are the things that strengthen a system