Как мы используем Yii

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

Yii core team, Stay.com

DevConf

Москва, 2013

  • PHP5 MVC.
  • Приятный API.
  • DAO, AR, миграции.
  • Мощный кеш.
  • Построитель форм.
  • Обработка ошибок, лог.
  • Тесты.
  • Документирован.
  • Сообщество.
  • BSD.

Prado, с 2004 → Yii 1.0, 2008 → Yii 1.1, 2010 → Yii 2, 2013

Что важно

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

Структура проекта

http://www.yiiframework.com/wiki/155/

Несколько приложений

  • Common (↓)
    • Models
    • Parameters
    • Components
  • Console (↑)
  • Frontend (↑)
  • Admin (↑)

Алиасы


Yii::setPathOfAlias('root', __DIR__);
echo Yii::getPathOfAlias('root');
                    
  • root
  • common
  • application (Yii default)
  • webroot

Пред-production настройки

Вытащить приложение за вебрут

Оставляем только index.php поправляя в нём пути.


// change the following paths if necessary
$yii='\path\to\framework\yii.php';
$config=__DIR__.'/../protected/config/main.php'; // !!!
...

Более безопасно, удобней.

Вытащить runtime из protected

protected/config/main.php, protected/config/console.php:


return array(
    'runtimePath' => Yii::getPathOfAlias('system') . '/../runtime/',
    ...
);

Туда пишется лог, файловый кеш, кеш HTMLPurifier, состояние приложения.

Настроить id для приложения

protected/config/main.php, protected/config/console.php:


return array(
    'id' => 'my-app-name',
    ...
);

Используется как префикс для:

  • Ключей кеша
  • Ключей данных пользователя в сессии

Отключить DEBUG-режим

В index.php прописать:

if(!defined('YII_DEBUG')) {
    define('YII_DEBUG', false);
}

Значительно влияет на производительность, безопасно.

Включить кеш схемы AR


return array(
    ...
    'components'=>array(
        ...
        'cache'=>array( // !!!
            'class'=>'CDbCache',
        ),
        'db'=>array(
            'connectionString'=>'mysql:host=localhost;dbname=yii_test',
            'schemaCachingDuration'=>3600, // !!!
        ),
    ),
);

Значительно влияет на производительность.

Включить APC, если ещё не включен

Можно поробовать yiilite.php. Хорошо работает с некоторыми версиями PHP и APC, но плохо с другими.

Готово?

Вроде... Что дальше?

По сути, деплой в PHP не очень нужен... поначалу.

  • Правки наживую, vim-style
  • ftp / sftp
  • rsync

Это не наш метод

Нас больше одного

Контроль версий

Как хранить код

  • Git или другая VCS. Git очень удобен.
  • Ветки: master, release-X.X, feature-XXX.
  • Теги: X.X.Y
  • Релиз.

Что делать с базой?

  • base-schema.sql — начальная структура.
  • base-data.sql — начальные данные.


Миграции

  • Не использовать модели и код приложения.
  • Если ушла в VCS и запускалась, не править.
  • Если ушла в VCS и не запускалась — поправить.
  • Не лезть в базу руками.

Так как?

Деплой

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

На это время может ставить maintenance mode.

  • На тестовый сервер и локально — автоматом.
  • На RC и production — полуавтоматом.
  • Гоняем тесты. Если фейл — письмо + остановка.
  • Чистим APC (stat=0).
  • Греем кеш.
  • Рестарт вебсервера (если нужен).
  • LESS/SCSS → CSS.
  • TypeScript → JavaScript.
  • Собрать и минифицировать CSS и JS.
    yiic compress all (в паблике нет).
    Жмёт, генерит файл аля all_123hash123.js, прописывает его в frontend/config/params-local.php.
  • Применить миграции yiic migrate.
  • Нагенерить документацию

Разные сервера, разные настройки

Окружения

Выносим настройки в конфиг.

Как быть с конфигами?

  • Общий конфиг.
  • Конфиги для разных приложений.
  • Конфиги для разных серверов.
  • Свой конфиг у разработчика.
  • Пароли и ещё много чего нельзя держать в VCS.

