Yii 1.1.8
27 июня 2011
Вышел релиз Yii 1.1.8, включающий более 80 багфиксов, новых возможностей и улучшений. Огромное спасибо тем, кто репортил баги, предлагал новые фичи и использовал по назначению Orphus на yiiframework.ru.
Забрать свежий дистрибутив можно с официального сайта.
Инструкции по обновлению можно почитать в UPGRADE.
Полный список изменений, как обычно, можно прочитать в CHANGELOG, мы же бегло рассмотрим самое интересное.
Свои классы для правил URL
Для сложной работы с URL, с которой не может справится стандартный класс CUrlRule
(например, когда часть URL зависит от значений в базе данных), можно написать свои классы для обработки URL и использовать их в конфигурации CUrlManager
:
array( // стандартное правило '/login' → 'site/login' и т.д. '<action:(login|logout|about)>' => 'site/<action>', // нестандартное правило для '/Производитель/Модель' array( 'class' => 'application.components.CarUrlRule', 'connectionID' => 'db', ), // стандартное правило для 'post/update' '<controller:\w+>/<action:\w+>' => '<controller>/<action>', ),
Сам класс при этом наследуется от CBaseUrlRule
и выглядит примерно так:
class CarUrlRule extends CBaseUrlRule { public $connectionID = 'db'; public function createUrl($manager,$route,$params,$ampersand) { if ($route==='car/index') { if (isset($params['manufacturer'], $params['model'])) return $params['manufacturer'] . '/' . $params['model']; else if (isset($params['manufacturer'])) return $params['manufacturer']; } return false; // не применяем правило } public function parseUrl($manager,$request,$pathInfo,$rawPathInfo) { if (preg_match('%^(\w+)(/(\w+))?$%', $pathInfo, $matches)) { // совпадают ли $matches[1] и $matches[3] с // производителем и моделью в базе? // если да, выставляем $_GET['manufacturer'] и/или $_GET['model'] // и возвращаем 'car/index' } return false; // не применяем правило } }
Улучшенный автозагрузчик классов
В Yii уже есть загрузчик классов, подключающий их как только они потребуются. Теперь он не конфликтует со сторонними загрузчиками и может выполняться как до них, так и после. В предыдущих версиях он всегда выполнялся после сторонних автозагрузчиков, что приводило к лишним вызовам при использовании классов Yii:
// По умолчанию сторонний загрузчик регистрируется до загрузчика Yii Yii::registerAutoloader($autoloader);
Теперь можно делать так:
// При передаче true вторым параметром сторонний автозагрузчик добавляется после загрузчика Yii Yii::registerAutoloader($autoloader, true);
По умолчанию автозагрузчик Yii использует PHP include path. Для некоторых хостингов это является проблемой, решить которую можно немного поправив index.php
:
require('path/to/yii.php'); // отключаем PHP include path Yii::$enableIncludePath = false; Yii::createWebApplication($config)->run();
Логирование в режиме реального времени
Некоторые консольные приложения могут работать очень долго. Для них полезно писать сообщения в лог сразу, а не ждать завершения приложения:
// автоматически передаём каждое сообщение роутеру лога Yii::getLogger()->autoFlush = 1; // автоматически пишем сообщения при получении логгером Yii::getLogger()->autoDump = true;
Работаем со счётчиками в БД через AR
В классе CActiveRecord
появился новый метод saveCounters()
, похожий на существующий CActiveRecord::updateCounters()
. Главное отличие — saveCounters()
работает только с текущим объектом в то время как updateCounters()
работает со всей таблицей:
$post = Post::model()->findByPk(1); // наращиваем количество просмотров поста $post->saveCounters(array('views'=>1)); // то же для прошлый версий Post::model()->updateCounters(array('views'=>1), 'id=1');
Генерация файлов переводов
При использовании yiic message
часто приходилось удалять старый файл и заменять его новым, который генерировался рядом. Теперь можно писать сразу в старый файл, если выставить в конфигурации команды опцию overwrite
в true
.
Создание URL в консольных приложениях
В веб-приложениях для генерации URL обычно используется CUrlManager
, который ранее не был доступен консольным приложениям. Теперь и в веб-приложениях и в консольных можно пользоваться Yii::app()->createUrl()
, что очень удобно, например, для построения sitemap, в котором перечисляются URL веб-приложения.
В clips теперь можно использовать параметры
Это полезно в том случае, когда кусок кода в view повторяется много раз, но он недостаточно сложен для выноса его в отдельный файл:
// определяем clip <?php $this->beginClip('hello') <p>Привет, {username}!</p> <?php $this->endClip() <?php // используем clip <?php $this->renderClip('hello',array( '{username}'=>'Qiang', )) <?php $this->renderClip('hello',array( '{username}'=>'Alex', )) <?php $this->renderClip('hello',array( '{username}'=>'Michael', ))
Комментарии RSS по email OK
И это в 2011 году, когда уже всё, что нужно, сказали Matt Zandstra, Martin Fowler и, особенно, Miško Hevery (статический класс, да ещё и с public-полем - сложно представить его реакцию).
Мне в своём коде стыдно видеть такое, но вот они сделали обновление - значит эта фича не является наследием прошлого, могли ведь сделать метод, как минимум.
зря вы так, можно сделать красиво и гибко
c renderClip так же странное решение, раз уж в Yii юзается eval, то стоило бы выделенный кусок евалить, тогда давая возможность пользоваться всеми возможностями шаблонизатора, а не плейсхолдеры. как, например, организовать там цикл?
+1 про клипы.
@OZ
Истинно: каждый раз, когда Фаулер видит подобное, он дёргает волосы на своей голове и в остервенении начинает звать в свою церковь новую паству ещё громче.
@OZ Ну а что тут такого страшного?
OZ, предлагаете везде делать академично и без антипаттернов? Что тогда станет с синтаксисом?
idle, посмотрел ещё раз на фото Фаулера :)
AmdY, красиво и гибко тоже работает. Если есть цикл — скорее всего это тянет на полноценный view partial, но можно подумать и над полноценным PHP через output buffering.
А тегированный кэш не добавили.. я в печали :(
А разве планировали?
Не могу понять это баг или нет?!
http://www.yiiframework.com/forum/index.php?/topic/21032-activerecord-relations-cdbcriteria-behaviour/
пока пришлось добавить метод в ActiveRecord, чтобы реализовать это. Но, вообще, судя по описанию, все должно работать изначально.