initSQLs для Yii2

В классе yii\db\Connection, заменившем CDbConnection пропал параметр initSQLs. Теперь для настройки таймзоны соединения с базой данных требуется навешивать обработчик события:

    'components' => [
        'db' => [
            'on afterOpen' => function($event) {
                $event->sender->createCommand('set time_zone="+00:00"')->execute();
            },
        ],

Валидация «только латинские символы»

Сабж делается легко, как всегда:

public function validateLatin($attribute)
{
    $value = $this->$attribute;
    if (preg_match('/[^\x20-\x7f]/', $value))
        $this->addError($attribute, 'Only latin symbols are allowed'));
}

Плюрализация в Yii2

Сабж делается очень легко, но не очень явно.

$f = \Yii::$app->i18n->messageFormatter;
$cost =  $f->format(
    '{n, plural, =0{бесплатно} =1{один рубль} one{# рубль} few{# рубля} many{# рублей} other{# рубля}}',
    ['n' => $model->cost], \Yii::$app->language);

Использование конструктора ActiveRecord в Yii2

Все компоненты в Yii2 наследуются от базового класса Object, который принимает на вход массив конфигурации объекта. Это удобно использовать для быстрой инициализации моделей ActiveRecord:

(new LogRecord([
    'userId' => $userId,
    'message' => 'Ololo',
])->insert(false);

Использование CDataProviderIterator

Начиная с версии 1.1.13 в Yii появилась возможность работать с большими наборами моделей ActiveRecord посредством итератора. Это позволяет значительно уменьшить потребления памяти. Использовать итератор легко и просто:

// создаем критерий
$criteria = new CDbCriteria();
$criteria->addCondition('status = 1');

// создаем DataProvider, использующий критерий
$provider = new CActiveRecordProvider('User', ['criteria' => $criteria]);

// создаем итератор и обходим результирующую выборку 
$iterator = new CDataProviderIterator($provider);
foreach ($iterator as $user) {
    ...
}

Про ErrorException

PHP по-умолчанию не ловит ошибки в блоке try/catch.

Т.е. такой код вывалит ошибку PHP Error[8]: Undefined offset: 1, хоть и ожидается совершенно иное поведение.

try {
    $a = [];
    echo $a[1];
} catch (Exception $e) {}

Чтобы все работало как ожидается, нужно установить отдельный обработчик ошибок, как указано в документации к базовому исключению ErrorException.

function exception_error_handler($errno, $errstr, $errfile, $errline ) {
    throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}
set_error_handler("exception_error_handler");

Генерация идентификаторов для уникальных URL

Самый матерый вариант, который я видел, выглядит так:

echo gmp_strval(gmp_init(hash('sha256', microtime()), 16), 62);

В нем берется sha256 хэш и переводится в систему счисления с базой 62 (цифры + латинские символы в верхнем и нижнем регистрах).

Результат получается такой:

5YQNOcr1o2SoNnFbWkmPmbioJOMcjCaQkczywNGJNpN

Отключение CWebLogRoute и YiiDebugToolbarRoute из контроллера

Порой требуется отключать некоторые веб логгеры для того, чтобы их код не портил вывод. Делается это так:

foreach (Yii::app()->log->routes as $route)
    if ($route instanceof CWebLogRoute || $route instanceof YiiDebugToolbarRoute)
        $route->enabled = false;

Переход на Yii2: DataColumn

В Yii2 изменились параметры описания колонок для GridView. Параметр name теперь называется attribute, параметр type теперь называется format.

Было:

'columns' => [
    [
        'type' => 'html',
        'name' => 'categoryId',
        'value' => function($data) {
            return CHtml::link($data->category->name, ['object-category/update', 'id' => $data->categoryId]);
        }
    ],
],

Стало:

'columns' => [
    [
        'format' => 'html',
        'attribute' => 'categoryId',
        'value' => function($data) {
            return Html::a($data->category->name, ['object-category/update', 'id' => $data->categoryId]);
        }
    ],
],