Окружения


common
  config
    main.php
    main-local.php ← .gitignore
  env
    production
      config
        main-local.php
    development
      config
        main-local.php

frontend
  config
    main.php
    main-local.php ← .gitignore
  www
    index.php ← .gitignore
  env
    production
      config
        main-local.php
      www
        index.php
    development
      config
        main-local.php
      www
        index.php
install.php <application> <environment>

Конфиги наследуются

  1. common/config/params.php
  2. common/config/params-local.php
  3. frontend/config/params.php
  4. frontend/config/params-local.php

$config1 = array(...);
$config2 = array(...);
$finalConfig = CMap::mergeArray($config1, $config2);
                    

CMap::mergeArray можно закешировать.

Инструменты


  • Phing
  • Jenkins
  • TeamCity

Данные

  • MySQL.
  • Кеш в APC.
  • noSQL только когда нужен.
  • Поиск SOLR/Sphinx.

Внешние API

  • Facebook.
  • Google.
  • Могут не работать.
  • Могут меняться.
  • Кеш.

i18n

  • UTF-8.
  • Collation.
  • Yii::t, исходник всегда английский.
  • С данными всегда по-разному…

Производительность

  • Узкие места будут не там, где вы думаете.
  • Все будут использовать проект «не так».
  • Рост можно контролировать.
  • Время — деньги.

Что тормозит?

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

Что делать?

  • Отложить выполнение.
  • Очереди.
  • SQL.
  • Кеш.

Внешние vs внутренние сервисы

Внешние Внутренние
Latency. Нужно мониторить.
Ломаются. Нужно ставить.
Без напряга. Нужно поддерживать.
Стоят денег. Детали.
Гарантии. Нет гарантий.

Внешние сервисы

Clientside

JavaScript

  • Без CClientScript::registerScriptFile().
    
    return array(
    'jquery.js',
    
    'widget.login.js',
    'widget.friends.js',
    
    'module.user.js',
    'module.post.js',
    );
                            
  • Модульная система, по модулю на 1-2 страницы.
  • + виджеты, структура примерно как у jQueryUI.
  • Все скрипты описываются явно в конфиге, жмутся при деплое.

CSS

  • LESS / SCSS …
  • Перечислены в конфиге, жмутся явно при деплое.

@base: #f938ab;

.box-shadow(@style, @c) when (iscolor(@c)) {
box-shadow:         @style @c;
-webkit-box-shadow: @style @c;
-moz-box-shadow:    @style @c;
}
.box-shadow(@style, @alpha: 50%) when (isnumber(@alpha)) {
.box-shadow(@style, rgba(0, 0, 0, @alpha));
}
.box {
color: saturate(@base, 5%);
border-color: lighten(@base, 30%);
div { .box-shadow(0 0 5px, 30%) }
}
                    

Соглашения CSS/JS

views/post/edit.php:


<div class="post-edit">...</div>
                    

css/post.css:


.post-edit p { ... }
.post-view h2 { ... }
                    

widgets/friends/views/index.php:


<div class="widget-friends-index">...</div>
                    

widgets/friends/assets/friends.css:


.widget-friends-index div { ... }
                                            
  • Глобальные классы g-*. Стили в global.css.
  • Layout использует префикс layout- и файл layout.css.

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

  • Readme.
  • API.
  • Комментарии.

Задачи

Шорткаты в global.php

Подключаются в index.php после инициализации приложения, но до запуска:


$app = Yii::createApplication('CWebApplication', $config);
include 'global.php';
$app->run();
                    

Примеры:


function app() {
return Yii::app();
}

function user() {
return Yii::app()->user;
}

function db() {
return Yii::app()->db;
}
                    

Шорткаты в global.php


function t($message, $params, $category = 'myproject') {
return Yii::t($category, $message, $params);
}
function h($text) {
return CHtml::encode($text);
}
function l(…) {
return CHtml::link(…);
}
function param($name, $default = null) {
return isset(Yii::app()->params[$name] ? Yii::app()->params[$name] : $default);
}
                    

Вопросы?