Вышла новая версия PHP-фреймворка Yii, включающая в себя более 80 улучшений и исправлений. Инструкции по установке и обновлению можно найти по адресу. Стоит отметить, что в релиз вошли четыре небольших изменения, которые могут повлиять на работу существующих приложений. Обязательно прочитайте UPGRADE.md.


Спасибо замечательному сообществу за отличные пулл-реквесты и обсуждения. Без вас этого релиза не было бы! За процессом разработки Yii 2 можно начать следить, поставив звёздочку на GitHub. Подписывайтесь на наш Twitter и Facebook. Обсудить релиз можно в комментариях.


Полный список изменений можно найти в CHANGELOG. Далее мы рассмотрим наиболее интересные.


URL


Новый класс yii\web\UrlNormalizer позволяет нормализовать запросы на URI с присутствующим или отсутствующим слешем в конце, что довольно важно для поисковой оптимизации. Подробное описание можно найти в разделе «URL normalization» официального руководства.


Миграции


Помимо небольших исправлений миграции получили и довольно значительное улучшение. Теперь можно запускать миграции из нескольких мест одновременно, если использовать для них пространства имён. Чтобы это сделать, необходимо настроить свойство migrationNamespaces консольного контроллера:


return [
    'controllerMap' => [
        'migrate' => [
            'class' => 'yii\console\controllers\MigrateController',
            'migrationNamespaces' => [
                'app\migrations',
                'some\extension\migrations',
            ],
            //'migrationPath' => null, //можно отключить миграции без пространств имён
        ],
    ],
];

Обработка ошибок


Ошибки при записи и чтении сессии теперь не скрываются в отладочном режиме, что позволяет легко выявить большинство проблем на этапе разработки.


Request


Появился новый метод yii\web\Request::getHostName(), возвращающий имя хоста для текущего запроса.


Не POST запросы, кодированные как multipart/form-data (например, загрузка файлов) теперь можно распарсить через yii\web\MultipartFormDataParser. Для того, чтобы этим воспользоваться, вы должны настроить Request::parsers следующим образом:


return [
    'components' => [
        'request' => [
            'parsers' => [
                'multipart/form-data' => 'yii\web\MultipartFormDataParser'
            ],
        ],
        // ...
    ],
    // ...
];

После этого следует вызвать Request::getBodyParams() и запрос будет разобран в соответствующие переменные. В том числе в $_FILES.


Базы данных


Было добавлено новое поведение для ActiveRecord. yii\behaviors\AttributeTypecastBehavior позволяет автоматически приводить типы значений атрибутов.


Типы задаются через attributeTypes:


use yii\behaviors\AttributeTypecastBehavior;

class Item extends \yii\db\ActiveRecord
{
    public function behaviors()
    {
        return [
            'typecast' => [
                'class' => AttributeTypecastBehavior::className(),
                'attributeTypes' => [
                    'amount' => AttributeTypecastBehavior::TYPE_INTEGER,
                    'price' => AttributeTypecastBehavior::TYPE_FLOAT,
                    'is_active' => AttributeTypecastBehavior::TYPE_BOOLEAN,
                ],
                'typecastAfterValidate' => true,
                'typecastBeforeSave' => false,
                'typecastAfterFind' => false,
            ],
        ];
    }

    // ...
}

Если attributeTypes не задан, значение будет определяться автоматически на основе правил валидации:


use yii\behaviors\AttributeTypecastBehavior;

class Item extends \yii\db\ActiveRecord
{
    public function rules()
    {
        return [
            ['amount', 'integer'],
            ['price', 'number'],
            ['is_active', 'boolean'],
        ];
    }

    public function behaviors()
    {
        return [
            'typecast' => [
                'class' => AttributeTypecastBehavior::className(),
                'owner' => $this,
                // 'attributeTypes' будет задан автоматически на основе `rules()`
            ],
        ];
    }

    // ...
}

Также был добавлен yii\mutex\OracleMutex — реализация блокировки возможностями Oracle.


Консоль


В консоли теперь можно вызвать описание команды передав -h или --help.


Тестирование


