8,4
рейтинг
28 сентября 2014 в 21:39

Разработка → Yii 2.0 RC

Yii*
Нам очень приятно сообщить о выходе RC (релиз кандидата) PHP-фреймворка Yii 2.0. Чтобы установить фреймворк или обновиться следуйте инструкциям на yiiframework.com.

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

Часто задаваемые вопросы



  • Что значит 2.0 RC? RC значит Release Candidate, то есть последний релиз перед стабильным GA (General Availability). До него остались, главным образом, правки небольших проблем и документация.
  • Когда будет стабильный релиз? Всё зависит от того, какие проблемы будут с RC. Предварительный план — сделать стабильный релиз примерно через две недели. Конечно, если RC покажет себя достаточно стабильным.
  • Могу ли я использовать RC в своих проектах? Да. Мы настоятельно рекомендуем попробовать его в новых проектах и будем признательны за сообщения об ошибках и просто отзывы. Так как стабильный релиз будет скоро, мы не советуем использовать RC на боевых серверах потому как, хоть это и маловероятно, в стабильной версии всё ещё может быть поломана обратная совместимость.
  • Есть ли документация по 2.0? Да, полное руководство, которое является самой полной документацией по 2.0 и документация по API — справочник, который поможет в использовании отдельных классов фреймворка.
  • Как обновиться с 1.1 на 2.0? Читайте Upgrading from Yii 1.1. Сразу отметим, что 2.0 полностью переписан и обновление не является тривиальным. Если ваше приложение на 1.1 работает хорошо и стабильно, рекомендуем продолжать использовать 1.1, если конечно у вас нет дополнительного времени и ресурсов для обновления.
  • Как обновиться с беты или альфы 2.0? Читайте инструкции в UPGRADE.
  • Как следить за разработкой 2.0? Вся разработка происходит на GitHub: github.com/yiisoft/yii2. Чтобы получать информацию об изменениях, можно отметить проект звёздочкой. Также можете подписаться на наш Twitter twitter.com/yiiframework и присоединиться к группе Facebook.




Главные улучшения в 2.0 RC



В данном релизе имеется большое количество полезных изменений и улучшений. Ниже мы опишем самое важное. Полный список изменений можно найти в CHANGELOG. Если хотите узнать фреймворке в общем, читайте полное рукводство.

Безопасность


Несколько экспертов по безопасности, включая Tom Worster и Anthony Ferrara, помогли нам с проверкой кода фреймворка и передали множество замечаний и предложений. Tom помог переписать часть кода, что позволило улучшить генерацию ключей, использовать более стойкое шифрование, защититься от timing attack и многих других типов атак.

Для более удобной настройки хелпер Security стал компонентом приложения security. В результате обращаться к нему можно как Yii::$app->security->encrypt().

В дополнение сделан ряд небольших, но важных для безопасности изменений. Например, теперь httpOnly включен для всех cookie по умолчанию, а CSRF токены можно хранить в сессиях вместо cookie если выставить yii\web\Request::enableCsrfCookie в false.

Работа с базой данных


Репликация и разделение чтения/записи


Репликация и разделение чтения/записи (read-write splitting) теперь поддерживаются ядром фреймворка. При репликации данные реплицируются с master серверов на slave сервера. Вся запись и обновления должны делаться на master серверах, а чтение можно производить со slave серверов. Для использования данной возможности настройте соединение с БД следующим образом:

[
    'class' => 'yii\db\Connection',

    // конфигурация для master
    'dsn' => 'dsn for master server',
    'username' => 'master',
    'password' => '',

    // общая конфигурация для slave-ов
    'slaveConfig' => [
        'username' => 'slave',
        'password' => '',
    ],

    // список конфигураций slave-ов
    'slaves' => [
        ['dsn' => 'dsn для slave 1'],
        ['dsn' => 'dsn для slave 2'],
        ['dsn' => 'dsn для slave 3'],
    ],
]


С данной конфигурацией вы можете продолжать писать код как и раньше. Если запрос выбирает данные, автоматически будет использован один из slave-ов (для выбора сервера используется простой алгоритм балансирования нагрузки). Если запрос обновляет или вставляет данные, будет использован master.

Транзакции


Было сделано несколько улучшений на тему транзакций.

