Snippets

Create an account or login to be able to add, comment and rate snippets.

Navigation

Popular Tags

action admin ajax batch cache cli criteria css culture custom database debug doctrine filter form forms generator helper i18n javascript model mysql navigation object oyunlar pager pagination pake propel query routing session sql template test user validation validator view

Latest comments latest comments

This is a public source code repository where you can find, rate and comment code snippets published by others, or store you owns and categorize them with tags for easy retrieval.

Latest snippets latest snippets

Google analytics code by filter

This simple filter automatically adds google analytics code for all pages. It's no longer required to modify all the layouts, just put google code to app.yml and this filter does everything for you.

Create a lib/filters/gaFilter.class.php file:

<?php
class gaFilter extends sfFilter
{
  public function execute($filterChain)
  {
    // Nothing to do before the action
    $filterChain->execute();
    // Find google code and check if current module is not disabled
    if(($gaCode = sfConfig::get("app_ga_code",false)) !== false
    && !in_array($this->getContext()->getModuleName(),sfConfig::get("app_ga_disabled_modules",array()))) {
      //Decorate the response with the tracker code
      $response = $this->getContext()->getResponse();
      $response->setContent(str_ireplace('</body>', $gaCode.'</body>',$response->getContent())); 
    }
   }
}
 

Add the filter to filters.yml :

# insert your own filters here
 
# Google analytics filter
ga_filter:
  class: gaFilter
 

Now you are able to insert GA code into your page. Simply copy the whole code and add it as ga_code option into your app.yml file:

all:
  ...
  ga:
    code: >
      <script type="text/javascript">
      try {
      var pageTracker = _gat._getTracker("...");
      pageTracker._trackPageview();
      } catch(err) {}</script>
 

It works on fact, that you probably will not have a </body> tag in other place except at the end of your page and you will not use it in other content type than text/html.

Optionally you may disable GA filter in specific modules, such as administration is. To do this, add this option to your app.yml:

all:
  ...
  ga:
    disabled_modules: [administration]
    code: >
      ...
 
by Radek Petráň on 2010-03-07, tagged analytics  filter  google 

Add inline javascript to the response

