Yii 2.0: обзор

Александр Макаров

Yii core team, Stay.com

Но сначала немного про PHP в целом

PHP замечателен!

PHP улучшается

  • Производительность.
  • Синтаксис.
  • API хеширования паролей.
  • Генераторы.
  • Встроенный вебсервер.
  • И многое другое...

Появляются альтернативные совместимые реализации

GitHub
  • PSR
  • Composer
  • Несколько стабильных, поддерживаемых и обратно совместимых фреймворков.

И это прекрасно!

А теперь о грустном…

Переусложнение

PHP-код становится слишком сложным из за стремления к безграничной гибкости.

Многие считают, что это единственный правильный путь.

Все проблемы программирования можно решить дополнительным слоем абстракции… кроме проблемы избыточной абстракции


David Wheeler

А всё ради чего?

А вдруг кто-то придумает поменять одну БД на другую, а вдруг надо поменять один основной компонент на другой? А вдруг что-то пойдёт не так...

И получаем

  • Непонимание, паттернизм. Как реализовано, а не для чего.
  • Легче тестировать, но сложнее писать, отлаживать и изучать код.
  • Слои. Много слоёв. В тестах можно извернуться раз, а с API работать постоянно.
  • Плата за гибкость — сложность. Сверхгибкость не нужна.
  • Невозможно отдать рутину менее опытным разработчикам не потратив много времени на обучение.

И что делать?

Практичные фреймворки

  • Без лишних сложностей.
  • Проще изучить.
  • Меньше магии.
  • Меньше слоёв.
  • Меньше конфигурации.
  • Простой и удобный API.
Yii
практичный фреймворк

Мифы о фреймворках

  • Переизобрёл колесо = плохой.
  • Контейнер DI и клёвые паттерны = хороший.
  • Сделали фичу первыми = лучше остальных.
  • Слабо связанный = всегда лучше.
  • Нет фичи X = плохой.

Действительно важно

  • Легко изучать.
  • Легко отлаживать и исправлять ошибки.
  • Не мешает работать и использовать сторонний код.
  • Дружелюбное активное сообщество.
  • Обратно совместим и стабилен.
  • Нет сложностей при попытках настроить и расширить.
  • Фреймворк должен нравиться ;)

Что такое Yii 2.0?

  • PHP 5.4.
  • Сбалансированный.
  • Будет стабильным и поддерживаемым.
  • Лицензирован под BSD.
  • Решает практически все задачи веб-разработки.
  • REST API framework.
  • Инструменты для отладки.
  • Генерация кода.
  • Очень приятная работа с данными.
  • Хорошая документация и дружелюбное сообщество.
Проекты
И ещё проекты

Один из самых быстрых PHP-фреймворков*.

*Кроме PECL и микрофреймворков

HHVM-совместим на 99.7%

Ставим basic


php composer.phar create-project --prefer-dist --stability=dev yiisoft/yii2-app-basic basic
cd basic
php -S localhost:80

http://www.yiiframework.com/download/

bootstrap

валидация и формы

отладчик

помнит всё

ищет по логам

полезные ошибки

полезные фаталы

Все ошибки — ErrorException


try {
    file_get_contents('test');
} catch (\yii\base\ErrorException $e) {
    // ну и ладно :(
}

генератор кода

генерируем контроллер

preview

diff

консоль

Мало?

advanced

  • Работа с данными.
  • Авторизация, аутентификация, восстановление пароля.
  • Разделение на frontend/backend/common/console + environments.

Ещё?

Официальные расширения

  • twig, smarty
  • swiftmailer
  • sphinx, elasticsearch
  • redis, mongodb
  • bootstrap, jui
  • imagine
  • gii, debug
  • codeception, faker
  • authclient
  • apidoc

ставятся очень просто:


php composer.phar require --prefer-dist yiisoft/yii2-mongodb "*"

и всё, можно работать

Уже есть около 250 неофициальных расширений.

Работа с базами данных

Один синтаксис для всего.


$query = new \yii\db\Query;
$query->select('id, name')
  ->from('tbl_user')
  ->orderBy('id DESC')
  ->limit(10);

$command = $query->createCommand();
echo $command->sql;
$rows = $command->queryAll();

$users = User::model()->find()
  ->orderBy('id DESC')
  ->limit(10)
  ->all();
                

Разделены модель и Query


$finder = Post::find()->where(['a' => 10]);
$finder2 = clone $finder;
$finder2->addWhere(['b' => 1]);

$model = $finder->one();
$model2 = $finder2->one();

// шорткаты
$post = Post::findOne(10); // pk = 10
$post = Post::findOne(['a' => 10, 'b' => 1]); // where a = 10 and b = 1
                    

Связи AR

has one, has many. Объявляются методами.


class User extends \yii\db\ActiveRecord
{
  public function getPosts()
  {
    return $this->hasMany('Post', ['user_id' => 'id']);
  }

