Yii 1.1.7
29 марта 2011
На днях вышел релиз 1.1.7 PHP-фреймворка Yii, в который было включено более 90 исправленных ошибок, улучшений и новых возможностей.
Полный список изменений доступен на сайте фреймворка, самые вкусные из которых мы рассмотрим ниже.
Поддержка URL в стиле REST
Теперь при использовании CUrlManager можно указать
метод (GET, POST, PUT и т.д.) в свойстве verb
правила URL.
К примеру, приведённые ниже правила GET
-запрос на post/123
будет обрабатываться
действием post/view
, а PUT
или POST
на post/123
— действием post/update
.
return array( 'components'=>array( 'urlManager'=>array( 'urlFormat'=>'path', 'rules'=>array( array('<controller>/view', 'pattern'=>'<controller:\w>/<id:\d+>', 'verb'=>'GET'), array('<controller>/update', 'pattern'=>'<controller:\w>/<id:\d+>', 'verb'=>'PUT, POST'), ), ), ), );
Получить данные PUT
и DELETE
можно при помощи методов CHttpRequest::getPut() и CHttpRequest::getDelete().
Кэширование запросов
При кэшировании запроса его результат сохраняется в кэш и, в случае повторного запроса берётся оттуда напрямую.
Кэширование запросов реализовано как для DAO, так и для AR. Несколько примеров:
// кэшируем результат выполнения $sql на 1000 секунд или пока не обновится tbl_post $sql = 'SELECT * FROM tbl_post LIMIT 20'; $dependency = new CDbCacheDependency('SELECT MAX(update_time) FROM tbl_post'); $rows = Yii::app()->db->cache(1000, $dependency)->createCommand($sql)->queryAll(); // то же, но для AR $posts = Post::model()->cache(1000, $dependency)->findAll(); // query caching with relational AR $posts = Post::model()->cache(1000, $dependency)->with('author')->findAll();
Привязка параметров для классов действий
В версии 1.1.4 была добавлена поддержка автоматического наполнения параметров для действий контроллера. В этой версии возможность была расширена на действия, описываемые в классах. Пример:
class UpdateAction extends CAction { public function run($id) { // $id будет заполняться данными из $_GET['id'] } }
Прозрачная валидация на клиенте
CActiveForm — мощный виджет, который значительно облегчает создание формы и её валидацию. Раньше он поддерживал только валидацию на стороне сервера и валидацию через AJAX. В данной версии добавлена валидация силами клиента, которая работает быстрее и не нагружает сервер.
Для реализации валидации на клиенте нет необходимости в дополнительном коде. Валидация работает на основе правил модели точно так же, как и валидация на стороне сервера.
Включить валидацию на клиенте можно выставив CActiveForm::enableClientValidation
в true
:
$form=$this->beginWidget('CActiveForm', array( 'enableClientValidation'=>true, )); <div class="row"> <?php echo $form->labelEx($model,'username'); <?php echo $form->textField($model,'username'); <?php echo $form->error($model,'username'); </div> <div class="row"> <?php echo $form->labelEx($model,'password'); <?php echo $form->passwordField($model,'password'); <?php echo $form->error($model,'password'); </div> <div class="row buttons"> <?php echo CHtml::submitButton('Login'); </div> <?php $this->endWidget();
Передача параметров реляционным именованным группам параметров
Теперь можно передавать параметры реляционным именованным группам параметров. К примеру,
если имеется группа rated
в модели Post
, которая принимает параметром минимальный рейтинг записи,
можно использовать это из модели User
следующим образом:
$users=User::model()->findAll(array( 'with'=>array( 'posts'=>array( 'scopes'=>array( 'rated'=>5, ), ), ), ));
Использование 'through' с HAS_MANY и HAS_ONE
В Active Record добавлена поддержка опции through
, которая позволяет строить отношения,
подобные MANY_MANY
, но более гибкие, позволяющие получение и использование данных из
средней таблицы-моста.
К примеру, можно получить все комментарии для всех пользователей определённой группы.
Больше информации и примеров можно найти в соответствующем разделе руководства.
Использование транзакций в миграциях
При выполнении миграции бывают ситуации, когда часть миграции не применяется и требуется откатить всё, что успело примениться. Хорошее решение данной проблемы — обернуть всю миграцию в транзакцию. Конечно, можно сделать это и напрямую, но использование новой возможности более удобно.
Вместо реализации CDbMigration::up() и CDbMigration::down(), можно использовать CDbMigration::safeUp() и CDbMigration::safeDown(). После этого код будет обёрнут в транзакцию:
class m101129_185401_create_news_table extends CDbMigration { public function safeUp() { $this->createTable('tbl_news', array( 'id' => 'pk', 'title' => 'string NOT NULL', 'content' => 'text', )); } public function safeDown() { $this->dropTable('tbl_news'); } }
Стоит отметить, что не все СУБД поддерживают транзакции.
Регистрация и использование своих пакетов скриптов
CClientScript теперь позволяет зарегистрировать и использовать свои пакеты скриптов. Ранее данная возможность использовалась исключительно для внутренних целей.
Пакет может содержать CSS, JavaScript, изображения и любые другие файлы, которые необходимо показать пользователям. Пакет может зависеть от других пакетов. То есть при регистрации пакета все пакеты, от которых он зависит, регистрируются автоматически.
Работа с пакетами строится следующим образом: сначала в CClientScript::packages описываются нужные пакеты, а затем они регистрируются при помощи CClientScript::registerPackage().
Комментарии RSS по email OK
Класс, вечером обновлюсь! Прям пора обновлений какая-то :)
Я бы полностью передкелал все виджеты в yii но времени нет.
класс, молодцы! :) я чувствую этот фремворк вернет славу пхп ) Даешь PHP on Yiis! )))
Самая радостная новость на этой неделе :)
Класс! Привязки параметров для классов действий как раз мне не хватало. Но и кеширование запросов вкусно выглядит. Сейчас мне только очень не хватает хорошего легкого шаблонизатора. А то в вьюшках порой такая каша получается, что прям ужас..
Вопрос по поводу стиля кода: почему вы не предваряете недоступные извне методы классов символом подчеркивания ?
Они и так предварены модификатором
private
.Я про это
Делается для того, чтобы визуально, не заглядывая в код функции, понять, открыта она для использования извне или нет.
Ну так написано
private
. По-моему достаточно красноречиво._ в начале имени метода - это атавизм, привычка оставшаяся со времен php 4, когда все методы были public. Понимаю, некоторым все еще удобнее использовать _ для облегчения чтения кода себе и единомышленникам. Yii полностью поддерживает стандарты php 5. Еще, насчет стандартов кодирования на php - http://www.dagbladet.no/development/phpcodingstandard/#methodsnames . Никаких ведущих подчеркиваний.
Andrei Frolikov, я начал изучать php уже далеко после выхода php5, и никаким образом к php4 отношения не имею, но мне кажется, при просмотре списка методов в классе этот символ очень удобен. Я, видел конечно малое количество проектов, но в них все закрытые методы во всех проектах были предварены этим символом.
Я согласен и мне тоже такое соглашение об оформлении кода кажется удобнее, т.к. читая код и встречая вызов метода с _ в начале, я автоматически понимаю, что он private и мне не нужно дополнительно смотреть его объявление. Возможно, разработчики Yii договорились строго придерживаться PHP Coding Standards.
Другая тема. Sam, на страницах русского руководства на yiiframework.com есть несколько ошибок в переводе, в основном это очепятки. Я посылал письма через форму обратной связи. Мне ответил Qiang Xue, сказав что сообщения по тему переводов отправлять вам на email. Но вот заново просматривать все руководство нет желания, так как ошибки разбросаны по нескольким страницам разных глав. Все копии писем спросите у своего коллеги т.к. на мою просьбу передать копии этих писем мне, чтобы я к вам обратился, никто не ответил.
Morgan, он мне их передал. Спасибо.
А мы ставим _ перед переменной, только, если это какая-то служебная переменная..например, $this->_db.
А можно ли как-то этому повысить приоритет? :) самому пока не хочется делать временный велосипед, но использовать уже хочется. Так бы из транка использовали версию.
http://code.google.com/p/yii/issues/detail?id=2260&sort=-id&colspec=ID%20Type%20Status%20Priority%20Milestone%20Owner%20Stars%20Summary
Можно комментарий к тикету написать с use-case-ами или unit-тестами.
Не могу понять порядок работы CDbCacheDependency он что сначала время кэша проверяет, а потом результат запроса, хотя вроде как наоборот? Потому что у меня ModelName::model()->cache(time, CDbCacheDependency)->findAll() даже после изменения запроса в CDbCacheDependency пишет в запросах старые запросы до изменения и так и достает старый кэш до изменений
Dr.Death, проверяется в таком порядке:
т.е. если в кеше значение имеется, expire ещё не скоро, зависимость даёт отличный результат от того, который был при выставлении значения и при этом отдаётся значение, а не
null
— это баг и нужен как можно более простой код для воспроизведения.А почему зависимости проверяются в последнюю очередь? Ведь если они сменились то не важно есть в кэше или нет, он все равно устарел
Проверяется по очереди:
null
, иначе →2.null
, иначе →3.null
, иначе значение.В таком порядке т.к. зависимости — более тяжёлая операция, чем проверка даты и попытка чтения кеша.
Дак а смысл этих зависимостей? И почему тогда запросы зависимостей выполняются каждый раз на суточном кэше? Может все таки сначала зависимость, иначе как объяснить что мои поделки с 24х часовым кэшем обновляются зависимостями при изменениях?
Внимательней перечитываем предыдущий мой коммент ;)
А как то можно "закэшировать" саму зависимость, чтоб она не вызывалась XX раз за время работы скрипта? При выводе в ней ничего не меняется.
Если и её закэшировать, то зачем она вообще нужна? Может требуется использовать что-то вроде тегирования?
Ну не закэшировать, а просто чтоб если используешь ее 10 раз подряд, то она вызывалась 1 раз, а не 10, может каким параметром мол не проверять повторно...
Dr.Death, на самом деле факт, что ничего не поменяется в процессе отображения верен только в том случае, если редактирует контент исключительно один человек.
нет, не изменится, если за время открытия-показа страницы не происходит показ, изменение, показ, поэтому смысл 10 раз за один показ страницы дергать одну и туже зависимость
С кешированием результата зависимости решение ненадёжное. Наудачу. Чуть больше пользователей, которые редактируют и данные начнут теряться. С тегами намного надёжней.
Мы друг друга не понимаем, "кэшировать" надо только на время просмотра одной страницы, чтоб за время ее генерации не выполнять XX раз один и тот же запрос выбирающий зависимость из базы.
Даже во время формирования этой страницы при достаточной нагрузке данные могу поменяться. Желание не проверять зависимость несколько раз, конечно, понятно, но не подходит для всех возможных случаев. Например, кеш может использоваться не только при отображении данных.