четверг, 14 июля 2011 г.

Разбиваем routing.yml на несколько файлов

Если количество роутов в вашем routing.yml уверенно перевалило за 50, то, вероятно, ориентироваться в таком файле стало трудно. Самое очевидное решение - разбить его на несколько файлов. Но, увы, в symfony1 нет такой штатной возможности. Решение несложное. Как известно, в .yml можно использовать РНР-код. Что ж, попробуем! Пишем в самом начале routing.yml:

//Подключаем файлы роутингов из папки /app/config/routing/
<?php
$dir=dirname(__FILE__).'/routing/';
$dh = opendir($dir);
while ($file = readdir($dh))
{
  if (is_dir($file))
    continue;
    
  require_once($dir.$file);
}
?>


затем создаем папку /frontend/config/routing/

затем создаем там любое количество файлов .yml, по которым распределяем наши роуты так, как нам этого хочется (переносим все роуты из routing.yml). Таким образом в rounting.yml остается только РНР-код, а все роуты структурированы по отдельным файлам.

На производительности такое решение не скажется совершенно, т.к. все yml-файлы в dev преобразовываются в РНР-код и кэшируются.

Совет: поскольку имеет значение порядок, в котором описаны роуты, именуйте файлы в соответствии с порядком их подключения:

10.blog.routing.yml
20.news.routing.yml
30.private.routing.yml
40.common.routing.yml

понедельник, 21 марта 2011 г.

How to change "csrf attack detected" message in symfony

It is proposed some methods how to change this message.

I wrote another simple one:

1. Override addCSRFProtection in BaseForm.class.php:

public function addCSRFProtection($secret = null)
  {
    parent::addCSRFProtection($secret);
    $validatorSchema=$this->getValidatorSchema();
    if (isset($validatorSchema[self::$CSRFFieldName])) 
    {
      $validatorSchema[self::$CSRFFieldName]=new myValidatorCSRFToken($validatorSchema[self::$CSRFFieldName]->getOptions());
    }
  }

2. Add new myValidatorCSRFToken.class.php with contents:

class myValidatorCSRFToken extends sfValidatorBase
{
  protected function configure($options = array(), $messages = array())
  {
    $this->addRequiredOption('token');

    $this->setOption('required', true);

    $this->addMessage('csrf_attack', 'Время сессии истекло.');
  }

  protected function doClean($value)
  {
    if ($value != $this->getOption('token'))
    {
      $exception=new sfValidatorError($this, 'csrf_attack');
      throw new sfValidatorErrorSchema($this, array($exception));
    }

    return $value;
  }
}

3. That's all :)

воскресенье, 19 декабря 2010 г.

Грабли: andWhere( id != ?, null)

Простой код

$id=null;

    $q=Doctrine_Query::create()
      ->from('sfGuardUser u')
      ->andWhere('u.id != ?',$id);
      
    print_r($q->fetchArray());

Дает совершенно неожиданные результаты:

1. SQL-запрос составляется правильный (в этом можно убедиться в дебаг-панели и в логах)

2. Результат (массив или коллекция) всегда будут пустыми.

Решение:
->andWhere('u.id != ?',(int)$id);

Вот уж не думал, что надо приводить типы в prepare_sql Доктрины!

суббота, 11 декабря 2010 г.

Как убрать поле "День" из виджета даты?

Предположим, нужно сделать виджет для выбора ГОДА+МЕСЯЦА. Проще всего для этих целей подойдет стандартный sfWidgetFormDate. Убираем у него поле для выбора дня:
$this->widgetSchema['month']->setOption('format','%month% %year%');

Но теперь сохранение формы дает ошибку Invalid на этом поле. Конечно: валидатор-то ожидает все три поля. Хорошо, не будем обманывать его ожиданий :) Дописываем в классе формы:

  function doBind(array $values)
  {
    $values['your_month_field_name']['day']=1;
    parent::doBind($values);
  }

вот и все

четверг, 9 декабря 2010 г.

Смена email пользователем

Часто в целях безопасности при регистрации пользователей их просят подтвердить свой email. Средства для генерации письма с подтверждением и экшены проверки кода подтверждения предоставляет, например, плагин sfApply. Однако, тот же плагин довольно топорно решает проблему смены email пользователем:
unset($this['email'])

Иначе говоря, все, кто хочет изменить email, идут лесом: это не разрешается. Как быть тем, кто хочет сделать более дружелюбный интерфейс?

вторник, 2 ноября 2010 г.

Отменяем кэширование CSS

Если вы часто (или хотя бы иногда!) меняете CSS-файлы фронтенда, то имеет смысл подумать над тем, чтобы не вводить в ступор пользователей, которые видят сайт в стилях, закэшированных их браузером. Иными словами, вы поменяли стили, а юзер думает "какого хрена у меня оно так выглядит?".

среда, 21 июля 2010 г.

Делаем "Направленный список чего-нибудь"

Заказчиком была поставлена следующая задача: сделать возможность создавать направленные списки (списки, в которых порядок следования элементов имеет значение), состоящие из произвольных объектов любых моделей проекта. Практическое применение: вывести в определенной последовательности 5 товаров, потом еще 10 товаров (в другой последовательности), затем 7 категорий товаров, и, наконец, 12 новостей (тоже в заранее заданной последовательности). Назовем этот список "рейтингом". Ниже представлена концепция с основными моментами реализации.