Во первых, вы можете работать с транзакциями в стиле callback-ов:

$connection->transaction(function() {
    $order = new Order($customer);
    $order->save();
    $order->addItems($items);
});


Что эквивалентно более длинному коду:

$transaction = $connection->beginTransaction();
try {
    $order = new Order($customer);
    $order->save();
    $order->addItems($items);
    $transaction->commit();
} catch (\Exception $e) {
    $transaction->rollBack();
    throw $e;
}


Во вторых, транзакции вызывают несколько событий. Например, событие beginTransaction вызывается соединением с БД при старте новой транзакции, а commitTransaction вызывается при удачном коммите. Вы можете использовать эти события для различной пред- и постобработки.

Наконец, можно указывать уровень изоляции транзакции (например, READ COMMITTED) при её старте:

$transaction = $connection->beginTransaction(Transaction::READ_COMMITTED);


Построение запроса


При построении запроса теперь можно использовать любые операторы. В примере ниже для условия age >= 30 используется оператор >=. Yii должным образом экранируем имя поля, а для значения использует связывание параметра.

$query = new \yii\db\Query;
$query->where(['>=', 'age', 30]);


При построении in или not можно использовать подзапросы:

$subquery = (new \yii\db\Query)
    ->select('id')
    ->from('user')
    ->where(['>=', 'age', 30]);

// выбираем заказы, которые сделали клиенты старше 30 лет
$orders = (new \yii\db\Query)
    ->from('order')
    ->where(['in', 'customer_id', $subquery])
    ->all();


Управление ресурсами


Yii использует пакеты Bower и NPM, то есть jQuery, jQuery UI, Bootstrap, через Composer при помощи замечательного Composer Asset Plugin.

Из за этого изменения необходимо до использования Yii один раз поставить плагин:

php composer.phar global require "fxp/composer-asset-plugin:1.0.0-beta2"


Теперь при помощи следующей команды вы сможете установить пакет Bower jQuery в директорию vendor:

php composer.phar require bower-asset/jquery:2.1.*


Подробнее о ресурсах написано в полном руководстве.

Форматирование данных


Мы значительно отрефакторили форматтеры данных yii\base\Formatter и yii\i18n\Formatter. Теперь существует только один класс yii\i18n\Formatter. Новый форматтер предоставляет единый интерфейс вне зависимости от наличия на сервере PHP расширения intl. Если расширение не установлено, форматирование будет производиться средствами фреймворка и не будет поддерживать интернационализацию.

Также мы стандартизировали форматы даты и времени. Теперь используется, главным образом, формат ICU. Такие классы, как DateValidator и JUI DatePicker используют такой формат по умолчанию. Форматы PHP можно использовать через префикс php:.

$formatter = Yii::$app->formatter;
$value = time();
echo $formatter->asDate($value, 'MM/dd/yyyy'); // эквивалентно date('m/d/Y', $value)
echo $formatter->asDate($value, 'php:Y/m/d');  // эквивалентно date('Y/m/d', $value)
echo $formatter->asDate($value, 'long');       // эквивалентно date('F j, Y', $value)


Формы


Улучшения коснулись и JavaScript компонента ActiveForm.

Вместо использования callback-ов по ходу выполнения валидации теперь вызываются события. Использовать их довольно просто:

$('#myform').on('beforeValidate', function (event, messages, deferreds) {
    // Вызывается до валидации всей формы сразу после нажатия submit.
    // Тут можно провести дополнительные проверки.
});

$('#myform').on('beforeSubmit', function () {
    // Вызывается после удачной валидации всех полей и до того как форма отправляется на северер.
    // Тут можно отправить форму через AJAX. Не забудьте вернуть false для того, чтобы форма не отправлялась как обычно.
});


Также поддерживается отложенная валидация. В примере выше параметр deferreds для события beforeValidate позволяет добавить новый объект Deferred. FileValidator и ImageValidator теперь поддерживают валидацию на клиенте именно благодаря отложенной валидации.

Некоторые методы в JavaScript коде ActiveForm стали частью API, что позволяет легче создавать динамичные формы с поддержкой валидации добавляемых полей на стороне клиента. К примеру, следующий JavaScript код может быть использован для валидации только что добавленного поля «address»:

