Открыть список
Как стать автором
Обновить

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

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

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

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

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

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

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

Использование 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. Будет наглядней и короче.

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

немного не понял как сделать так, чтоб было проще и наглядней.
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'];
    }
}
Я сильно сомневаюсь что это наглядней и короче.
Вам так и так надо указать, что отдаётся JSON. У нас это делается в декларативной форме. Вы, похоже, предпочитаете явную с оборачиванием классом. На вкус и цвет…
Вы, похоже, предпочитаете явную с оборачиванием классом.

А beforeAction мы явно не оборачиваем в класс? Или его можно вынести?
Руками каждый раз собирать 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);


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


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

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

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


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


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

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

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

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

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

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

А почему не сделали откат если callback возвращает false? ИМХО, это удобнее чем выбрасывать исключения (в yii 1.x как раз использую подобную обертку, только там еще и исключении можно поглотить — оно далеко не всегда нужно извне callback-а).
SamDark, подскажите пожалуйста, а почему user теперь обязательный компонент? Т.е. если в конфиге, в компонентах нет 'user', то выбрасывается исключение Invalid Configuration – yii\base\InvalidConfigException User::identityClass must be set.
Как-то это не правильно я считаю. А если у меня в приложению просто не нужно работать с пользователями? Все равно надо определять компонент?
Он не обязательный, а просто прописан по умолчанию для веб-приложения.
Вот конфиг 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
Гм. Так вы сессии используете и проверку на аутентификацию. Для них нужен user.
Ой, ой. Извините, я затупил. Тестировал у себя на разрабатываемом проекте (структура как на app-advanced) и случайно открыл не ту «часть» приложения, которая и вызвала ошибку (как раз после обновления на RCv поэтому и связал с этим). А когда на basic ошибку проверял, то просто убрал user не посмотрев в контроллеры
Багтрекер в комментариях.
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.