Code snippets for symfony 1.x

Navigation

Snippets by user Mike Crowe

Globally format forms

If you are like me, you see the nice Forms chapter, but when you follow the instructions, your forms don't look nice like the examples.

I gleaned the following techniques from various forum posts. I take NO credit for this, it's heavily snatched from other sources.

First, create your format class, which lays out all forms. I use tables in my design, but you can find examples of div based versions elsewhere, )such as here).

/lib/sfWidgetFormSchemaFormatterCustom.class.php:

<?php
class sfWidgetFormSchemaFormatterCustom extends sfWidgetFormSchemaFormatterTable
{
  protected
    $rowFormat       = "<tr class='formrow'>\n  <th class='formheader'>%label%:</th>\n  <td class='forminput'>%error%%field%%help%%hidden_fields%</td>\n</tr>\n",
    $errorRowFormat  = "<tr><td colspan='formerror' colspan=\"2\">\n%errors%</td></tr>\n",
    $helpFormat      = '<br />%help%',
    $decoratorFormat = "<table class='form'>\n  %content%</table>";
}
 

The key here is to insert into each HTML element the global classes to format your code. Above, you can see I added the 'form' class to the table, 'formheader' to the header rows, and 'forminput' for each field.

Next, you need to globally enable this formatter for all forms:

/config/ProjectConfiguration.class.php:

<?php
 
require_once dirname(dirname(__FILE__)).'/lib/vendor/symfony/lib/autoload/sfCoreAutoload.class.php';
sfCoreAutoload::register();
 
class ProjectConfiguration extends sfProjectConfiguration
{
  public function setup()
  {
    // for compatibility / remove and enable only the plugins you want
    $this->enableAllPluginsExcept(array('sfDoctrinePlugin', 'sfCompat10Plugin'));
    sfWidgetFormSchema::setDefaultFormFormatterName('Custom');
  }
}
 

Naturally, make sure you manage your plugins appropriately. They key line is the:

sfWidgetFormSchema::setDefaultFormFormatterName('Custom');
 

Now, customize your CSS files:

.form {
  padding-top:15px;
}
.formrow {
 
}
.formheader {
  text-align: right;
  font-weight: bold;
  padding-right: 10px;
  vertical-align: middle;
}
td.forminput input {
  width: 300px;
}
.formerror {
 
}
 

Hope this helps others.

by Mike Crowe on 2009-10-24, tagged form  formatter  sfform  widget 

Verify form field matches existing field: sfValidatorPropelExisting

This snippet may be used as a post-validator to verify that a column exists within a Propel table. It's a trivial derivative of the sfValidatorPropelUnique (so much so I left the copyrights in place). It's strictly a that validator with the logic reversed.

/*
 * This file is part of the symfony package.
 * (c) Fabien Potencier <fabien.potencier@symfony-project.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
 
/**
 * sfValidatorPropelExisting validates that the uniqueness of a column.
 *
 * Warning: sfValidatorPropelExisting is susceptible to race conditions.
 * To avoid this issue, wrap the validation process and the model saving
 * inside a transaction.
 *
 * @package    symfony
 * @subpackage validator
 * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
 * @version    SVN: $Id: sfValidatorPropelExisting.class.php 13249 2008-11-22 16:10:11Z fabien $
 */
class sfValidatorPropelExisting extends sfValidatorSchema
{
  /**
   * Constructor.
   *
   * @param array  $options   An array of options
   * @param array  $messages  An array of error messages
   *
   * @see sfValidatorSchema
   */
  public function __construct($options = array(), $messages = array())
  {
    parent::__construct(null, $options, $messages);
  }
 