$('#myform').yiiActiveForm('add', {
    'id': 'address',
    'name': 'address',
    'container': '.field-address',
    'input': '#address',
    'error': '.field-address .help-block'
});


Логирование и обработка ошибок


Вы можете использовать массивы и объекты как данные при логировании. Все включенные по умолчанию в фреймворк цели логов автоматически конвертируют их в текстовое представление. В своём классе цели лога можно обрабатывать такие данные специальным образом.

InvalidCallException, InvalidParamException, UnknownMethodException теперь наследуются от BadMethodCallException из SPL, что делает иерархию исключений более логичной.

При отображении исключений теперь показываются аргументы методов в стектрейсе.

Инструменты разработчика


Отладчик Yii — очень полезный инструмент, который показывает детальную информацию о ходе выполнение приложения. Мы добавили в него новую панель, которая показывает загруженные бандлы ресурсов и их содержимое.

Генератор кода Gii теперь можно использовать из консоли. Ранее предоставлялся только веб интерфейс, который хоть и очень интуитивен, не нравится хардкорным консольщикам. Теперь довольны должны быть все. Более того, код генераторов не изменился. При создании своего генератора не надо делать двойной работы: и консоль и веб используют один и тот же код.

Чтобы попробовать Gii в консоли, запустите следующие команды:

# перейдите в базовую директорию приложения
cd path/to/AppBasePath

# смотрим справку по Gii
yii help gii

# смотрим справку по генератору моделей
yii help gii/model

# генерируем модель City на основе таблицы city
yii gii/model --tableName=city --modelClass=City


Поведения


Мы добавили новое поведение yii\behaviors\SluggableBehavior, которое позволяет заполнить определённый атрибут модели транслитерированной готовой к использованию в URL версией строки. Использовать его можно следующим образом:

use yii\behaviors\SluggableBehavior;

public function behaviors()
{
   return [
       [
           'class' => SluggableBehavior::className(),
           'attribute' => 'title',
           // 'slugAttribute' => 'alias',   // храним строку для URL (или slug) в поле "alias"
           // 'ensureUnique' => true,       // нам нужны только уникальные slug-и
        ],
    ];
}


Поведения теперь могут присоединяться анонимно:

$component->attachBehaviors([
    'myBehavior1' => new MyBehavior,  // именованное поведение
    MyBehavior::className(),          // анонимное поведение
]);


Шаблонные движки


Расширения Smarty и Twig были существенно улучшены. Для каждого из них был введён специальный синтаксис для многих возможностей Yii, что, судя по отзывам, позволяет работать с Smarty и Twig так же эффективно, как с обычными шаблонами PHP. Подробнее о новом синтаксисе можно узнать в полном руководстве.

Документация на Русском


