<rmcreative>

RSS

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:

<?php $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

  1. №4241
    Роман
    Роман 29.03.2011, 15:24:51

    Класс, вечером обновлюсь! Прям пора обновлений какая-то :)

  2. №4242
    Ekstazi
    Ekstazi 29.03.2011, 23:09:35

    Я бы полностью передкелал все виджеты в yii но времени нет.

  3. №4243
    Andrei Frolikov
    Andrei Frolikov 30.03.2011, 0:09:33

    класс, молодцы! :) я чувствую этот фремворк вернет славу пхп ) Даешь PHP on Yiis! )))

  4. №4246
    Timlar
    Timlar 30.03.2011, 9:45:00

    Самая радостная новость на этой неделе :)

  5. №4258
    jeicd
    jeicd 30.03.2011, 18:27:04

    Класс! Привязки параметров для классов действий как раз мне не хватало. Но и кеширование запросов вкусно выглядит. Сейчас мне только очень не хватает хорошего легкого шаблонизатора. А то в вьюшках порой такая каша получается, что прям ужас..

  6. №4269
    Morgan
    Morgan 01.04.2011, 19:11:26

    Вопрос по поводу стиля кода: почему вы не предваряете недоступные извне методы классов символом подчеркивания ?

  7. №4270
    Sam
    Sam 01.04.2011, 22:02:29

    Они и так предварены модификатором private.

  8. №4275
    Morgan
    Morgan 03.04.2011, 15:43:08

    Я про это

    private function _test(){}

    Делается для того, чтобы визуально, не заглядывая в код функции, понять, открыта она для использования извне или нет.

  9. №4276
    Sam
    Sam 03.04.2011, 20:15:54

    Ну так написано private. По-моему достаточно красноречиво.

  10. №4277
    Andrei Frolikov
    Andrei Frolikov 03.04.2011, 20:26:35

    _ в начале имени метода - это атавизм, привычка оставшаяся со времен php 4, когда все методы были public. Понимаю, некоторым все еще удобнее использовать _ для облегчения чтения кода себе и единомышленникам. Yii полностью поддерживает стандарты php 5. Еще, насчет стандартов кодирования на php - http://www.dagbladet.no/development/phpcodingstandard/#methodsnames . Никаких ведущих подчеркиваний.

  11. №4278
    Morgan
    Morgan 03.04.2011, 22:12:03

    Andrei Frolikov, я начал изучать php уже далеко после выхода php5, и никаким образом к php4 отношения не имею, но мне кажется, при просмотре списка методов в классе этот символ очень удобен. Я, видел конечно малое количество проектов, но в них все закрытые методы во всех проектах были предварены этим символом.

  12. №4279
    Andrei Frolikov
    Andrei Frolikov 03.04.2011, 22:34:06

    Я согласен и мне тоже такое соглашение об оформлении кода кажется удобнее, т.к. читая код и встречая вызов метода с _ в начале, я автоматически понимаю, что он private и мне не нужно дополнительно смотреть его объявление. Возможно, разработчики Yii договорились строго придерживаться PHP Coding Standards.

  13. №4280
    Morgan
    Morgan 03.04.2011, 23:25:19

    Другая тема. Sam, на страницах русского руководства на yiiframework.com есть несколько ошибок в переводе, в основном это очепятки. Я посылал письма через форму обратной связи. Мне ответил Qiang Xue, сказав что сообщения по тему переводов отправлять вам на email. Но вот заново просматривать все руководство нет желания, так как ошибки разбросаны по нескольким страницам разных глав. Все копии писем спросите у своего коллеги т.к. на мою просьбу передать копии этих писем мне, чтобы я к вам обратился, никто не ответил.

  14. №4284
    Sam
    Sam 04.04.2011, 11:57:30

    Morgan, он мне их передал. Спасибо.

  15. №4286
    Владислав
    Владислав 04.04.2011, 17:05:14

    А мы ставим _ перед переменной, только, если это какая-то служебная переменная..например, $this->_db.

  16. №4300
    Andrey Gayvoronsky
    Andrey Gayvoronsky 05.04.2011, 15:08:36

    А можно ли как-то этому повысить приоритет? :) самому пока не хочется делать временный велосипед, но использовать уже хочется. Так бы из транка использовали версию.

    http://code.google.com/p/yii/issues/detail?id=2260&sort=-id&colspec=ID%20Type%20Status%20Priority%20Milestone%20Owner%20Stars%20Summary

  17. №4301
    Sam
    Sam 05.04.2011, 16:24:26

    Можно комментарий к тикету написать с use-case-ами или unit-тестами.

  18. №4504
    Dr.Death
    Dr.Death 27.04.2011, 0:00:48

    Не могу понять порядок работы CDbCacheDependency он что сначала время кэша проверяет, а потом результат запроса, хотя вроде как наоборот? Потому что у меня ModelName::model()->cache(time, CDbCacheDependency)->findAll() даже после изменения запроса в CDbCacheDependency пишет в запросах старые запросы до изменения и так и достает старый кэш до изменений

  19. №4507
    Sam
    Sam 27.04.2011, 17:04:50

    Dr.Death, проверяется в таком порядке:

    1. Наличие в кеше.
    2. expire.
    3. Зависимости.
  20. №4508
    Sam
    Sam 27.04.2011, 17:07:40

    т.е. если в кеше значение имеется, expire ещё не скоро, зависимость даёт отличный результат от того, который был при выставлении значения и при этом отдаётся значение, а не null — это баг и нужен как можно более простой код для воспроизведения.

  21. №4509
    Dr.Death
    Dr.Death 27.04.2011, 19:13:12

    А почему зависимости проверяются в последнюю очередь? Ведь если они сменились то не важно есть в кэше или нет, он все равно устарел

  22. №4510
    Sam
    Sam 27.04.2011, 19:41:27

    Проверяется по очереди:

    1. Если нет в кеше — вернём null, иначе →2.
    2. Если expire настал — вернём null, иначе →3.
    3. Если зависимости поменялись — вернём null, иначе значение.

    В таком порядке т.к. зависимости — более тяжёлая операция, чем проверка даты и попытка чтения кеша.

  23. №4511
    Dr.Death
    Dr.Death 27.04.2011, 19:44:30

    Дак а смысл этих зависимостей? И почему тогда запросы зависимостей выполняются каждый раз на суточном кэше? Может все таки сначала зависимость, иначе как объяснить что мои поделки с 24х часовым кэшем обновляются зависимостями при изменениях?

  24. №4512
    Sam
    Sam 27.04.2011, 20:39:06

    И почему тогда запросы зависимостей выполняются каждый раз на суточном кэше?

    Внимательней перечитываем предыдущий мой коммент ;)

  25. №4513
    Dr.Death
    Dr.Death 28.04.2011, 13:54:27

    А как то можно "закэшировать" саму зависимость, чтоб она не вызывалась XX раз за время работы скрипта? При выводе в ней ничего не меняется.

  26. №4514
    Sam
    Sam 28.04.2011, 16:54:17

    Если и её закэшировать, то зачем она вообще нужна? Может требуется использовать что-то вроде тегирования?

  27. №4515
    Dr.Death
    Dr.Death 28.04.2011, 16:59:05

    Ну не закэшировать, а просто чтоб если используешь ее 10 раз подряд, то она вызывалась 1 раз, а не 10, может каким параметром мол не проверять повторно...

  28. №4519
    Sam
    Sam 29.04.2011, 16:54:30

    Dr.Death, на самом деле факт, что ничего не поменяется в процессе отображения верен только в том случае, если редактирует контент исключительно один человек.

  29. №4520
    Dr.Death
    Dr.Death 29.04.2011, 20:37:17

    нет, не изменится, если за время открытия-показа страницы не происходит показ, изменение, показ, поэтому смысл 10 раз за один показ страницы дергать одну и туже зависимость

  30. №4522
    Sam
    Sam 30.04.2011, 1:34:30

    С кешированием результата зависимости решение ненадёжное. Наудачу. Чуть больше пользователей, которые редактируют и данные начнут теряться. С тегами намного надёжней.

  31. №4523
    Dr.Death
    Dr.Death 30.04.2011, 22:42:03

    Мы друг друга не понимаем, "кэшировать" надо только на время просмотра одной страницы, чтоб за время ее генерации не выполнять XX раз один и тот же запрос выбирающий зависимость из базы.

  32. №4524
    Sam
    Sam 01.05.2011, 0:00:36

    Даже во время формирования этой страницы при достаточной нагрузке данные могу поменяться. Желание не проверять зависимость несколько раз, конечно, понятно, но не подходит для всех возможных случаев. Например, кеш может использоваться не только при отображении данных.

  1. Почта опубликована не будет.

  2. Можно использовать синтаксис Markdown или HTML.

  3. Введите ответ в поле. Щёлкните, чтобы получить другую задачу.