Pull to refresh

Пишем плагины

Reading time 4 min
Views 666
Как всегда началось все с того, что мне не подошли готовые решения из хранилища плагинов для symfony. Точнее сказать — готовые решения просто не работали, но это уже совсем другая история.

Сегодня я хотел бы поделиться своим опытом и знаниями о том, как писать плагины для symfony. И так как я буду описывать все то, что надо делать, на своем примере, побочным эффектом будет дополнительная информация о том, как создавать виджеты и валидаторы для форм (sfForm).

И так ниже вы узнаете:
  • Как создавать плагины
  • Как писать виджеты для sfForm
  • Как писать валидаторы к этим виджетам

Пишем плагин! В моем случае это плагин для отображения капчи в форме регистрации (в любой форме, не важно). Хотелось бы сказать, что плагин это тот же самый модуль, с тем лишь условием, что все скрипты (файлы) объединены в одном месте, а именно в директории «plugins» проекта. В связи с этим первым шагом необходимо создать директорию с названием идентичным названию вашего плагина, в моем случае это «sfVirCaptchaPlugin».

Мне хотелось универсальности при создания плагина и основные настройки я вынес в конфигурационный файл. Для этого я в директории «sfVirCaptchaPlugin» создал поддиректорию «config», там соответственно создал файл «app.yml» примерно со следующим содержанием:
all:
sfVirCaptcha:
width: 40
height: 20


Затем занялся написанием непосредственно класса генерирующего капчу (саму логику я пожалуй опущу, если кому интересно, как делать капчи и прочее, я уверен что поиск по хабру даст вам не меньше 10 результатов, данный же пост совсем о другом). И так создаем еще одну поддиректорию «lib» (надо предупредить, что авто-загрузчик в symfony парсит отнюдь не все директории, поэтому старайтесь придерживаться стандартных названий директорий). В «lib» создаем файл «sfVirCaptcha.php»:
<?php

class sfVirCaptcha
{
public function __construct()
{
// Те самые значения из app.yml
$this->width = sfConfig::get('app_sfVirCaptcha_width');
$this->height = sfConfig::get('app_sfVirCaptcha_height');
}

/**
* Генерация капчи
*
* @return image
*/
public function get()
{
$captcha = imagecreate($this->width, $this->height);
// ...процесс генерации картинки опускаю, дабы избежать флуда в комментариях ;)
// Сохраняем код в сессию для последующей проверки
sfContext::getInstance()->getUser()->setAttribute('sfVirCaptcha', $code);
return $captcha;
}

/**
* Проверка полученного из формы кода
*/
public static function Validate($value)
{
if (sfContext::getInstance()->getUser()->getAttribute('sfVirCaptcha') == $value) {
return true;
}
return false;
}
}

?>


Таким образом у нас готов класс генерирующий капчу и проверяющий введенный код на правильность. Самое время заняться action'ом, который нам будет отдавать картинку (качпу). Создаем директорию «modules», в ней директорию «sfVirCaptcha», далее «actions», а уже там файл «actions.class.php» содержащий в себе:
<?php

class sfVirCaptchaActions extends sfActions
{
public function executeIndex(sfWebRequest $request)
{
// Установка в заголовки страницы Content-type
$this->getResponse()->setContentType('image/png');
// Получение капчи
$sfVirCaptcha = new sfVirCaptcha();
// Выдача (отображение) капчи
imagepng($sfVirCaptcha->get());
// Отказ от использования layout'ов и template'ов в данном action'е
return sfView::NONE;
}
}


Теперь по запросу project/sfVirCaptcha мы получаем готовую картинку (капчу).

Следующим этапом в создании плагина определим написание виджета для формы. Для этого необходимо в ранее созданной директории «lib» создать файл «sfWidgetFormVirCaptcha.php»:
<?php

// Создаем класс, который наследуется от sfWidgetForm
class sfWidgetFormVirCaptcha extends sfWidgetForm
{
// Определяем стандартный для виджетов метод configure
protected function configure($options = array(), $attributes = array()) {
$this->addOption('type', 'text');
$this->setOption('is_hidden', false);
}

// Рендерим html-код, который будет вставлен непосредственно в форму
public function render($name, $value = null, $attributes = array(), $errors = array()) {
$result = $this->renderTag('input', array_merge(array('type' => $this->getOption('type'), 'name' => $name, 'value' => $value), $attributes));
$result .= '  ';
return $result;
}
}

?>


Не откладывая в долгий ящик следом создаем валидатор для этого виджета, создаем в той же директории «lib» файл «sfValidatorVirCaptcha.php»:
<?php
// Создаем класс, который наследуется от sfValidatorBase
class sfValidatorVirCaptcha extends sfValidatorBase {
// Определяем стандартный для валидаторов метод configure
protected function configure($options = array(), $messages = array()) {
parent::configure($options, $messages);
}

// Метод, который непосредственно валидирует переданное значение
protected function doClean($value) {
$value = (string) $value;
// Пользуемся прежде созданным методом Validate класса sfVirCaptcha
if (!sfVirCaptcha::Validate($value)) {
throw new sfValidatorError($this, 'invalid', array('value' => $value));
}
return $value;
}
}

?>


И вот! Плагин готов! Теперь можно вставлять капчу в любую форму. Пример формы регистрации:
<?php

class UserRegistrationForm extends sfForm
{
public function configure()
{
$this->setWidgets(array(
'login' => new sfWidgetFormInput(),
'password' => new sfWidgetFormInputPassword(),
'captcha' => new sfWidgetFormVirCaptcha(),
));

$this->setValidators(array(
'login' => new sfValidatorString(array('min_length' => 3, 'required' => true)),
'password' => new sfValidatorString(array('min_length' => 3, 'required' => true)),
'captcha' => new sfValidatorVirCaptcha(),
));

$this->widgetSchema->setNameFormat('user[%s]');
}
}



Вот собственно и все. Ан нет… забыл, что необходимо прописать данный плагин в settings.yml, и почистить кеш, а вот после этого можете смело им пользоваться.

P.S. Написано несколько скомкано, но голова и так под вечер работает плохо, а желание поделиться опытом огромное. Если кому что-то не понятно спрашивайте, я обязательно постараюсь ответить.
Tags:
Hubs:
+19
Comments 43
Comments Comments 43

Articles