Документация частично переведена на Русский, но вариант перевода не окончательный и читать её можно либо напрямую с GitHub, либо сгенерировав HTML самостоятельно. Огромное спасибо
русскоязычному сообществу за непосредственное участие в переводе.
Александр Макаров @SamDark
карма
281,4
рейтинг 8,4
PHP, Yii, Android
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

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

  • +6
    Спасибо за проделанную работу! Очень ждал этот день
  • +4
    Прекрасная новость, порадовали в конце недели. Молодцы, так держать. Особенно порадовал bower без nodejs.
    • 0
      уже довольно давно есть bowerphp. composer-asset-plugin никакого отношения к yii так же не имеет.
      • 0
        bowerphp работает отвратно. Гитхаб репозитории не поддерживает, соединение часто вылетает. Оно и немудрено, проект в альфа-версии. В общем, мы покрутили-повертели его и вернулись обратно на bower.
        • 0
          Почему не поддерживает github репозитории? Поддерживает он. Хотя я не вижу в этом ровным счетом никакого смысла. Можно поставить node.js на билд-сервере или собирать на локальной машине а потом уже деплоить.
          • 0
            >> Почему не поддерживает github репозитории? Поддерживает он.

            Я ему скармливал ровно тот же самый bower.json, который на bower отрабатывает без проблем, и он отваливался с ошибкой not found на тех пакетах, которых нет на bower.io/search, из чего был сделан вывод, что гитхаб он не умеет.

            >>… собирать на локальной машине а потом уже деплоить.

            Сейчас мы так и делаем, храним пакеты под vcs. bowerphp ставился как раз для того, чтобы при деплое подтягивать зависимости, не устанавливая nodejs на прод машину. Но работал он ну очень нестабильно, то и дело отваливаясь на всяких «jquery not found», хотя рядом composer вообще не вякает даже (вообще мне композер очень нравится стабильностью работы, даже рубиевский бандлер не такой). А еще странно, что капистрано не отваливался с ошибкой, когда bowerphp отваливался. Т.е. приложение по факту успешно проходило деплой, но без пакетов.
            • 0
              проблемы со сторонними библиотеками лечатся ишусами в трекере и пул реквестами. Почему-то люди вместо того что бы допилить одну библиотеку начали ваять другую. Меня это удивляет. Хотя может это потому что в php нету модулей и конфликты по версиям чаще встречаются изза этого.
  • 0
    А как использовать beforeSubmit в ActiveForm? Я имею в виду как описать событие в самом виджете. Ранее я делал так
    <?php $form = ActiveForm::begin([ 'beforeSubmit' => 'function(form) { ... }' ]); ?>
    • +1
      Можно так:
      $this->registerJs(<<<JS
          $('#form-id').on('beforeSubmit', function(){
              var form = this;
          });
      JS
      );
      

      Свойства ActiveForm::$beforeSubmit больше нет.
      • +1
        Или этот же код (заключенный в <<>>) поместить в общий js файл, если не хотите мешать js с php
      • 0
        Жаль. Мне нравилось как это раньше работало. Придется регистрировать отдельно, как вы написали
  • +5
    Другой порядок параметров в условии
    where([ 'age', '>=', 30]);
    был бы более человекочитаемым
    • +2
      Можно сразу сделать where('age >= 30') и это будет работать.
      Если условие оформляется как массив, первым элементом идет оператор (and, or, not, between, in и т.д). Если добавили еще и элементарные операторы, то вполне логично то, что этот самый оператор идет первым элементом массива.
      • +2
        текстовые кондишны вида where('age >= 30') в реальных проектах довольно редкое явление, т.к. параметры идут в основном из внешних данных, а их необходимо подставлять в params (в изначальном варианте с тремя параметрами так и происходит). Я понимаю, что такой порядок сделали потому, что так проще и еще потому, что «так повелось», но всё же.
        • +3
          Да, все верно, нужно или через параметр where('age >= :age') или where(['>=', 'age', $age]).
          Думаю что дело не «так повелось», а в том, что разные операторы принимают разное кол-во аргументов.
        • +1
          Со времен лиспа еще так повелось.
  • +2
    Было бы здорово если бы подзапросы можно было использовать в \yii\db\Query::addSelect()
    Чтобы код:
    $query->addSelect(['foo' => $subquery]);
    

    строил запрос типа:
    SELECT
        (SELECT ...) AS foo
    FROM ...
    
    • 0
      Это легко сделать, но в cakephp 3.
    • +5
      Напишите issue, посмотрим, что можно сделать.
    • 0
      Насколько я поковырял ormку, я склонен считать что её проще переписать целиком, отказавшись от поддержки части баз, нежели пытаться проапдейтить для полноценной поддержки мультизапросов :(
      • 0
        По-моему следует вообще отказаться от своей ORM в пользу Doctrine/Propel/whatever. Если ребята из Symfony не стали свой велосипед городить, то это что-то да значит.
        • 0
          Авторы Yii свои велосипеды на тему БД писали ещё когда Doctrine и Symfony не было.
          • 0
            Велосипеды это конечно хорошо, но давайте прикинем. Propel хоть в каком-то виде появился за год до Prado. Doctrine начали пилить в 2006-ом, через год после первого релиза Symfony. Yii 1.0 вышел где-то в 2008-ом… на дворе 2014-ый год… хм… велосипеды… их все писали. Проблема Yii в том что (по крайнемере в первых версиях) продолжают писаться велосипеды. Я больше не о компонентах фреймворка, их можно воспринимать как полноценные решения, а больше о том духе который царит в Yii сообществе. Велосипеды. Просто забавная статистика на основе тех проектов которые я видел.
            • 0
              Я сам в начале 2008-ого пилил свой велосипед, и если бы друг не показал мне Yii, вышел бы его клон.
              • +5
                Так это хорошо попробовать пописать своё. Появляется понятие о том, что можно сделать, а что нет. Изучается устройство фреймворков и идеи, которые потом можно в своём коде применить. Ну а конечному пользователю, в общем-то, всё равно, кто был первый. Ему главное стабильно, удобно и быстро. У нас оно по сочетанию этих качеств как минимум не хуже остальных.
        • 0
          Да, вполне может быть. Незнаю, правда, будет ли проще интегрировать что-то готовое в юи, нежели покрыть велосипедом свои потребности.
          • 0
            Пробовал я как-то интегрировать Symfony/Forms и Doctrine в Yii1,1. Жить можно. Только тяжко это и делалось только в рамках рефакторинга одного легаси проекта. Затем был PHP-DI, HttpKernel и полная смена фреймворка.
            • 0
              И да, сразу предупрежу. Заниматься подобным — извращение. Просто проект был в том состоянии, при котором был выбор, либо переписывать его на Yii либо на Symfony. Вот только именно переписывать времени небыло, пришлось планомерно заниматься интеграцией.
  • 0
    Долго ждал «middle of 2014» и в итоге перешёл на symfony2. Заметил что в Yii2 остались многие недочёты с первой версии.
    • +10
      Какие?
      • 0
        Очень нравится в Laravel функция withPivot() для работы с Pivot Tables. Позволяет к результатам выборки добавить доп. поля (которые в YII2 добавляются в $extraColumns функции link()). Таким образом можно не создавать промежуточную модель по pivot таблице. Насколько понял, в YII2, так пока нельзя?
        • 0
          Можно, но не так удобно.
          • 0
            Считаете, что создание модели для pivot table с доп. полями — это правильное решение? Вопрос без сарказма.
            • 0
              Эти поля надо как-то заполнять, удалять связи, редактировать их, выводить списком в админке. Без модели делать это, как по мне, не очень удобно.
            • +1
              Но надо будет глянуть, что сделано в Laravel на тему API. Может стоит перенять.
      • +4
        Так и остались жёстко привязанные компоненты типа Session, User и т.д.

        Использование header(), die(), exit() до сих пор нормальная практика.

        Проблемы с Response так и остались. Лично я ждал что в Yii2 объект класса Response будет создаваться внутри контроллера.

        Как контролировать список Yii::$app->response->format?

        Создание BaseController extends Controller от которогого будут наследоватся все контроллеры и создавать из него колбасу из хелперов наподобии:
        // BaseController extends Controller
        public function jsonResponse($data)
        {
        	\Yii::$app->response->getHeaders()->set('Access-Control-Allow-Origin', '*');
        	\Yii::$app->response->format = yii\web\Response::FORMAT_JSON;
        	return json_encode($data);
        }
        
        // MyController extends BaseController
        public function actionIndex()
        {
        	return $this->jsonResponse([]);
        }
        

        так и осталось.

        PS: рейтинг комментария интересно прыгает.
        • +2
          Жёстко привязанные к чему?

          Использование header(), die(), exit() до сих пор нормальная практика.


          Нет.

          Проблемы с Response так и остались. Лично я ждал что в Yii2 объект класса Response будет создаваться внутри контроллера.


          Какие именно проблемы? Руками каждый раз собирать Response объектом, как по мне, излишне.

          Как контролировать список Yii::$app->response->format?


          Это не список, а строка. Форматтеры настраиваются и добавляются из конфига приложения, секция components, компонент response, свойство formatters: github.com/yiisoft/yii2/blob/master/framework/web/Response.php#L121

          создавать из него колбасу из хелперов


          Можно сделать, например, в beforeAction. Будет наглядней и короче.

          • 0
            Можно сделать, например, в beforeAction. Будет наглядней и короче.

            немного не понял как сделать так, чтоб было проще и наглядней.
            • +1
              class MyController extends \yii\web\Controller
              {
                  public function beforeAction($action)
                  {
                      \Yii::$app->response->getHeaders()->set('Access-Control-Allow-Origin', '*');
                      switch ($action->id) {
                          case 'json1':
                          case 'json2':
                              \Yii::$app->response->format = yii\web\Response::FORMAT_JSON;
                          break;
                          case 'xml':
                              \Yii::$app->response->format = yii\web\Response::FORMAT_XML;
                          break;
                      }
                      return parent::beforeAction($action);
                  }
              
              
                  public function actionIndex()
                  {
                      return $this->render('help');
                  }
              
                  public function actionJson1()
                  {
                      return ['name' => 'Alex'];
                  }
              
                  public function actionJson2()
                  {
                      return ['name' => 'Qiang'];
                  }
              
                  public function actionXml()
                  {
                      return ['name' => 'Carsten'];
                  }
              }
              
              • 0
                Я сильно сомневаюсь что это наглядней и короче.
                • +1
                  Вам так и так надо указать, что отдаётся JSON. У нас это делается в декларативной форме. Вы, похоже, предпочитаете явную с оборачиванием классом. На вкус и цвет…
                  • 0
                    Вы, похоже, предпочитаете явную с оборачиванием классом.

                    А beforeAction мы явно не оборачиваем в класс? Или его можно вынести?
          • +1
            Руками каждый раз собирать Response объектом, как по мне, излишне.

            Я думаю так:
            	return new JsonResponse($data);
            

            проще чем:
            	\Yii::$app->response->getHeaders()->set('Access-Control-Allow-Origin', '*');
            	\Yii::$app->response->format = yii\web\Response::FORMAT_JSON;
            	return json_encode($data);
            


            Да и ответ создаём когда надо и если надо.
            • +2
              В последней строчке json_encode лишнее, т.к. из-за yii\web\Response::FORMAT_JSON Response сам занимается преобразованием в JSON, и нужно просто return $data;
        • +1
          Так и остались жёстко привязанные компоненты типа Session, User и т.д.


          Компоненты можно переопределить и создать свои классы. А в них уже хотите — наследуйтесь от базовых, хотите — нет.
          • 0
            Я говорю про случаи когда они вообще не нужны.
            • 0
              А когда они не нужны?
            • +1
              Компоненты в Yii загружаются лениво. То есть только тогда, когда к ним обращаются. Если в приложении никто не логинится, компонент сессии вообще не отработает.
    • +3
      поддерживаю какие недочеты вы заметили. Также хотелось бы услышать впечатления про симфони после yii
  • +2
    А я не ждал «middle of 2014» :-)
    Стал использовать в проектах, как только вышла альфа-версия, и не стыжусь.
    • +1
      Я чуть позже, с беты и очень рад, что все таки решился переписать проект, который уже начал писать на Yii1 на вторую версию. Месяц ушел, чтобы переварить изменения в фреймворке, дальше уже легче)
    • +1
      Аналогично. Правда, временами с композером были проблемы. Но они оперативно фиксились.
  • +7
    У нас недавно, 13 сентября, был год, как мы девелопим на Yii2. Абсолютно довольны выбором. Специфика проекта такова, что практически не используем фронтенд-компоненты фреймворка, про них мало что могу сказать. Но ActiveRecord и QueryBuilder сделаны очень хорошо и удобно, особенно если сравнивать с Yii1.

    Для тех, кто ещё не пробовал Yii2 могу в его поддержку выделить такие моменты как:

    • Очень хорошо документированный код, в котором всегда легко разобраться и который удобно расширять
    • Быстрая скорость исправления багов
    • Хорошая реакция на рациональные предложения от коммьюнити
    • Ну и само коммьюнити — очень отзывчивое и доброжелательное, а главное — квалифицированное
    • Хорошая стабильность — даже на пре-альфе у нас всё работало. Да, бывали падения, ломалась совместимость, но это было ожидаемо, так как шла активная разработка


    Из последних нововведений особая благодарность за bower-assets. Стало гораздо удобнее подключать frontend-зависимости.
    • 0
      Справедливости ради стоит отметить, что ребята уж очень долго кормили завтраками по поводу второй версии; вполне возможно именно поэтому теперь „скорость хорошая“.
  • +3
    Отдельный респект за Gii из консоли.
    • 0
      Неужели таки запилили? Я уже успел плюнуть и свой консольный контроллер гиишный написать.
      • 0
        Умгу. По нормальному запилили. Чтобы кушал генераторы и web и консольный Gii одинаковые.
  • +2
    Стартанули два проекта на Yii2 еще с alpha версии. Очень рады) В ноябре надеюсь новый проект начну уже на stable.
  • 0
    echo $formatter->asDate($value, 'MM/dd/yyyy'); // эквивалентно date('m/d/Y', $value)
    


    В чем преимущество использования форматтера вместо нативной php функции?

    • +2
      ICU, поддержка форматирования в зависимости от локали (для «short», «medium», «long» и «full»).
      — В случае фейла показывает nullValue (можно конфигурировать).
      — Принимает во внимание часовой пояс.
    • 0
      нативной какой? там большой хелпер использующий расширение intl или фолбэк.
  • 0
  • +2
    Отличная новость. Пощупали двойку в бете — осталось очень приятное впечатление. Будем обязательно использовать.
  • 0
    Большое спасибо за работу! Пользуюсь второй версией еще с августа 2013.

    Очень расстроила функция cache в db\Connection, предыдущие варианты c beginCache и endCache были тоже не фонтан, но использовать было удобнее.
    Сейчас же в нужно оборачивать все в анонимные функции, через use() передавать зачастую по несколько штук переменных, а если запросов много идет подряд — то вовсе кучу переменных, как по мне — совсем не по «феншую».

    Почему бы не сделать как было в старом добром Yii1 — к query добавляем функцию cache($duration, $dependency = null) — и получается гораздо удобнее и красивее.
    • 0
      В 1.1 частенько beginCache и endCache были ну в совсем разных местах и отладка превращалась в ужасный ужас. Но если будут на текущий синтаксис частые жалобы, вернём.
      • 0
        beginCache и endCache — согласен, совсем не ахти.
        а как на счет метода cache в query — чтобы избавиться от анонимных функций?
        • 0
          Query — это как старый добрый CDbCriteria. То есть условия для запроса. Кеш туда не очень вписывается логически.
        • 0
          Анонимные функции выглядят совсем неплохо.
          • +1
            согласен, выглядят они прикольно, по js'ному

            НО возьмем пример, в виджете, фукнция run:
            $articlesCount = Article::find()
                            ->published()
                            ->count();
            
            $videosCount = Video::find()
                            ->published()
                            ->count();
            
            $pollsCount = Poll::find()
                            ->published()
                            ->count();
            
            return $this->render('widget-view', [
                  'articlesCount' => $articlesCount, 
                  'videosCount' => $videosCount,
                  'pollsCount' => $pollsCount,
            ]);
            


            задача — как это все закешировать:
            вариант 1:
            $articlesCount = Article::getDb()->cache(function(){
               return Article::find()
                            ->published()
                            ->count();
            }, 3600);
            
            $videosCount = Video::getDb()->cache(function(){
                return Video::find()
                            ->published()
                            ->count();
            }, 1800);
            
            $pollsCount = Poll::getDb()->cache(function(){
               return Poll::find()
                            ->published()
                            ->count();
            }, 43200);
            
            return $this->render('widget-view', [
                  'articlesCount' => $articlesCount, 
                  'videosCount' => $videosCount,
                  'pollsCount' => $pollsCount,
            ]);
            


            чет дофига анонимок, давайте по другому
            вариант 2:
            \Yii::$app->db->cache(function() use(&$articlesCount, &$videosCount, &$pollsCount) {
            $articlesCount = Article::find()
                            ->published()
                            ->count();
            
            $videosCount = Video::find()
                            ->published()
                            ->count();
            
            $pollsCount = Poll::find()
                            ->published()
                            ->count();
            }, 3600);
            
            return $this->render('widget-view', [
                  'articlesCount' => $articlesCount, 
                  'videosCount' => $videosCount,
                  'pollsCount' => $pollsCount,
            ]);
            


            сразу встает проблема — одинаковое время кеширования, и переменные в use, и это мы туда еще параметров запросов никаких не передавали.
            другая проблема — у нас модели (или просто Query) могут обращаться к разным базам, одним махом уже не покешируешь.

            резюмируя: на мой взгляд:
            1. текущая реализация подходит для примеров из документации, в реальном проекте обычно код сложнее.
            2. появляется реально лапша коллбеков, за что я всегда любил yii — что код получается логичным, читабельным и минимум обвеса. Сейчас же в угоду паттернам клиенский код не удобный. Осталось добавить еще вызов пары фабрик, сервис локаторов и получим симфони или зенд.
            3. отладка — иногда удобно пройтись по построению запроса дебаггером и посмотреть потом в самом конце в queryInternal что туда пришло и что оно вернуло, с анонимками — сразу не попадешь в фукнцию, надо идти до call_user_func — эт такое, придираюсь
            4. возможно добавление метода cache в Query и не отвечает канонам, паттернам и всего всего такого умного, но по факту оно удобнее и фукнциональнее

            разумеется, ИМХО
            • +1
              Мне с «дофига анонимок» нравится больше. Анонимки сами по себе часть PHP с 5.3, желание избавляться от них довольно странно.

              1. Если код кеширования становится сложнее, что-то надо менять. Кеш — одна из сложнейших задач вообще, так что надо стараться кешировать как можно проще.
              2. В 1.1 не особо много анонимок потому как они в PHP 5.1 и 5.2, которые для него были основными, не поддерживаются. Анонимка — не паттерн, а часть языка.
              3. Почему? Поставил breakpoint в анонимку, нажал run и попал…
              4. Добавление метода cache в Query не отвечает логике. Паттерны тут не при чём.
            • 0
              Опередил. «дофига анонимок» нормально выглядят и читаются.
  • 0
    $connection->transaction(function() {});

    А почему не сделали откат если callback возвращает false? ИМХО, это удобнее чем выбрасывать исключения (в yii 1.x как раз использую подобную обертку, только там еще и исключении можно поглотить — оно далеко не всегда нужно извне callback-а).
  • 0
    SamDark, подскажите пожалуйста, а почему user теперь обязательный компонент? Т.е. если в конфиге, в компонентах нет 'user', то выбрасывается исключение Invalid Configuration – yii\base\InvalidConfigException User::identityClass must be set.
    Как-то это не правильно я считаю. А если у меня в приложению просто не нужно работать с пользователями? Все равно надо определять компонент?
    • 0
      Он не обязательный, а просто прописан по умолчанию для веб-приложения.
      • –1
        Вот конфиг yii2-app-basic откуда я удалил компонент user
        <?php
        
        $params = require(__DIR__ . '/params.php');
        
        $config = [
            'id' => 'basic',
            'basePath' => dirname(__DIR__),
            'bootstrap' => ['log'],
            'components' => [
                'request' => [
                    // !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
                    'cookieValidationKey' => 'HcXm7J9dgjen_UNZovotOiShvs1vJ--V',
                ],
                'cache' => [
                    'class' => 'yii\caching\FileCache',
                ],
                'errorHandler' => [
                    'errorAction' => 'site/error',
                ],
                'mailer' => [
                    'class' => 'yii\swiftmailer\Mailer',
                    // send all mails to a file by default. You have to set
                    // 'useFileTransport' to false and configure a transport
                    // for the mailer to send real emails.
                    'useFileTransport' => true,
                ],
                'log' => [
                    'traceLevel' => YII_DEBUG ? 3 : 0,
                    'targets' => [
                        [
                            'class' => 'yii\log\FileTarget',
                            'levels' => ['error', 'warning'],
                        ],
                    ],
                ],
                'db' => require(__DIR__ . '/db.php'),
            ],
            'params' => $params,
        ];
        
        if (YII_ENV_DEV) {
            // configuration adjustments for 'dev' environment
            $config['bootstrap'][] = 'debug';
            $config['modules']['debug'] = 'yii\debug\Module';
        
            $config['bootstrap'][] = 'gii';
            $config['modules']['gii'] = 'yii\gii\Module';
        }
        
        return $config;
        
        


        а вот скриншот ошибки awesomescreenshot.com/0fc3ku55d3
        • 0
          Гм. Так вы сессии используете и проверку на аутентификацию. Для них нужен user.
          • 0
            Ой, ой. Извините, я затупил. Тестировал у себя на разрабатываемом проекте (структура как на app-advanced) и случайно открыл не ту «часть» приложения, которая и вызвала ошибку (как раз после обновления на RCv поэтому и связал с этим). А когда на basic ошибку проверял, то просто убрал user не посмотрев в контроллеры
  • +1
    Багтрекер в комментариях.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.