Новшества Symfony 1.2. Часть первая
Приветствуем!
Хотите что-то написать?Нужно назвать себя.
Если вы пришли в первый раз,
то нужно зарегистрироваться.
Переводы → Новшества Symfony 1.2. Часть первая
Symfony 1.2 уже вышел, пора бы уже и на русский перевести стать о нововведениях в Symfony 1.2 (которымя прямо нарадоваться не могу). Читаем начало перевода и радуемся вместе. Скоро будут остальные куски.
ps: Господа, активней. К выходным уже надеюсь запущу wiki и с такими статьями будет попроще!
Данный урок это быстрое техническое вступление к Symfony 1.2. Оно создано для разрабочиков, которые ранее работали на 1.0 и 1.1, а так же для тех кто хочет быстро ознакомиться с новшествами 1.2
Для сначала стоит отметить что 1.2 совместим с PHP версии 5.2.4 и позднее, тогда как 1.1 работает PHP 5.1 а symfony 1.0 с PHP 5.0.
Если вы решили обновиться с версий 1.1 or 1.0, пожалуйста прочтите файл UPGRADE, который вы найдёте с дистрибутивом. Там вы найдёте всю информацию по безопасному обновлению ваших проекто до symfony 1.2.
Propel
Propel был обновлён до версии 1.3, в котором Creole заменён на PDO, а так же включены некоторые новые возможности: объединение копий объектов, mastert-slave соединения, родная поддержка деревьев(nested-set) и улучшенная манипуляция данными
Конфигурационный файлdatabases.yml теперь использует синтаксис PDO:
dev:
propel:
param:
classname: DebugPDO
all:
propel:
class: sfPropelDatabase
param:
dsn: mysql:dbname=example;host=localhost
username: username
password: password
encoding: utf8
persistent: true
pooling: true
classname: PropelPDO
Немного изменился api транзакий: ->begin был переименован в ->beginTransaction() и ->rollback() переименован в ->rollBack(). Метод ::doSelectRS был переименован в ::doSelectStmt.
Чтобы узнать больше о Propel 1.3, ознакомьтесь с полной документацией на их сайте.
Doctrine
Doctrine теперь элитный житель в symfony 1.2. Это значит что symfony 1.2 теперь объединяет в себе как Doctrine, так и Propel. Весь встроенный функционал доступен для Propel and Doctrine, так что теперь вы свободны выбирать ту ORM, которая вам подходит больше.
Запрос
Теперь вы можете эмулировать запросы браузера PUT и DELETE используя метод POST и добавляя параметр sf_method
<form action="#" method="POST"> <input type="hidden" name="sf_method" value="PUT" /> <!-- // ... --> </form>
Хелпер form_tag() теперь способен генерировать скрытый тег для методов отличных от GET или POST. Поэтому открывающий тэг form может быть создан посредством хелпера form_tag() данным способом:
<?php echo form_tag('#', array('method' => 'PUT')) ?>
Т.к. хелпер link_to() теперь привязан к CSRF ключу, если включена CSRF защита, вы можете проверить ключ, в тот момент, когда нажата ссылка при помощи метода checkCSRFProtection():
public function executeDelete($request) { $request->checkCSRFProtection(); }
Метод checkCSRFProtection() выкинет исключения, если ключа нет или он не верен.
Формы
Древовидные формы
Самым главным ограниченем форм Propel в symfony 1.1 была невозможность автосохранения привязанных форм. Это было внедерно в symfony 1.2. Теперь, сохраняя форму Propel, symfony будет автоматом сохранять основной объект, а так же все объекты привязанных форм.
Новые методы sfForm
Метод sfForm::renderFormTag() генерирует открывающий тег form для текущей формы. Так же он добавляет атрибут enctype если того требует форма, а так же создаёт скрытый тег, если метод не GET or POST:
<?php echo $form->renderFormTag('@article_update', array('method' => 'PUT')) ?>
Класс sfFormPropel перегружает renderFormTag() для автоматической смены HTTP метода, основанно на связанном объекте: если объект новый, то метод будет POST, а если объект уже существует, то метод будет PUT.
Метод sfForm::hasErrors() возвращает true если ошибки были найдены или же false в обратном случае. Данный метод возвращает false если форма не привязана. Данный метод весьма полезен в шаблонах:
<?php if ($form->hasErrors()): ?> В форме есть ошибки, надо бы их пофиксить <?php endif; ?>
Метод sfForm::renderUsing() позволяет рендерить форму используя особый форматтер набора виджетов. Она позволяет использовать форматтер прямо в шаблоне:
// в шаблоне, форма будет отображена с использованием форматтера "list" echo $form->renderUsing('list');
Метод sfForm::renderHiddenFields() возвращает HTML для скрытых виджетов. Данный метод может пригодиться, если поля формы рендерятся отдельно:
<form action="<?php echo url_for('@some_route') ?>"> <?php echo $form->renderHiddenFields() ?> <ul> <?php echo $form['name']->renderRow() ?> </ul> <input type="submit" /> </form>
Методы sfForm::getStylesheets() и sfForm::getJavaScripts() возвращают файл стилей и JavaScript'ов, необходимых для отображения формы. Данные файлы могу быть определены в самой форме через перегрузку данных методов, или даже каждым из виджетов (подробнее в параграфе про Виджеты).
В шаблоне вы можете использовать хелперы include_javascripts_for_form() и include_stylesheets_for_form() для отображения скриптов и стилей. Обе функции принимаю объект формы в виде аргумента:
<?php include_javascripts_for_form($form) ?> <?php include_stylesheets_for_form($form) ?>
sfForm применяет интерфейсы Iterator и Countable для более лёгких итераций по полям формы в шаблоне
<ul> <?php foreach ($form as $field): ?> <li><?php echo $field ?></li> <?php endforeach; ?> </ul>
Проверенные переменные и их предобработка
Бы добавлена предобработка проверенных переменных перед обновлением объекта Propel.
Если вы хотите предобработать значение, то вам нужно добавить метод updateXXXColumn() в вашу форму, где XXX это PHP-имя вашей колонки в Propel.
Данный метод должен возвращать обработанную переменную или false чтобы удалить значение из массива проверенных переменных:
class UserForm extends sfFormPropel { // ... protected function updateProfilePhotoColumn($value) { // если пользователь не отправил profile_photo, // удалим данное значение // т.к. как мы хотим сохранить оригинал if (!$value) { return false; } // удаляем старое фото // сохраняем новое фото на диск // изменяем имя файла на новое return $filename; } }
Валидаторы
sfValidatorSchemaCompare
Константы класса sfValidatorSchemaCompare были изменены. Изменять ваш код не потребуется, но теперь у вас будут замечательные ярлыки. Данные два случая равносильны:
// symfony 1.1 and 1.2 $v = new sfValidatorSchemaCompare('left', sfValidatorSchemaCompare::EQUAL, 'right'); // symfony 1.2 only $v = new sfValidatorSchemaCompare('left', '==', 'right');
sfValidatorChoice
sfValidatorChoice теперь имеет опцию multiple, которая позволяет ему работать как sfValidatorChoiceMany.
sfValidatorPropelChoice так же имеет опцию multiple и работает как sfValidatorPropelChoiceMany.
sfValidatorDateRange
symfony 1.2 предлагает новый валидатор sfValidatorDateRange для проверки области дат.
sfValidatorFile
Класс sfValidatedFile стал более гибким в области сохранения файлов.
Его конструктор теперь принимает новы аргумент - путь сохранения файлов.
Так что теперь, при сохранении файлов вы можете:
-
передать абсолютное имя файла, как и раньше:
$file->save(sfConfig::get('sf_uploads_dir').'/filename.pdf');
-
передать относительный путь (symfony его всё равно сделает абсолютным):
$file->save('filename.pdf');
-
передать
null. Имя файла будет сгенерировано при помощи методаgenerateFilename():$file->save();
Кроме того, метод save() возвращает имя сохранённого файла относительного аргумента $path.
Так как объект класса sfValidatedFile создаётся валидатором sfValidatorFile, новая опция path в последстии просто передаётся в конструктор класса sfValidatedFile:
$this->validatorSchema['file'] = new sfValidatorFile(array('path' => sfConfig::get('sf_uploads_dir')));
Класс sfFormPropel принимает на себя данные улучше для автоматизации сохранения файлов свзязаннх с объектов Propel. Спасибо новому методу saveUploadedFile().
Так что, если у вас есть объект Propel с полем file и вы передадите путь валидатору для file в вашей форме, symfony обо всё для вас позаботится:
-
Если файл не был загружен в форму:
- ничего не делаем и ничего не меняем в базе данных
-
если файл залит через форму
- удалем старый файлы
- сохраняет новый
- устанавливаем значение поля
file(относительно данному пути)
В соотвествующем действии модуля вы можете лишь использовать $this->form->save() для сохранения объекта и файла.
Symfony так же вычислит уникальное имя файла используя хэш и добавив предполагаемое расширение файла. Если вы хотите изменить имя файла, то достаточно будет создать метод generateXXXFilename() в вашем объекте, где XXX это PHP имя вашего поля с файлом. Методу передаётся объект sfValidatedFile
public function generateFileFilename(sfValidatedFile $file) { return $this->getId().$file->getExtension($file->getOriginalExtension()); }
Конечно вы можете создать и методupdateXXXColumn(), который мы видели ранее, чтобы переписать данное поведение и управлять процессом загрузки файлом самостоятельно.
sfValidatorI18nChoiceCountry and sfValidatorI18nChoiceLanguage
Валидаторы sfValidatorI18nChoiceCountry и sfValidatorI18nChoiceLanguage требовали опцию culture в symfony 1.1. Т.к. данная опция не использовалась в этих валидаторах, то culture теперь запрещена. Больше вам не придётся ломать голову над обратной совместимостью.
Установка дефолтных значений для сообщение об ошибках на коды required и invalid
Было добавлено 2 новых метода в класс sfValidatorBase позволяющие определить стандартные сообщения на коды ошибков required и invalid:
sfValidatorBase::setRequiredMessage('Поле нужно заполнить'); sfValidatorBase::setInvalidMessage('Значения для данного поля неверно');
Виджеты
Опции виджетов
У всех виджетов появилась опция default. Данная опция устанавливает дефолтное значение:
$widget = new sfWidgetFormInput(array('default' => 'default value')); $widget->setDefault('default value'); echo $widget->getDefault();
Вы так же можете проставить стандартные значения для групп виджетов:
$widget = new sfWidgetFormSchema(...); $widget->setDefaults(array('name' => 'default value')); $widget->setDefault('name', 'default value'); var_export($widget->getDefaults());
Данные стандартные значения берутся в расчёт, если вы не используете стандартные значения для формы.
У всех виджетов появилась опция label. Данная опция позволяет установить лейбл в рамках группы виджетов:
$widget = new sfWidgetFormInput(array('label' => 'Enter your name here')); $widget->setLabel('Enter your name here'); echo $widget->getLabel();
JavaScript'ы и стили виджетов
Виджеты теперь могут определять скрипты и стили, необходимые для их отрисовки, через методы getJavaScripts() и getStylesheets():
class MyWidget extends sfWidgetForm { public function getJavaScripts() { return array('/path/to/a/file.js'); } public function getStylesheets() { return array('/path/to/a/file.css' => 'all', '/path/to/a/file.css' => 'screen,print'); } }
Метод getJavaScripts() вернёт массив файлов Javascript. Метод getStylesheets() массив с файлами в виде ключей и формат отображения (media) в виде значений.
Новые виджеты
symfony 1.2 приносит нам несколько новых виджетов:
sfWidgetFormDateRangesfWidgetFormFilterInputsfWidgetFormFilterDatesfWidgetFormI18nSelectCurrencysfWidgetFormSelectCheckbox
"Семья" sfWidgetFormChoice
Появилась так же новая семьа виджетов типа choice:
sfWidgetFormChoicesfWidgetFormChoiceManysfWidgetFormPropelChoicesfWidgetFormPropelChoiceMany
Стандартно данные виджеты ведут себя как их предшественники Select. Но они являются обёрткой поверх виджетов sfWidgetFormSelect, sfWidgetFormSelectRadioи sfWidgetFormSelectCheckbox. Они используют один из трёх данных виджетов для отображения. Для смены стандартного виджета есть несколько опций:
expanded:- Если false, то будет тег
select - Если true и
multiplefalse, то увидит список радиокнопокradio - Если true и
multipleтоже true, тогда увидим список теговcheckbox
- Если false, то будет тег
renderer_options: Создавая виджет (select,radio,checkbox), вы передаёте этот параметр, включающий в себя опцииrenderer_class: Класс, который заменяет стандартныйrenderer: Вы можете напрямую передать виджет (предыдущие опции будут переписаны).
А вот и пример:
$widget = new sfWidgetFormPropelSelect(array('model' => 'Article')); // is equivalent to $widget = new sfWidgetFormPropelChoice(array('model' => 'Article')); // change the rendering to use a radio list $widget->setOption('expanded', true); // create a multiple select $widget = new sfWidgetFormPropelChoiceMany(array('model' => 'Article')); // change the rendering to use a checkbox list $widget->setOption('expanded', true);
Данные виджеты теперь используются для генерация форм Propel'а
Ответ
sfWebResponse::getCharset()
Метод sfWebResponse::getCharset() возвращает текущую кодировку ответа. Данная кодировка автоматически обновляется, если вы указали тип контента.
sfWebResponse::getStylesheets() и sfWebResponse::getJavascripts()
Методы getStylesheets() and getJavascripts() теперь могут возвращать все стили и JavaScript'ы в определённом порядке, если вы передали sfWebResponse::ALL в качестве первого аргумента:
$response = new sfWebResponse(new sfEventDispatcher()); $response->addStylesheet('foo.css'); $response->addStylesheet('bar.css', 'first'); var_export($response->getStylesheets()); // выводит array( 'bar.css' => array(), 'foo.css' => array(), )
sfWebResponse::ALL теперь являет стандартным аргументов для позиций.
Prototype и Scriptaculous
В symfony, 1.2 встроенны библиотеки Prototype и Scriptaculous и связанные с ними хелперы (JavascriptHelper) теперь перемещены в основной плагин.
Основые плагины ведут себя как и все обычные плагины, поставляемые с symfony. Это позволит JavaScript и CSS файлам класса sfProtoculousPlugin (более менее подходящее название для данного дуэта) вести себя как обычный набор плагинов. Теперь всё лежит в web/sfProtoculousPlugin,а не в web/sf (как это было 1.0 и 1.1). Опцияprototype_web_dir так же указывает на данную директорию.
В дополнение к этому javascript хелперы, которые могу быть применены к любому JS фреймворку были вынесены в JavascriptBaseHelper который остаётся в ядре.
Так же, javascript_tag() теперь может весит себя как slot(). Это позволяет делать подобное:
<?php javascript_tag() ?> alert('All is good') <?php end_javascript_tag() ?>
Коментарии:
Комментарий удалён
Спасибо, очень полезная статья, узнал много нового. Особенно про связанные объекты в формах Propel/Doctrine
ответить