Allows you to define a script block in a template, and let it be included by the include_javascripts() helper after all js files, so that you can put it right before the body tag , to conform to the Yahoo performance best practice (see http://developer.yahoo.com/performance/rules.html#js_bottom).

First put this class in your /lib/response directory:

<?php
/*
*  LfmWebResponse
* @package    forcemolle
* @subpackage response
* @author     Jules Bernable <julius@laforcemolle.org>
*
*/
class LfmWebResponse extends sfWebResponse
{
  protected
    $inline_scripts = array();
 
  public function initialize(sfEventDispatcher $dispatcher, $options = array())
  {
    parent::initialize($dispatcher, $options);
 
    $this->inline_scripts = array_combine($this->positions, array_fill(0, count($this->positions), array()));
  }
 
  /**
   * Adds a script block to the current web response.
   *
   * @param string $script    The JavaScript code
   * @param string $id        A unique identifier for the script
   * @param string $position  Position
   */
  public function addInlineScript($script='', $position=sfWebResponse::LAST)
  {
    $this->validatePosition($position);
 
    $this->inline_scripts[$position][] = $script;
  }
 
  /**
   * Retrieves inline scripts from the current web response.
   *
   * By default, the position is sfWebResponse::ALL,
   * and the method returns all inline scripts ordered by position.
   *
   * @param  string $position  The position
   *
   * @return array An array of inline scripts
   */
  public function getInlineScripts($position = self::ALL)
  {
    if (self::ALL === $position)
    {
      $inline_scripts = array();
      foreach ($this->getPositions() as $position)
      {
        foreach ($this->inline_scripts[$position] as $script)
        {
          $inline_scripts[] = $script;
        }
      }
      return $inline_scripts;
    }
    else if (self::RAW === $position)
    {
      return $this->inline_scripts;
    }
 
    $this->validatePosition($position);
 
    return $this->inline_scripts[$position];
  }
 
}
 

Update your $sf_app_dir/config/factories.yml accordingly:

all:
  response:
    class: LfmWebResponse
 

Then you need to overwrite the symfony AssetHelper. First copy $sf_symfony_lib_dir/helper/AssetHelper.php to $sf_app_dir/lib/helper/AssetHelper.php (or to $sf_lib_dir/helper/AssetHelper.php if you want it enabled globally). Then replace the get_javascripts() function (line 492) by the following:

function get_javascripts()
{
  $response = sfContext::getInstance()->getResponse();
  sfConfig::set('symfony.asset.javascripts_included', true);
 
  $html = '';
  foreach ($response->getJavascripts() as $file => $options)
  {
    $html .= javascript_include_tag($file, $options);
  }
 
  use_helper('JavascriptBase');
  foreach ($response->getInlineScripts() as $script)
  {
    $html .= content_tag('script', javascript_cdata_section($script), array('type' => 'text/javascript'));
  }
 
  return $html;
}
 

Et voilà ! You can now add a script in a template this way:

<?php $sf_response->addInlineScript(<<<EOF
// Mootools FTW!
window.addEvent('domready', function()
{
  var foo = alert('BAR!');
});
EOF
);
?>
 

Your script block is now added after all js files added by include_javascripts() !

Please note that this is a basic implementation. You can not 'override' a script nor remove it afterwards.

by Jules Bernable on 2010-03-07, tagged javascript  performance  response 
(2 comments)

Thumbnails creation in view (like sorl in django)

function thumbnail($path, $maxWidth, $maxHeight, $params=null)
{
    $path = ($path{0} == '/' ? '' : '/') . $path;
 
    $maxWidth = (int) $maxWidth;
    $maxHeight = (int) $maxHeight;
 
    $fileName = @end(explode('/', $path));
 
    $thumbsDir = sfConfig::get('sf_web_dir').'/images/thumbs';
    if(!file_exists($thumbsDir)) {
        mkdir($thumbsDir);
        chmod($thumbsDir, 0777);
    }
 
    $thumbName = $fileName.'-'.$maxWidth.'x'.$maxHeight.'.png';
    $thumbPath = '/images/thumbs/'.$thumbName;
 
    $sourcePath = sfConfig::get('sf_web_dir').$path;
    $destPath = sfConfig::get('sf_web_dir').$thumbPath;
 
    if(!file_exists($destPath)) {
        $t = new sfThumbnail($maxWidth, $maxHeight);
        $t->loadFile($sourcePath);
        $t->save($destPath, 'image/png'); 
    }
 
    $path = $thumbPath;
    return image_tag($path, $params);
 
}
 

Usage similar to image_tag, directory web/images/thumbs with chmod 0777 need to be created. Depending on sfThumbnailPlugin

example:

echo thumbnail('bigPhoto.png', 100, 100, 'alt=myBigPhoto');
 
by Adam Zieliński on 2010-03-06, tagged thumbnail 

CPF e CNPJ Validator

<?php
class sfValidatorCpfCnpj extends sfValidatorBase {
 
  /**
   * Configures the current validator
   *
   * Available options (required):
   *
   *  * tipo: CPF or CNPJ
   *
   * @param array $options   An array of options
   * @param array $messages  An array of error messages
   *
   * @see sfValidatorBase
   **/
 
  protected function configure($options = array(), $messages = array())
  {
    $this->addRequiredOption('tipo');
    $this->setMessage('invalid', '%tipo% %value% não é válido.');
  }
 
  protected function validaCPF($cpf) {
        $cpf = str_replace(array('.','-'),'',$cpf);
 
        $soma = 0;
 
        if (strlen($cpf) <> 11)
        return false;
 
        // Verifica 1º digito
        for ($i = 0; $i < 9; $i++):
            $soma += (($i+1) * $cpf[$i]);
        endfor;
 
        $d1 = ($soma % 11);
 
        if ($d1 == 10):
            $d1 = 0;
        endif;
 
        $soma = 0;
 
        // Verifica 2º digito
        for ($i = 9, $j = 0; $i > 0; $i--, $j++):
            $soma += ($i * $cpf[$j]);
        endfor;
 
        $d2 = ($soma % 11);
 
        if ($d2 == 10):
            $d2 = 0;
        endif;
 
        if ($d1 == $cpf[9] && $d2 == $cpf[10]):
            return true;
        else:
            return false;
        endif;
    }
 
    protected function validaCNPJ($cnpj) {
 
        $cnpj = str_replace(array('.','/','-'),'',$cnpj);
 
        if (strlen($cnpj) <> 14)
        return false;
 
        $soma = 0;
 
        $soma += ($cnpj[0] * 5);
        $soma += ($cnpj[1] * 4);
        $soma += ($cnpj[2] * 3);
        $soma += ($cnpj[3] * 2);
        $soma += ($cnpj[4] * 9);
        $soma += ($cnpj[5] * 8);
        $soma += ($cnpj[6] * 7);
        $soma += ($cnpj[7] * 6);
        $soma += ($cnpj[8] * 5);
        $soma += ($cnpj[9] * 4);
        $soma += ($cnpj[10] * 3);
        $soma += ($cnpj[11] * 2);
 
        $d1 = $soma % 11;
        $d1 = $d1 < 2 ? 0 : 11 - $d1;
 
        $soma = 0;
        $soma += ($cnpj[0] * 6);
        $soma += ($cnpj[1] * 5);
        $soma += ($cnpj[2] * 4);
        $soma += ($cnpj[3] * 3);
        $soma += ($cnpj[4] * 2);
        $soma += ($cnpj[5] * 9);
        $soma += ($cnpj[6] * 8);
        $soma += ($cnpj[7] * 7);
        $soma += ($cnpj[8] * 6);
        $soma += ($cnpj[9] * 5);
        $soma += ($cnpj[10] * 4);
        $soma += ($cnpj[11] * 3);
        $soma += ($cnpj[12] * 2);
 
 
        $d2 = $soma % 11;
        $d2 = $d2 < 2 ? 0 : 11 - $d2;
 
        if ($cnpj[12] == $d1 && $cnpj[13] == $d2):
            return true;
        else:
            return false;
        endif;
    }
 
  protected function doClean($value)
  {
    $tipo = $this->getOption('tipo');
 
    if($tipo == 'CPF'):
            if(!$this->validaCPF($value)):
                throw new sfValidatorError($this, 'invalid', array('tipo' => $this->getOption('tipo'), 'value' => $value));
                return false;
            endif;
    elseif($tipo == 'CNPJ'):
            if(!$this->validaCNPJ($value)):
                throw new sfValidatorError($this, 'invalid', array('tipo' => $this->getOption('tipo'), 'value' => $value));
                return false;
            endif;
    else:
        throw new sfValidatorError($this, 'invalid', array('tipo' => $this->getOption('tipo'), 'value' => $value));
        return false;
    endif;
 
    return $value;
  }  
}
 
?>
 
by Anderson da Veiga on 2010-02-27, tagged 12  13  14  cnpj  cpf  symfony  validator 

Moving the front controllers outside the web directory in Symfony 1.4

On occasions we want to move the front controllers of our application to another location and remove them from the web directory, without losing the relative directions to the directories css, js, images, etc..

For this we need to do two things.

  1. Add a little code in the class sfWebRequest to achieve this behavior in the development environment.
  2. Create a filter with the same code for the production environment.

For development environment: Replace the following line in the class sfWebRequest

568 $this->relativeUrlRoot = preg_replace('#/[^/]+\.php5?$#', '', $this->getScriptName());
 

by the following code

568 $relative = preg_replace('#/[^/]+\.php5?$#', '', $this->getScriptName());
569 $webDir = str_replace('\\', '/', sfConfig::get('sf_web_dir'));
570 $intercept = '/'.implode('/', array_intersect(explode('/',$relative), explode('/',$webDir)));       
571 $position = strpos($webDir, $intercept);
572 $this->relativeUrlRoot = substr($webDir, $position);                 
 

For production environment:: Create a filter relativeUrl.

class relativeUrlFilter extends sfFilter 
{
    public function execute($filterChain){
        $context  = $this->getContext();
        $request  = $context->getRequest();
 
        $relative = preg_replace('#/[^/]+\.php5?$#', '', $request->getScriptName());
        $webDir = str_replace('\\', '/', sfConfig::get('sf_web_dir'));
        $intercept = '/'.implode('/', array_intersect(explode('/',$relative), explode('/',$webDir)));       
        $position = strpos($webDir, $intercept);
        $request->setRelativeUrlRoot(substr($webDir, $position));                
        $filterChain->execute();
    }
}
 

Active a filter in apps/yourapp/config/filters.yml

rendering: ~
security:  ~
 
relativeUrl:                 
  class: relativeUrlFilter
 
cache:     ~
common:    ~
execution: ~
 

and that's it. Now you can put the front controllers outside the web directory, for example, in the root directory of the application myproject/index.php and myproject/myapp_dev.php, or in another location within the web directory, for example, myproject/web/frontend/index.php and myproject/web/backend/index.php.

Note: Remember that if you move these files of the web directory, you must update the following line of code according to the new location.

require_once(dirname(__FILE__).'/../config/ProjectConfiguration.class.php');
 
by Ivannis Suárez Jérez on 2010-02-23, tagged configuration 

Draggable Map Marker that updates latitude and longitude values

<div class="span-24 last">
<div id="map_canvas" class="span-22 prepend-1 append-1 last" style="height: 300px"></div>
<div id="marker_info" style="height:300px; vertical-align:top; background-color:pink;" class="ui-helper-hidden">Some marker info</div>
</div>
 
<% if (false) { %>
    <script src="../../Scripts/jquery-1.3.2.min-vsdoc.js" type="text/javascript"></script>
    <script src="../../Scripts/jquery.validate-vsdoc.js" type="text/javascript"></script>
<% } %>
<script src="http://maps.google.com/maps?file=api&v=2&sensor=false&key=yerKey" type="text/javascript"></script>
<script src="Scripts/jquery.bbq.js" type="text/javascript"></script>
<script type="text/javascript"> 
var map;
var marker;
 
$(document).ready(function() {
 
    var ps = $.deparam.fragment();
    var big = true;
    var point = new GLatLng(37.4419, -122.1419);
    if(ps.lat) {        
        point = new GLatLng(ps.lat, ps.lng);
    }
 
    map = new GMap2(document.getElementById("map_canvas"));
    map.addControl(new GLargeMapControl());
    map.addControl(new GNavLabelControl());
    map.setCenter(point, 13);
 
    marker = new GMarker(point, {draggable: true});
 
    GEvent.addListener(marker, "dragstart", function() {
        map.closeInfoWindow();
        });
 
    GEvent.addListener(marker, "dragend", function() {
        point = marker.getLatLng();
        location.hash = "#lat=" + point.lat() + "&lng=" + point.lng();
    });
 
    GEvent.addListener(marker, "click", function() {
        $('#map_canvas').removeClass('last').removeClass('span-22').addClass('span-18');
        $('#marker_info').addClass('span-4').addClass('last').show();
        if(big) {
            map.panBy(new GSize(-90, 0));
            big = false;
        }
    });
 
    map.addOverlay(marker);
});
    </script>
 
by Willie T on 2010-02-22, tagged googlemaps  javascript 
(1 comment)

Validator to make a field read-only

Sometimes, when you display the form for a Doctrine object, you want to make some fields read-only..

You can unset the field, and just display the value in the template. But it's better to still display an input form. You can also mess with the template, etc.

Here's a validator to achive the same goal, with no need to touch the template.

class sfValidatorReadOnlyField extends sfValidatorBase
{
  /**
   * Configures the current validator
   * 
   * Available options (required):
   *
   *  * object: The current form object
   *  * field:  The current form field
   *
   * Available error codes:
   *
   * * changed
   *
   * @param array $options   An array of options
   * @param array $messages  An array of error messages
   *
   * @see sfValidatorBase
   **/
  protected function configure($options = array(), $messages = array())
  {
    $this->addRequiredOption('object');
    $this->addRequiredOption('field');
 
    $this->addMessage('changed', 'You don\'t want to mess with me, kid!');
  }
 
  /**
   * @see sfValidatorBase
   */
  protected function doClean($value)
  {
    // Ok, we could just reset the value, but it's so more fun this way
    $object = $this->getOption('object');
    if ($value != $object->get($this->getOption('field')))
    {
      throw new sfValidatorError($this, 'changed');
    }
 
    return (string) $value;
  }
}
 

In your form class, use this code :

public function configure()
{// make some fields readonly
    $this->widgetSchema['first_name']->setAttribute('readonly', 'readonly');
    $this->widgetSchema['last_name']->setAttribute('readonly', 'readonly');
    $this->widgetSchema['email_address']->setAttribute('readonly', 'readonly');
 
    $this->validatorSchema['first_name'] = new sfValidatorReadOnlyField(array('field' => 'first_name', 'object' => $this->getObject()));
    $this->validatorSchema['last_name'] = new sfValidatorReadOnlyField(array('field' => 'last_name', 'object' => $this->getObject()));
    $this->validatorSchema['email_address'] = new sfValidatorReadOnlyField(array('field' => 'email_address', 'object' => $this->getObject()));
 
…
}
 
by Thibault Jouannic on 2010-02-15, tagged form  validator 

JQuery Code to help handle attaching an embedded video/audio list to a post

<textarea id="comment" style="height:35px;max-height:100px; line-height:12px; font-size:12px;" class="span-24 last"></textarea>
 
    <div id="b" class="span-24 last">
        <button id="vid">Vid</button> <button id="pic">Pic</button> 
    </div>
 
 
 
 
[javascript]
<script type="text/javascript"> 
$(document).ready(function() {
    var vidIndex = 0;
    var vidList = new Array();
    $('#vid').click(function() {
        $('#vidContainer').slideDown();
    });
    $('#closeVid').click(function() {
        $('#vidContainer').slideUp();
    });
    $('#addVid').click(function() {
        $('#vidList').append('<div id="vid'+vidIndex+'"><span class="video">' + $('#vidUrl').val() + '</span> <button title="'+vidIndex+'" class="removeVid">Remove</button></div>');
        ++vidIndex;
 
        var chosen = '';
        $('.video').each(function () {
            chosen += $(this).text() + ',';
        });
        $('#params').html(chosen);
    });
    $('.removeVid').live("click", function(){
        var index = $(this).attr('title');
        $('#vid'+index).remove();
        --vidIndex;
 
        var chosen = '';
        $('.video').each(function () {
            chosen += $(this).text() + ',';
        });
        $('#params').html(chosen);
    });
</script>
 
by Willie T on 2010-02-05, tagged jquery 

Dump fixtures using Criteria

In case you have a populated database and you need to generate a fixtures for it, you can use symfony propel:data-dump tasks or manually call methods of sfPropelData.

But If your database contains too much data to be fetched, this methods will not work for you.

For such cases I have extended sfPropelData to use Propel Criteria objects to filter dumped data. For example, you can set limit 30 records for every model to prevent dumping all records from database.

Usage:

You can create special tasks to generate fixtures and use there class listed below

$data = new fxPropelData();
 
// Defining criterias
$c1 = new Criteria();
$c1->setLimit(30);
$c2 = clone($c1);
$c2->add('IS_DELETED',0);
 
// array with models and criterias for them
    $models = array(
      'Fruit'=> $c1,
      'Vegetable' => $c2,
    );
 
$data->dumpDataWithCriteria(sfConfig::get('sf_data_dir').'/fixtures/food.yml',$models, $options['connection']);
 

class fxPropelData

class fxPropelData extends sfPropelData {
 
  public function dumpDataWithCriteria($directoryOrFile, $models = array(), $connectionName = null) {
 
    $dumpData = $this->getDataWithCriteria($models, $connectionName);
 
    // save to file(s)
    if (!is_dir($directoryOrFile)) {
      file_put_contents($directoryOrFile, sfYaml::dump($dumpData, 3));
    }
    else {
      $i = 0;
      foreach ($models as $tableName => $criteria) {
        if (!isset($dumpData[$tableName])) {
          continue;
        }
 
        file_put_contents(sprintf("%s/%03d-%s.yml", $directoryOrFile, ++$i, $tableName), sfYaml::dump(array($tableName => $dumpData[$tableName]), 3));
      }
    }
  }
 
  protected function getDataWithCriteria($models, $connectionName = 'propel') {
    $this->loadMapBuilders();
    $this->con = Propel::getConnection($connectionName);
    $this->dbMap = Propel::getDatabaseMap($connectionName);
 
 
    $dumpData = array();
 
    foreach ($models as $model => $criteria) {
      $tableName = $model;
 
      $tableMap = $this->dbMap->getTable(constant(constant($tableName.'::PEER').'::TABLE_NAME'));
      $hasParent = false;
      $haveParents = false;
      $fixColumn = null;
      foreach ($tableMap->getColumns() as $column) {
        $col = strtolower($column->getName());
        if ($column->isForeignKey()) {
          $relatedTable = $this->dbMap->getTable($column->getRelatedTableName());
          if ($tableName === $relatedTable->getPhpName()) {
            if ($hasParent) {
              $haveParents = true;
            }
            else {
              $fixColumn = $column;
              $hasParent = true;
            }
          }
        }
      }
 
      if ($haveParents) {
        // unable to dump tables having multi-recursive references
        continue;
      }
 
      // get db info
      $resultsSets = array();
      if ($hasParent) {
        $resultsSets[] = $this->fixOrderingOfForeignKeyDataInSameTableWithCriteria($resultsSets, $criteria, $tableName, $fixColumn);
      }
      else {
        $stmt = call_user_func(array($tableName.'Peer', 'doSelectStmt'),$criteria,$this->con);
        $resultsSets[] = array_merge($stmt->fetchAll(PDO::FETCH_ASSOC),$resultsSets);
        $stmt->closeCursor();
        unset($stmt);
      }
 
 
      foreach ($resultsSets as $rows) {
        if(count($rows) > 0) {
          if (!isset($dumpData[$tableName])) $dumpData[$tableName] = array();
 
          foreach ($rows as $row) {
            $pk = $tableName;
            $values = array();
            $primaryKeys = array();
            $foreignKeys = array();
 
            foreach ($tableMap->getColumns() as $column) {
              $col = $column->getName();
              $isPrimaryKey = $column->isPrimaryKey();
 
              if (is_null($row[$col])) {
                continue;
              }
 
              if ($isPrimaryKey) {
                $value = $row[$col];
                $pk .= '_'.$value;
                $primaryKeys[$col] = $value;
              }
 
              if ($column->isForeignKey()) {
                $relatedTable = $this->dbMap->getTable($column->getRelatedTableName());
                if ($isPrimaryKey) {
                  $foreignKeys[$col] = $row[$col];
                  $primaryKeys[$col] = $relatedTable->getPhpName().'_'.$row[$col];
                }
                else {
                  $values[$col] = $relatedTable->getPhpName().'_'.$row[$col];
 
                  $values[$col] = strlen($row[$col]) ? $relatedTable->getPhpName().'_'.$row[$col] : '';
                }
              }
              elseif (!$isPrimaryKey || ($isPrimaryKey && !$tableMap->isUseIdGenerator())) {
                // We did not want auto incremented primary keys
                $values[$col] = $row[$col];
              }
            }
 
            if (count($primaryKeys) > 1 || (count($primaryKeys) > 0 && count($foreignKeys) > 0)) {
              $values = array_merge($primaryKeys, $values);
            }
 
            $dumpData[$tableName][$pk] = $values;
          }
        }
      }
    }
 
    return $dumpData;
  }
 
  protected function fixOrderingOfForeignKeyDataInSameTableWithCriteria($resultsSets, $criteria, $tableName, $column, $in = null)
  {
    is_null($in) ? $criteria->add($column->getName(),NULL) : $criteria->add($column->getName(),$in,Criteria::IN);
 
    $stmt = call_user_func(array($tableName.'Peer', 'doSelectStmt'),$criteria,$this->con);
 
    $in = array();
    while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
    {
      $in[] = "'".$row[strtolower($column->getRelatedColumnName())]."'";
      $resultsSets[] = $row;
    }
 
    if ($in = implode(', ', $in))
    {
      $resultsSets = $this->fixOrderingOfForeignKeyDataInSameTableWithCriteria($resultsSets, $tableName, $column, $in);
    }
 
    return $resultsSets;
  }
 
 
}
 
by Davert on 2009-12-11, tagged creiteria  fixtures  functional  propel  test  unit 

How to generate routes (links) from the model or from a task

The symfony routing system is tied to the sfContext resource via the factory handler.

It might an issue if you need to build routes in the cli mode, where sfContext has no instance. Sample: one of your cron jobs sends emails that contain links.

The best way I've found is to provide an access to the routing system linked to the ProjectConfiguration class. Add a static protected "$routing" variable and a static public method "getRouting()" :

class ProjectConfiguration extends sfProjectConfiguration
{
  static protected
    $routing = null # Symfony routing system
    ;
 
 
  /**
   * Returns the routing resource for the active application
   */
  static public function getRouting()
  {
    if (null !== self::$routing)
    {
      return self::$routing;
    }
 
    // If sfContext has an instance, returns the loaded routing resource
    if (sfContext::hasInstance() && sfContext::getInstance()->getRouting())
    {
      self::$routing = sfContext::getInstance()->getRouting();
    }
    else
    {
      // Initialization
      if (!self::hasActive())
      {
        throw new sfException('No sfApplicationConfiguration loaded');
      }
      $appConfig = self::getActive();
      $config = sfFactoryConfigHandler::getConfiguration($appConfig->getConfigPaths('config/factories.yml'));
      $params = array_merge(
        $config['routing']['param'],
        array(
          'load_configuration' => false,
          'logging'            => false,
          'context'            => array(
            'host'      => sfConfig::get('app_host',   'localhost'),
            'prefix'    => sfConfig::get('app_prefix', sfConfig::get('sf_no_script_name') ? '' : '/'.$appConfig->getApplication().'_'.$appConfig->getEnvironment().'.php'),
            'is_secure' => sfConfig::get('app_host',   false),
          ),
        )
      );
      $handler = new sfRoutingConfigHandler();
      $routes = $handler->evaluate($appConfig->getConfigPaths('config/routing.yml'));
      $routeClass = $config['routing']['class'];
      self::$routing = new $routeClass($appConfig->getEventDispatcher(), null, $params);
      self::$routing->setRoutes($routes);
    }
 
    return self::$routing;
  }
}
 

In the method, the 'context' parameter needs further explanations.

In a classic context, symfony is loaded after a web request. Sample: https://www.example.com/frontend_dev.php/products

This request provides data that are reused when sf needs to generate a new dynamic url:

In the cli mode, as Symfony is not loaded by a request, you have to provide these parameters (prefix can be guessed).

In app.yml, add:

all:
  host: www.example.com
  is_secure: false
 

Now, let's see how to generate the link. If your routing.yml file looks like it:

product_show:
  url:     /products/:category_slug/:slug
  class:   sfDoctrineRoute
  options: { model: Product, type: object }
  # ...
 

Then building the link is as simple as:

class Product extends BaseProduct
{
  /**
   * Returns the public url
   */
  public function getUrl()
  {
    return ProjectConfiguration::getRouting()->generate('product', $this, true);
  }
 
 
  /* ... */
}
 

Regards.

by Éric Rogé on 2009-12-11, tagged cli  routing 
(1 comment)