  /**
   * Configures the current validator.
   *
   * Available options:
   *
   *  * model:              The model class (required)
   *  * column:             The unique column name in Propel field name format (required)
   *                        If the uniquess is for several columns, you can pass an array of field names
   *  * field               Field name used by the form, other than the column name
   *  * primary_key:        The primary key column name in Propel field name format (optional, will be introspected if not provided)
   *                        You can also pass an array if the table has several primary keys
   *  * connection:         The Propel connection to use (null by default)
   *  * throw_global_error: Whether to throw a global error (false by default) or an error tied to the first field related to the column option array
   *
   * @see sfValidatorBase
   */
  protected function configure($options = array(), $messages = array())
  {
    $this->addRequiredOption('model');
    $this->addRequiredOption('column');
    $this->addOption('field', null);
    $this->addOption('primary_key', null);
    $this->addOption('connection', null);
    $this->addOption('throw_global_error', false);
 
    $this->setMessage('invalid', 'An object with the same "%column%" already exist.');
  }
 
  /**
   * @see sfValidatorBase
   */
  protected function doClean($values)
  {
    if (!is_array($values))
    {
      throw new InvalidArgumentException('You must pass an array parameter to the clean() method (this validator can only be used as a post validator).');
    }
 
    if (!is_array($this->getOption('column')))
    {
      $this->setOption('column', array($this->getOption('column')));
    }
 
    if (!is_array($field = $this->getOption('field')))
    {
      $this->setOption('field', $field ? array($field) : array());
    }
    $fields = $this->getOption('field');
 
    $criteria = new Criteria();
    foreach ($this->getOption('column') as $i => $column)
    {
      $name = isset($fields[$i]) ? $fields[$i] : $column;
      if (!array_key_exists($name, $values))
      {
        // one of the column has be removed from the form
        return $values;
      }
 
      $colName = call_user_func(array(constant($this->getOption('model').'::PEER'), 'translateFieldName'), $column, BasePeer::TYPE_FIELDNAME, BasePeer::TYPE_COLNAME);
 
      $criteria->add($colName, $values[$name]);
    }
 
    $object = call_user_func(array(constant($this->getOption('model').'::PEER'), 'doSelectOne'), $criteria, $this->getOption('connection'));
 
    // if no object or if we're updating the object, it's ok
    if (!is_null($object) && !$this->isUpdate($object, $values))
    {
      return $values;
    }
 
    $error = new sfValidatorError($this, 'invalid', array('column' => implode(', ', $this->getOption('column'))));
 
    if ($this->getOption('throw_global_error'))
    {
      throw $error;
    }
 
    $columns = $this->getOption('column');
 
    throw new sfValidatorErrorSchema($this, array($columns[0] => $error));
  }
 
  /**
   * Returns whether the object is being updated.
   *
   * @param BaseObject  $object   A Propel object
   * @param array       $values   An array of values
   *
   * @return Boolean     true if the object is being updated, false otherwise
   */
  protected function isUpdate(BaseObject $object, $values)
  {
    // check each primary key column
    foreach ($this->getPrimaryKeys() as $column)
    {
      $columnPhpName = call_user_func(array(constant($this->getOption('model').'::PEER'), 'translateFieldName'), $column, BasePeer::TYPE_FIELDNAME, BasePeer::TYPE_PHPNAME);
      $method = 'get'.$columnPhpName;
      if (!isset($values[$column]) or $object->$method() != $values[$column])
      {
        return false;
      }
    }
 
    return true;
  }
 
  /**
   * Returns the primary keys for the model.
   *
   * @return array An array of primary keys
   */
  protected function getPrimaryKeys()
  {
    if (is_null($this->getOption('primary_key')))
    {
      $primaryKeys = array();
      $tableMap = call_user_func(array(constant($this->getOption('model').'::PEER'), 'getTableMap'));
      foreach ($tableMap->getColumns() as $column)
      {
        if (!$column->isPrimaryKey())
        {
          continue;
        }
 
        $primaryKeys[] = call_user_func(array(constant($this->getOption('model').'::PEER'), 'translateFieldName'), $column->getPhpName(), BasePeer::TYPE_PHPNAME, BasePeer::TYPE_FIELDNAME);
      }
 
      $this->setOption('primary_key', $primaryKeys);
    }
 
    if (!is_array($this->getOption('primary_key')))
    {
      $this->setOption('primary_key', array($this->getOption('primary_key')));
    }
 
    return $this->getOption('primary_key');
  }
}
 
by Mike Crowe on 2009-10-24, tagged propel  validator