Шаблоны приложений были изменены, чтобы работать с недавними изменениями в Codeception. Подробнее об этом можно прочитать в новом разделе на сайте Codeception: «Yii 2.0 quickstart guide». Если вы используете шаблон проекта advanced, ознакомьтесь с его документацией по тестированию.

Поделиться с друзьями
-->

Комментарии (40)


  1. mhthnz
    20.10.2016 16:09

    За поведение спасибо) а то постоянно в changedAttributes ерунду получал.


  1. samizdam
    20.10.2016 17:45

    Почему бы не использовать semver?


    1. SamDark
      20.10.2016 17:53

      Мы его используем. Полная версия — 2.0.10.0. Просто чистые патч-релизы получаются не часто. В основном, когда крупно налажали и латаем на ходу (пока такое было, кажется, один раз за всё существование Yii).


      1. samizdam
        20.10.2016 18:01

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


        1. Big
          20.10.2016 18:18
          +1

          Они используют такое соглашение по наименованию версий — 2.MAJOR.MINOR.PATCH (сейчас сменился MINOR с 9 на 10)


        1. Mendel
          22.10.2016 13:50
          +1

          Ну да, правильно писать что-то вроде yii2 версия 0.10.0 а не yii версия 2.0.10.0 но композер так тоже понимает, так что чего уж нарушать исторически сложившийся шаблон.
          ПС: да, для нуля особые правила, я помню.


  1. naquad
    20.10.2016 18:21

    Круто! Очень радует, что фреймворк живее всех живых :)

    Хотелось бы ещё узнать как по поводу зависимостей от клиентских библиотек? Когдато на Хабре проскакивала статья, о том, что есть планы их убрать подальше. Это в планах осталось или от этого отказались?


    1. SamDark
      20.10.2016 18:21
      +1

      Да, планы есть. В 2.1 или 2.2 сделаем.


      1. ju5tify
        25.10.2016 15:13
        -2

        Это же очень хорошо. От этой костыльной fxp-ссанины рыгать хочется.


    1. SOKOJI
      20.10.2016 23:03

      На 2.1 запланировано, если не ошибаюсь.


  1. alexantr
    20.10.2016 23:03
    +1

    Хорошее обновление.
    Правда, заметил одну ошибку в инструкциях по установке на сайте yiiframework.com. Для Composer Asset Plugin указана минимальная версия 1.1.1, хотя с версии 2.0.9 нужен как минимум 1.2.0.


    1. SamDark
      23.10.2016 11:34

      Поправил.


  1. nepster09
    21.10.2016 10:00
    +1

    Я давненько по рабочей необходимости перебрался на laravel5, однако продолжаю следить, как там у Yii2 дела продвигаются, так вот возможно я что-то пропустил или не знаю, но есть следующий список фитч, которых нет в (или я об этом не знаю):

    Seeds: — возможность наполнения базы данных тестовыми данными. В Yiii2 такое можно делать в миграциях, однако в laravel5 это сделанно в виде отдельной команды, что дает возможность получить как голую схему базы данных, так и заполнить ее тестовыми данными.

    Composers: — весьма интересная штука, которая позволяет внедрять данные в одну и/или более вьюшек. Что-то похожее на виджеты, такой себе класс, который может содержать логику и передать некоторые данные в вид. Что бывает удобно, например когда нужно передать одни и те-же данные в несколько страниц.

    Middleware: — во круг этого крутилось множество обсуждений, но я упустил конкретный ответ. Все останется по прежнему, тоесть поведения (фильтры и тп.) или все-же Middleware будут жить в Yii2?
    (хеш тег: Yii2, give a chance to Middleware)

    Requests: — спорная штука, но иногда удобно. Во первых вынос валидации из модели в отдельный спец. класс, а во вторых можно сделать так, что пока валидация не пройдет, мы даже до экшина не дойдем.

    И так-же присоединяюсь к тому, что нужно разбить Yii2 на отдельные компоненты. Что мне нравится в этом инструменте, что почти о любом наркоманстве, о котором я могу подумать, оно уже есть. Я имею ввиду хелперы или вспомогательные методы (например сравнение 2 объектов активрекорд https://github.com/yiisoft/yii2/issues/9036, equals вместо === и много еще чего интересного в хорошем смысле).

    Однако по факту есть разные области применения Yii2 и не всегда это просто сайт. что делает более 50% функционала просто не нужными в зависимости от определенных ситуаций.

    В общем было бы здорово получить комментарии от разработчиков по теме.


    1. wispoz
      21.10.2016 10:27
      +2

      Аналог Seeds — это Fixtures
      http://www.yiiframework.com/doc-2.0/guide-test-fixtures.html


    1. SamDark
      21.10.2016 11:39
      +1

      Seeds — fixtures.


      Composers — может быть удобно в отдельных случаях, но вообще штука спорная. Таскает данные довольно неявно. Легко просадить производительность, легко перекрыть локальной переменной, не сильно приятно дебажить, когда не ясно сходу, откуда прилетела переменная.


      Middleware — не в 2.1, но мы не перестаём обдумывать, нужно ли оно и в каком виде. По сути у нас уже примерно то же, только не по PSR. Используется извне, например, Codeception.


      Про Requests не понял, про что именно речь. Можно ссылку?


      И так-же присоединяюсь к тому, что нужно разбить Yii2 на отдельные компоненты.

      Да, потихоньку делаем. С каждой версией что-то будет уезжать из ядра.


      Однако по факту есть разные области применения Yii2 и не всегда это просто сайт. что делает более 50% функционала просто не нужными в зависимости от определенных ситуаций.

      Факт. Хотя даже у REST API исключительно под телефоны есть лендинг...


      1. nepster09
        21.10.2016 14:55

        Seeds — fixtures. Да, я когда-то сталкивался, но поработать не довелось. Засовывал данные в миграции.

        Согласен с Composers, но можно придерживаться неких правил именования например: $composerMyVar.
        Тоесть все переменные, которые начинаются с composer будут приходить именно от туда, очевидно, понятно и сложнее перетереть.

        https://laravel.com/docs/5.3/requests
        По сути в 2 словах, я могу гарантировать, что в контроллере будут уже валидные данные. Вот кстате не большой пример https://mattstauffer.co/blog/laravel-5.0-form-requests.

        «Факт. Хотя даже у REST API исключительно под телефоны есть лендинг...», он может быть сделан на другой платформе или с помощью angular2 и тп.


        1. SamDark
          21.10.2016 15:01

          Согласен с Composers, но можно придерживаться неких правил именования например: $composerMyVar.
          Тоесть все переменные, которые начинаются с composer будут приходить именно от туда, очевидно, понятно и сложнее перетереть.

          Не знаю… костыльно как-то.


          https://laravel.com/docs/5.3/requests

          По сути это form model.


          1. nepster09
            21.10.2016 16:02

            Да, но тут удобно еще. что Laravel5 сам все инжектит и проделывает. Плюс я после Yii2 достаточно быстро привык к тому, что в Laravel5 все разбили очень жестко. Это весьма удобно, в Yii2 вы как-то все соединили очень жестко. Тоесть то, что по факту можно расписать в 5 классов, влазит в одну модель.


            1. Mendel
              22.10.2016 14:23
              +1

              А зачем разделять?
              У любого правила цель одна — повысить эффективность.
              Вот многие ругают Yii за то, что валидация в модели. мол не SOLID-но.
              Но ТАК УДОБНЕЕ. Я когда начал писать свой фреймворк, то пошел по пути Юии.
              Потом углубился в этом подходе еще больше. У меня правила это не только валидация а просто правило работы с полем. У него есть и свой аналог авфтерЛоад и бефорСаве (привязанные к конкретному полю), и валидация и другие обработчики. Выходит если я указал полю правило int то я этим сказал что оно при загрузке из базы приводится к целому, при валидации — приводится и валидируется. Повесил на него defaultValue и при чтении значения из поля — NULL меняется на значение, но оно не попадает в базу, а остается NULL, а указав defaultSaveValue наоборот — при сохранении оно сохранится. Так удобно. Да, более «кошерно» было бы сделать например так как сделали тут — отдельным поведением. Но зачем? В тех 5% случаев где стандартного поведения не хватит можно будет просто создать свое правило, благо они простые и копипаст никто не отменял.
              В особо сложных случаях можно и методы в модели соответствующие переопределить.
              Потом я пошел еще дальше. Я вынес связи в правила. Ведь и поле и связь это виртуальное свойство объекта. Зачем? Ну тут больше упрощение кода из соображений солидности чем удобство работы, но удобство не страдает, и можно всегда довесить на это виртуальное поле другие правила, или даже заменить его без изменения прочего кода, что дает большую гибкость.

              следующая итерация у меня была еще более спорная. К ней и веду:
              Значительная часть контроллеров представляли из себя CRUD в админке.
              У меня есть базовый контроллер у которого есть виджет выводящий форму, которая активформ, но разбитая сразу на закладки. Когда у объекта полсотни полей, то всегда удобно вынести их по разным закладкам. Естественно чтобы не перечислять поля по закладкам это выносится в настройки. Держать эти настройки во вьюве неудобно. Мы плодим лишние шаблоны. Которые не отличаются.
              По факту место настройкам разделяющим поля по группам — в контроллере.
              Так и сделал.
              Но в процессе реальной разработки часто бывает поля появляются и исчезают.
              При таких изменениях нужно отразить изменение в конфиге модели, в конфиге контроллера и в языковом файле. Лезть в три файла муторно. Проще в два, ибо от языка особо не избавишься, тут ломается функционал. Поэтому настройки разделения полей модели на группы я унес в настройки модели. Это может и не так кошерно, но это практично и экономит время разработки, уменьшает колво ошибок и все такое.

              Не призываю к тому чтобы идти моим путем. Я лишь защищаю рациональность того чтобы валидация была в модели. Так удобнее.


              1. nepster09
                22.10.2016 14:45
                +1

                а Вы понимаете, что такое модель?


                1. Mendel
                  22.10.2016 15:24
                  +1

                  В данном контексте речь идет про AR. Но смешивание этих понятий не так уж и важно.
                  Модель отображает нечто из предметного мира в програмном окружении. Данные, объект и т.п.
                  Я понимаю что сферическая модель может быть вообще без атрибутов и явно не влазить в паттерн активРекорд, но на практике важнее удобство в 90% случаях, которое не лишает возможности пусть и менее удобно решить оставшиеся 10% задач.
                  А так то Ваш вопрос уж очень общий.
                  В стиле Ларавел.) Не согласны — скажите в чем. Увидели ошибку, пусть даже терминологическую — скажите где. А так то звучит стремновато. Раскройте мысль, будьте добры.


                  1. nepster09
                    22.10.2016 15:42
                    +1

                    Речь скорее о подходах как laravel5, так и Yii2, в этих инструментах сидит ActiveRecord, за несколько лет работы с ним, у меня почему-то начинает вырабатываться дикая аллергия на него. Так-как по большей части в сообществах принято считать, что модель == 1 файл (а точнее класс унаследованный от ActiveRecord).

                    Но если чуть-чуть покапать, поделать проекты с более сложной логикой и с весьма длительной поддержкой, то ActiveRecord породит достаточно много проблем.

                    Я прошел и до сих пор прохожу через множество адских штук, которые были рождены именно благодаря ActiveRecord. Это скорее претензия не к вам конкретно, а наверно для множество новичков или людей, которые порождают божественные классы, дублируют логику, суют ее во вьюшки и еще очень много интересных вещей делают.

                    Я не могу сказать, что я стал хорошо разбираться в этом всем деле, так как еще до сих пор обжигаюсь, но то, что мне достается из легаси кода на инструментах с использованием ActiveRecord оставляет желать лучшего.

                    Вообще изначально под моделью подразумевается бизнес логика по хорошему состоящая из множество различных классов, что улучшает читабельность кода, поддержку и в целом благоприятно влияет на проект. Хорошим примером будет domain model, при чем не обязательно в контексте DDD.

                    Я так-же согласен, что ActiveRecord это дико удобная штука, с ее помощью можно весьма быстро и удобно работать, очень просто делать реляции, различные связи и сократить код. Однако это удобство несет в себе весьма скрытую опасность, и если вам нужна длительная поддержка, жирная бизнес-логика, удобство и гибкость, то с ActiveRecord будет весьма сложно и сложнота будет стремиться к невозможному.

                    И самый больный пример из своего опыта, который я могу примести это примерно следующая ситуация:
                    Представьте, что вы работаете в небольшой конторе по разработке WEB-проектов различной сложности. Штат предположим из 5 бэкендеров в вашем подчинении. 3 из них джуны, 1 что-то похожий на мидла и вы тоже мидл, такой себе среднячковый (это я возможно о себе). Вы распределяете работу, пишите задачи, сроки горят, туда сюда, быстрее и вот потом когда вы смотрите на код работающего проекта, то все правки и доработки туда вносятся начиная с комментария «Отче наш, сущий на небесах ...».

                    Конечно это не проблема Yii2 или Laravel5, или вообще AR. Но сложилось как сложилось и глубокая связанность, а особенно размазанная логика весьма сложно исправляется.
                    В доменной же моделе, когда все разбито на отдельные части, при готовой архитектуре, которую можно навязать тем-же джунам, будет все более менее терпимо, а при желании можно подменить через тот-же DI.

                    Честно говоря у меня много наболело по этому поводу. Поэтому я наверно извинюсь, за излишки.


                    1. Mendel
                      22.10.2016 15:52
                      +1

                      Вы под Опенкартом поработайте. Сразу начнете любить ваших легаси-писателей как хороших кодеров)

                      Вообще юии это такой «вордпресс для умных». В нем такого творят, что страшно.
                      Но как правило 90% проекта это много разных вариаций на тему CRUD, с десяток взаимных связей и пляски по борьбе с собственным непониманием АПИ.

                      Можешь сделать быстро — сделай быстро. RAD наше всё). Да, желательно соблюдать структуру и документирование и т.п., но без фанатизма. Нарушения стандартов самим Yii это малая толика зла дающая нам бонусы. Истинный ад живет в нарушениях стандартов теми кто пользуется фреймворком.


              1. zelenin
                22.10.2016 15:34

                Но ТАК УДОБНЕЕ.

                удобнее, не значит лучше.
                и опять же стандартная аргументация: yii — rad-фреймворк, поэтому для задач, которые он решает, быстрее и удобнее — аргумент. Для крупных приложений, которые на rad-фреймворках обычно не пишутся, встроенная в модель валидация (а так же общее неследование SOLID) не прокатит.


                1. Mendel
                  22.10.2016 15:44
                  +1

                  В том то и дело, что для своей ниши оно эффективно. Всё.
                  Это сродни критике всего явления ORM. Мол там такие планы запросов вырастают, что уж проще делать запросы руками. Ну так и делайте. Но только там где это нужно.
                  Пишешь на ORM, потом в уже живом окружении, уже покрытое тестами и т.п. дописываешь узкие места прямыми запросами. В процессе уточнив ТЗ, проверив все взаимодействия компонент и т.п.

                  У юии в принципе AR тяжелые. Разделяй не разделяй, а в сложных задачах все равно выкидывать всю подсистему и писать свое. Или переписать 0.1% кода, поднажать на кеширование и доплатить лишние 20 баксов в месяц на более мощный сервер и не морочить себе голову.


  1. ablai
    21.10.2016 11:26

    Ребята, не много не по теме, подскажите как можно установить все расширения с «minimum-stability»: «stable» и сделать исключение для несколько других расширений.

    Ситуация такая. Нужно установить kartik-v/yii2-export «dev-master», необходим функциональность с dev версий. Но при установке «minimum-stability»: «dev» все другие пакеты переходят тоже на dev игнорируя версий указанные в composer.json. Как быть?


    1. SamDark
      21.10.2016 11:40

      В идеале — упросить Kartik-а тэгнуть релиз. Но должно работать, если пакету приписать @dev к версии.


      1. zelenin
        21.10.2016 17:37
        +1

        или лучше номер коммита, чтобы все-таки зафиксировать версию — dev-master#c64571f892bda1298bad9c5e94ede0bc3f0e4627


        1. ablai
          22.10.2016 15:18

          можно подробнее


          1. zelenin
            22.10.2016 15:35
            +1

            указать версию пакета в таком стиле в composer.json. Тем самым мы зафиксируем пакет на конкретном коммите, если стабильный релиз нам не подходит или пакет не миеет стабильного тега.


            1. BoShurik
              22.10.2016 20:09

              composer.json все равно будет считываться из указанной ветки, а не из коммита, так что это не всегда выход


              https://getcomposer.org/doc/04-schema.md#package-links


              Note: While this is convenient at times, it should not be how you use packages in the long term because it comes with a technical limitation. The composer.json metadata will still be read from the branch name you specify before the hash. Because of that in some cases it will not be a practical workaround, and you should always try to switch to tagged releases as soon as you can.

              Может помочь объявление своего пакета:
              http://stackoverflow.com/questions/34784809/how-to-use-a-specific-tag-version-with-composer-and-a-private-git-repository


              "repositories": [
                # ...
                {
                  "type": "package",
                  "package": {
                    "name": "vendor/package",
                    "version": "v0.5.0",
                    "source": {
                      "url": "git@gitlab.server.com:vendor/project.git",
                      "type": "git",
                      "reference": "dd6ed3c8"
                    }
                  }
                }
              ]


              1. ablai
                22.10.2016 22:08

                Спасибо, попробую )


              1. zelenin
                22.10.2016 23:11
                +1

                composer.json все равно будет считываться из указанной ветки, а не из коммита

                непонятно, что там с чем что. dev-master#123abc установит коммит с хэшом 123abc из ветки dev-master. Что не так по вашему?


                1. BoShurik
                  23.10.2016 00:07

                  Если в HEAD в composer.json будут зависимости, к примеру


                  {
                      "require": {
                          "symfony/console": "3.0"
                      }
                  }

                  А в dev-master#123abc


                  {
                      "require": {
                          "symfony/console": "~2.7"
                      }
                  }

                  То composer будет считать, что надо установить "symfony/console": "3.0" в качестве зависимости, хотя сам пакет будет установлен из указанного коммита. Это происходит потому. что пакет скачивается уже после того, как разрешены зависимости.


                  1. zelenin
                    23.10.2016 00:10

                    я не понимаю о чем вы. мы тут про указание зависимости в СВОЕМ проекте? если будет указан dev-master#123abc, то он и установится.


                    1. BoShurik
                      23.10.2016 13:24
                      +1

                      Он устанвится, но его зависимости будут отрезолвены неверно.
                      В документации же все понятно:


                      The composer.json metadata will still be read from the branch name you specify before the hash.

                      Т.е. если указать "kartik-v/yii2-export": "dev-master#47fd3e870a1b7c8dcfe572b8290b6c61011a6aa7"


                      То версия composer.json будет использована из мастера вместо https://github.com/kartik-v/yii2-export/blob/47fd3e870a1b7c8dcfe572b8290b6c61011a6aa7/composer.json, и если они отличаются, то будут проблемы


                      1. zelenin
                        23.10.2016 14:40
                        +1

                        да, теперь понял проблему. Хотя формулировка очень размытая. Указанный коммит тоже находится в ветке перед хэшом, и логично что и содержимое composer.json тоже находится в этой ветке. Только речь не о ветке, а о текущем/последнем коммите указанной ветки.
                        Т.е. указав версию в нотации dev-master#47fd3e870a1b7c8dcfe572b8290b6c61011a6aa7, мы разресолвим зависимости не из composer.json коммита 47fd3e870a1b7c8dcfe572b8290b6c61011a6aa7 ветки master, а из composer.json последнего коммита ветки master.
                        PS. Да, это проблема.


  1. GoldenCentury
    21.10.2016 11:26
    +2

    Сасибо!


  1. nurik_6
    21.10.2016 17:59

    По поводу пункта «Requests» — скорее всего вы пропустили этот момент, при чтении документации, ведь тоже самое можно сделать и в Yii2. У меня в одном из проектов как раз и реализована аутентификация прежде, чем actions выполнятся.

    Просто в контроллере добавляем поведение с необходимым способом аутентификации, при этом заранее описываем класс аутентификации наследованным от AuthMethod. При этом можно объединять сразу 2 вида аутентификации для использования в одном контроллере.

    Вот чего действительно не хватает, так это Middleware, из-за этого иногда приходится приделывать велосипеды.


    1. SamDark
      21.10.2016 18:00

      А для чего именно? Какая задача?