  public function getActivePosts()
  {
    return $this->hasMany('Post', ['user_id' => 'id'])
      ->where(['status' => Post::STATUS_ACTIVE]);
  }
}
                    

$posts = $user->getPosts()->limit(10)->all();
$postCount = $user->getPosts()->count();
                    

Многие ко многим


class Post extends \yii\db\ActiveRecord
{
    public function getTags()
    {
        return $this->hasMany(Tag::className(), ['id' => 'tag_id'])
            ->viaTable('post_tag', ['post_id' => 'id']);
    }
}

AR asArray


$posts = Post::find()->limit(10)->asArray()->all();
foreach($posts as $post) {
  echo $post['title']."\n";
}
                    

dirty attributes и link

При save() сохраняется только то, что поменялось.

Появился метод link для сохранения связанных записей и unlink для удаления.


$comment = new Comment();
$comment->text = 'Hello, Yii!';

// INSERT INTO post_comment ...
$post->link('comments', $comment);

// DELETE FROM post_comment ...
$post->unlink('comments', $comment);
                    

Получение данных порциями


// 10 записей за раз
foreach (Customer::find()->batch(10) as $customers) {
    // $customers — массив 10 или менее объектов
}
// 10 записей за раз, итерация по одной
foreach (Customer::find()->each(10) as $customer) {
    // $customer — объект Customer
}
// с жадной загрузкой
foreach (Customer::find()->with('orders')->each() as $customer) {
}

А также

  • AR работает с noSQL, в т.ч. связи между моделями
  • Жадная и ленивая загрузка данных

О приоритетах

Мы не усложняем

В Yii нет ни одного названия вроде setMyCoolFactoryDependencyInjectionContainer()

Мы балансируем

Делаем приятный API, покрываем 80%, даём умолчания, позволяем расширять остальное.

Мы документируем

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

А ещё...

  • Мы любим инструменты (apidoc) и IDE
  • Не забываем про производительность
  • Сами используем фреймворк

Мы следим за тенденциями

REST API framework

Удобно

  • controller action — API endpoint
  • controller — группа endpoint для одного типа ресурса
  • model — ресурс

Пример


namespace app\controllers;

use yii\rest\ActiveController;

class UserController extends ActiveController
{
    public $modelClass = 'app\models\User';

    public function actionSearch($keyword) // !!!
    {
        $result = SearchService::search($keyword);
        return $result;
    }
}
'urlManager' => [
    'enablePrettyUrl' => true,
    'enableStrictParsing' => true,
    'showScriptName' => false,
    'rules' => [
        [
            'class' => 'yii\rest\UrlRule',
            'controller' => 'user'
        ],
    ],
]
  • GET /users: постранично все юзеры;
  • HEAD /users: заголовки ↑;
  • POST /users: новый юзер;
  • GET /users/123: информация юзера 123;
  • HEAD /users/123: заголовки ↑;
  • PATCH /users/123 и PUT /users/123: обновить юзера 123;
  • DELETE /users/123: удалить юзера 123;
  • OPTIONS /users: показать какие HTTP-verbs можно использовать для /users;
  • OPTIONS /users/123: показать какие HTTP-verbs можно использовать /users/123.

Пробуем


curl -i -H "Accept:application/json" "http://localhost/users"

    HTTP/1.1 200 OK
    Date: Sun, 02 Mar 2014 05:31:43 GMT
    Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
    X-Powered-By: PHP/5.4.20
    X-Pagination-Total-Count: 1000
    X-Pagination-Page-Count: 50
    X-Pagination-Current-Page: 1
    X-Pagination-Per-Page: 20
    Link: <http://localhost/users?page=1>; rel=self,
        <http://localhost/users?page=2>; rel=next,
        <http://localhost/users?page=50>; rel=last
    Transfer-Encoding: chunked
    Content-Type: application/json; charset=UTF-8

    [
        {
            "id": 1,
            ...
        },
        {
            "id": 2,
            ...
        },
        ...
    ]
                

Возможности

  • Быстрое прототипирование
  • JSON/XML или свой формат
  • Версионирование
  • Настраиваемая сериализация, можно выбрать что отдавать
  • Коллекции, поля и постраничная разбивка, валидация

Возможности

  • REST + fallback
  • OPTIONS и HEAD
  • Аутентификация (HTTP basic, URL token, OAuth2), авторизация (обычная: access filter и RBAC)
  • HATEOAS (Hypermedia as the Engine of Application State)
  • HTTP-кеш
  • Rate limiting: N запросов в секунду на пользователя

Документация: http://www.yiiframework.com/doc-2.0/guide-rest.html

1.1 → 2.0?

Пользуйтесь 2.0 с осторожностью

1.1 стабилен и поддерживается минимум до 2016

Чем помочь:

Вопросы?