{{tag>Yii2 jquery ajax csrfToken url html view urlmanager activerecord docs}}

====== Документация по Yii 2 Framework ======

===== Configuration =====

<code php>
<?php
return [
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=localhost;dbname=yii2',
            'username' => 'yii2', 
            'password' => '<password>',
        ],
        'cache' => [
            'class' => 'yii\caching\DummyCache',
        ],      
        'urlManager' => [
            'rules' => [
                '<action:(login|logout|about)>' => 'site/<action>',
      
                // ...
      
                ['class' => 'app\components\CarUrlRule', 'connectionID' => 'db', ...],
            ],  
            'enablePrettyUrl' => true,
            'enableStrictParsing' => true,
            'showScriptName' => false,
            'suffix' => '.html',
        ],
    ]
];
</code>
===== URL Management =====

<code php>
echo \Yii::$app->urlManager->createUrl(['site/page', 'id' => 'about']);
// /index.php/site/page/id/about/
echo \Yii::$app->urlManager->createUrl(['date-time/fast-forward', 'id' => 105])
// /index.php?r=date-time/fast-forward&id=105
echo \Yii::$app->urlManager->createAbsoluteUrl('blog/post/index');
// http://www.example.com/index.php/blog/post/index/
</code>

<code php>
$route = [
// ... path + params
];

$url = \Yii::$app->urlManager;
$url->createUrl($route);
$url->createAbsoluteUrl($route);

$url = Yii::$app->urlManager->createUrl($route);
$url = Yii::$app->urlManager->createAbsoluteUrl($route);
</code>

==== Конфигурация ====

<code php>
<?php
return [
    // ...
    'components' => [
        'urlManager' => [
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'enableStrictParsing' => true,
            'suffix' => '.html',
            'rules' => [
                '<action:(login|logout|about)>' => 'site/<action>',
    
                // ...
    
                ['class' => 'app\components\CarUrlRule', 'connectionID' => 'db', ...],
            ],  
        ],
    ],
];
</code>
==== Url ====

=== yii\helpers\Url::toRoute ===

<code php>
echo Url::toRoute([''], $schema = false); // currently active route
echo Url::toRoute(['view', 'id' => 'contact'], $schema = false); // same controller, different action
echo Url::toRoute(['post/index'], $schema = false); // same module, different controller and action
echo Url::toRoute(['/site/index'], $schema = false); // absolute route no matter what controller is making this call
echo Url::toRoute(['post/read', 'id' => 100, '#' => 'title'], $schema = false)
</code>

<code php>
echo Url::toRoute('', $schema = false); // currently active route
echo Url::toRoute('post/index', $schema = false); // same module, different controller and action
echo Url::toRoute('/site/index', $schema = false); // absolute route no matter what controller is making this call
</code>

=== yii\helpers\Url::to ===

<code php>
echo Url::to('', $schema = false); // currently active route
echo Url::to('post/index', $schema = false); // same module, different controller and action
echo Url::to('/site/index', $schema = false); // absolute route no matter what controller is making this call
</code>

<code php>
echo Url::to('@web', $schema = false);
echo Url::canonical(); // get canonical URL for the curent page
echo Url::home(); // get home URL
echo Url::remember(); // save URL to be used later
echo Url::previous(); // get previously saved URL
</code>

  * **$schema = true** - Абсолютный адрес
  * **$schema = 'https'** - Указание на испоользование шифрованного протокола

Синоним для yii\helpers\Url::toRoute
<code php>
echo Url::to([''], $schema = false); // currently active route
echo Url::to(['view', 'id' => 'contact'], $schema = false); // same controller, different action
echo Url::to(['post/index'], $schema = false); // same module, different controller and action
echo Url::to(['/site/index'], $schema = false); // absolute route no matter what controller is making this call
echo Url::to(['post/read', 'id' => 100, '#' => 'title'], $schema = false)
</code>

Примеры использоватия можно глянуть в тестах https://github.com/yiisoft/yii2/blob/master/tests/unit/framework/helpers/UrlTest.php

=== yii\helpers\Html::url (old) ===

<code php>
echo Html::url(['']); // currently active route
echo Html::url(['view', 'id' => 'contact']); // same controller, different action
echo Html::url(['post/index']); // same module, different controller and action
echo Html::url(['/site/index']); // absolute route no matter what controller is making this call
echo Html::url(['post/read', 'id' => 100, '#' => 'title'])
</code>

<code php>
echo Html::url(''); // currently active route
echo Html::url('post/index'); // same module, different controller and action
echo Html::url('/site/index'); // absolute route no matter what controller is making this call
</code>

вместо старых методов нада использовать **yii\helpers\Url::to**

Примеры использоватия можно глянуть в тестах https://github.com/yiisoft/yii2/blob/master/tests/unit/framework/helpers/UrlTest.php

==== createUrl ====

<code php>
echo $this->createUrl([''], $schema = null); // currently active route
echo $this->createUrl(['view', 'id' => 'contact'], $schema = null); // same controller, different action
echo $this->createUrl(['post/index'], $schema = null); // same module, different controller and action
echo $this->createUrl(['/site/index'], $schema = null); // absolute route no matter what controller is making this call
echo $this->createUrl(['post/read', 'id' => 100, '#' => 'title'], $schema = null)
</code>

<code php>
echo $this->createUrl('', $schema = null); // currently active route
echo $this->createUrl('post/index', $schema = null); // same module, different controller and action
echo $this->createUrl('/site/index', $schema = null); // absolute route no matter what controller is making this call
</code>

=== createAbsoluteUrl (old) ===

Усли $this - это yii\web\Controller

<code php>
echo $this->createAbsoluteUrl([''], $schema = null); // currently active route
echo $this->createAbsoluteUrl(['view', 'id' => 'contact'], $schema = null); // same controller, different action
echo $this->createAbsoluteUrl(['post/index'], $schema = null); // same module, different controller and action
echo $this->createAbsoluteUrl(['/site/index'], $schema = null); // absolute route no matter what controller is making this call
echo $this->createAbsoluteUrl(['post/read', 'id' => 100, '#' => 'title'], $schema = null)
</code>

вместо старых методов надо использовать **yii\helpers::toRoute**

Усли $this - это yii\web\Controller

<code php>
echo $this->createAbsoluteUrl('', $schema = null); // currently active route
echo $this->createAbsoluteUrl('post/index', $schema = null); // same module, different controller and action
echo $this->createAbsoluteUrl('/site/index', $schema = null); // absolute route no matter what controller is making this call
</code>

вместо старых методов надо использовать **yii\helpers::toRoute**

==== Request ====

=== GET ===

<code php>
Yii::$app->request->get();
Yii::$app->request->getQueryParams();
Yii::$app->request->getQueryParam('File');
Yii::$app->request->get('File');
</code>

=== POST ===

<code php>
Yii::$app->request->post();
Yii::$app->request->getBodyParams();
Yii::$app->request->getBodyParam('File');
Yii::$app->request->post('File');
</code>

===== View =====

==== CSS ====

<code php>
$this->registerCssFile();
</code>

==== JS ====

<code php>
$this->registerJsFile();
</code>

=== Вставка кода внутри представления ===

В примере производится вставка JS кода из assets c применением переменной в скрипте JS_FABRIC_CAR_URL
<code php>
$this = Yii::$app->view;
</code>
  
<code php>
<?php 
$this->registerJs('var JS_FABRIC_CAR_URL = "' . Html::url(['/core/ajax/fabric-car']) . '";', View::POS_HEAD, 'js-fabric-car-url');
$publish = Yii::$app->assetManager->publish(Yii::getAlias('@app/modules/core/assets/js'));
$this->registerJsFile($publish[1] . '/block-select-car.js', [yii\web\JqueryAsset::className()], ['position'=>View::POS_END]);
?> 
</code>

==== assetManager ====

<code php>
'components' => [
    'assetManager' => [
        'class' => 'yii\web\AssetManager',
        'forceCopy' => true,          
    ],
],
</code>

  * forceCopy - Включает постоянное обновление асетов

=== через ajaxSetup ===

Добавление csrfToken в Ajax запрос (Yii2)

<code php>
$js_global_variables = '
$.ajaxSetup({
        data: ' . \yii\helpers\Json::encode([
            \yii::$app->request->csrfParam => \yii::$app->request->csrfToken,
        ]) . '
    });' . PHP_EOL;
$this->registerJs($js_global_variables, yii\web\View::POS_HEAD, 'js_global_variables');
</code>

или через header

<code php>
$js_global_variables = '
$.ajaxPrefilter(function( options ) {
    if ( !options.beforeSend) {
        options.beforeSend = function (xhr) { 
            xhr.setRequestHeader("HTTP_X_CSRF_TOKEN", ' . \yii::$app->request->csrfToken .');
        }
    }
});' . PHP_EOL;
$this->registerJs($js_global_variables, yii\web\View::POS_HEAD, 'js_global_variables');
</code>

или через JQuery

<code js>
      $.ajax({
        url: 'http://site?controller/action',
        type: 'post',
        data: {payload: payload, _csrf: yii.getCsrfToken()},        
        dataType: 'json',
      }).success(function(response) {
      });
</code>

==== Form ====

  * [[yii2:form|ActiveForm]]
  * [[yii2:form|HTML]]   

**Подробно** https://github.com/yiisoft/yii2/blob/master/docs/guide/form.md

===== Ajax =====

  * [[yii2:Ajax|Active Form Ajax Validation]]
  * [[yii2:Ajax:select|Зависимый select от другого select'а]]

==== Pjax ====

<code php>
use app\modules\cabinet\components\CabinetController;
use app\models\Image;

class CameraController extends CabinetController
{
    public function actionFavorite()
    {
        $id = (int) Yii::$app->request->post('id');

        if (!$id) {
            return false;
        }

        $image = Image::findOne($id);

        if ($image->f_fav) {
            Image::updateAll(['f_fav' => 0], ['id' => $id]);
            return $this->renderPartial('favorite', ['id' => $id, 'f_fav' => 0]);
        } else {
            Image::updateAll(['f_fav' => 1], ['id' => $id]);
            return $this->renderPartial('favorite', ['id' => $id, 'f_fav' => 1]);
        }

        return false;
    }
}  
</code>

Вывод партиала в main.php

<code php>
<?= $this->render('favorite', ['id' => 1, 'f_fav' => true);?>
</code>

Отображаемая вьюха favorite.php

<code php>
<?php
use yii\widgets\Pjax;
use yii\helpers\Html;
?>
<?php Pjax::begin(); ?>
<?= Html::beginForm(['favorite'], 'post', ['data-pjax' => '', 'class' => 'form-inline']); ?>
<?= Html::hiddenInput('id', $id) ?>
<?= Html::submitButton($f_fav ? '<i class="fa fa-star"></i>' : '<i class="fa fa-star-o"></i>', []) ?>
<?= Html::endForm() ?>
<?php Pjax::end(); ?>
</code>

===== Виджеты / Widgets =====

  * [[yii2:widgets:masked-input|]] - http://demos.krajee.com/masked-input

===== Model / AR / DAO / Запросы к БД =====

Как получить модель из модуля

<code php>
        $user    = Yii::$app->getModule("user")->model("User", ["scenario" => "register"]);
        $profile = Yii::$app->getModule("user")->model("Profile");
</code>

==== Active Record ====

<code php>
class Post extends ActiveRecord
{
    public function getCreator()
    {
        return $this->hasOne('User', ['id' => 'user_id']);
    }
    public function getComments()
    {
        return $this->hasMany('Comment', ['post_id' => 'id']);
    }
    public function getTrustComments($isTrust = true)
    {
        return $this->hasMany('Comment', ['post_id' => 'id'])
            ->where('status = :status', [
                     ':status' => $isTrust ? self::TRUST : self::UNTRUST,
              ])
            ->orderBy('id');
    }
}
</code>

<code php>
        $price = PriceItem::find()
            ->select(['price', 'create_time' => 'DATE_FORMAT(create_time, "%d.%m.%Y")'])
            ->where(['and', 
                ['price_list_form_id' => $price_list_form_ids], 
                ['>', 'create_time', '2015.01.01']
        ])->orderBy(['price' => SORT_ASC])->asArray()->one();
</code>

<code php>
// we receive an ActiveQuery instance
$query = Post::find();
 
// all posts
$posts = $query->all();
 
// looking for all the posts with a condition
$posts = $query
    ->where(array('status' => Post::DRAFT))
    ->orderBy('time')
    ->all();
 
// looking for a post 
$post = $query
   ->where(['id' => 10, 'status' => Post::READ])
   ->one();
 
// or easier: "where" condition can be transmitted directly to the factory method
$post = Post::find(['id' => 10, 'status' => Post::READ]);
 
// having transmitted to the factory method not a massive, but a number equivalent to the primary key search 
$post = Post::find(10)
   ->where(['status' => Post::READ])
   ->one();
 
// we index the result to a necessary attribute
$posts = $query->indexBy('title')->all();
 
// the result as an array
$posts = $query->asArray()->all();
</code>

<code php>
User::find()->where(['and', ['phone_number' => $phone], ['<>', 'id', $user->id] ])->exists();
User::find()->where(['or', ['phone_number' => $phone], ['=', 'id', $user->id] ])->exists();
</code>

=== Ключи в эллементах коллекции AR ===

<code php>
$query = SparesCategory::find()->where(['parent_id' => 0]);
$query->indexBy = function($row){ // Ключ в который будет помещена возвращаемая модель
    return $row->id;
};
$categories = $query->all();
</code>

<code php>
        $quey = CarMark::find()->indexBy(function($row){
            return $row->id;
        })->all();
</code>

=== Создание модели из возвращаемы данных Command (с помощью populateRecord()) ===

<code php>
        $sql = "SELECT * FROM `tbl_spares_category` c
            LEFT JOIN tbl_form_spares_category fc ON fc.category_id = c.id
            WHERE fc.form_id = :form_id AND fc.category_id = :category_id";
        $select_marks = Yii::$app->db->createCommand($sql, [
            ':form_id' => $form_id,
            ':category_id' => $category_id,
        ])->queryAll();
  
        foreach($marks as $row){
            
            // Only yii2 alpha
            //$mark = SparesCategoryForm::create($row);
          
            $mark = new SparesCategoryForm;
            SparesCategoryForm::populateRecord($mark, $row);
            
  
            if(isset($mark->id)){
  
              // do somethig
  
            }
        }
</code>

  * [[Activedataprovider|Activedataprovider]]
  * [[SqlDataProvider|SqlDataProvider]]
  * [[ArrayDataProvider|ArrayDataProvider]]
==== Join ====

=== with() ===

Не делает SQL JOIN(), применяется не только в реляционых БД (NoSql)
Применяется только для построений конструкций вида **WHERE IN()**, плюс наполняют [[yii2:start#relation|relation]]

=== leftJoin() ===

Добавляет SQL LEFT JOIN(), применяется только в реляционыых БД, плюс наполняют [[yii2:start#relation|relation]]

<code php>
$this->joinWith([[relation_name]], true, 'LEFT JOIN')
</code>

=== joinWith() ===

Добавляет SQL JOIN(), применяется только в реляционыых БД, плюс наполняют [[yii2:start#relation|relation]]

<code php>
// Выбираем MyModel с relation1 и relation2.
// Все три забираем запросом с JOIN.
$query = MyModel::find()
    ->joinWith(['relation1', 'relation2']);
 
$countQuery = clone $query;
$pages = new Pagination(['totalCount' => $countQuery->count(), 'pageSize' => 15]);
 
$items = $query
    ->orderBy($sort->orders)
    ->offset($pages->offset)
    ->limit($pages->limit)
    // Забираем дополнительно relation3 и relation4.
    // Фильтровать по ним нам не нужно, так что будут
    // запросы вида WHERE ID IN (1,2,3,4) или аналоги
    // для noSQL.
    ->with(['relation3', 'relation4'])
    ->all();
</code>

https://github.com/yiisoft/yii2/blob/master/docs/guide/active-record.md#joining-with-relations

=== innerJoinWith() ===

==== Validate (Rules) ====

<code php>
class User extends \yii\db\ActiveRecord
{
    // ...
 
    public function rule()
    {
        return [
                  [
                    ['attribute1', 'attribute2', ...],
                    'validator class or alias',
                    // specifies in which scenario(s) this rule is active.
                    // if not given, it means it is active in all scenarios
                    'on' => ['scenario1', 'scenario2', ...],
                    // the following name-value pairs will be used
                    // to initialize the validator properties
                    'property1' => 'value1',
                    'property2' => 'value2',
                    // ...
                  ],
                  [
                    ['attribute1', 'attribute2', ...],
                    'validator class or alias',
                    // specifies in which scenario(s) this rule is active.
                    // if not given, it means it is active in all scenarios
                    'except' => ['scenario1', 'scenario2', ...],
                    // the following name-value pairs will be used
                    // to initialize the validator properties
                    'property1' => 'value1',
                    'property2' => 'value2',
                    // ...
                  ],          
              ];
    }
 
}
</code>

Пример использования в модели
<code php>
  if ($User->load($_POST)) {

      $User = new User;
      $Profile = new Profile;

      // validate for ajax request
      $Profile->load($_POST);
      if (Yii::$app->request->isAjax) {
          Yii::$app->response->format = Response::FORMAT_JSON;
          return ActiveForm::validate($User, $Profile);
      }

      // validate for normal request
      if ($User->validate() and $Profile->validate()) {
        // do somthing
      }
  }
</code>

Пример применения валидатора без использования модели
<code php>
$email = 'test@example.com';
$validator = new yii\validators\EmailValidator();
if ($validator->validate($email, $error)) {
    echo 'Email is valid.';
} else {
    echo $error;
}
</code>

  * **Подробно** https://github.com/yiisoft/yii2/blob/master/docs/guide/model.md
  * **Список базовых валидаторов:** https://github.com/yiisoft/yii2/blob/master/docs/guide/validation.md

==== Scenario ====

<code php>
class User extends \yii\db\ActiveRecord
{
    // ...

    public function getProduct()
    {
        return $this->hasOne(Order::className(), ['product_id' => 'id']);
    }

    public function scenarios()
    {
        return [
            'userCreates' => [
                'attributes' => ['name', 'value'],
                'atomic' => [self::OP_INSERT],
            ],
        ];
    }
  
    public function afterSave($insert)
    {
        parent::afterSave($insert);
        if ($this->getScenario() ==== 'userCreates') {
            // FIXME: TODO: WIP, TBD
        }
    }
}
</code>

**Подробно** https://github.com/yiisoft/yii2/blob/master/docs/guide/structure-models.md#scenarios-

==== Relation ====

<code php>
class Customer extends \yii\db\ActiveRecord
{
    //
    public function getOrders()
    {
        return $this->hasMany(Order::className(), ['customer_id' => 'id']);
    }    
  
    //
    public function getBigOrders($threshold = 100)
    {
        return $this->hasMany(Order::className(), ['customer_id' => 'id'])
            ->where('subtotal > :threshold', [':threshold' => $threshold])
            ->orderBy('id');
    }

    // Вытащить данные из таблицы модели Item, используя связи из таблицы tbl_order_item
    public function getItems()
    {
      // Получить данные через таблицу tbl_order_item
      return $this->hasMany(Item::className(), ['id' => 'item_id'])
            ->viaTable('tbl_order_item', ['order_id' => 'id']);
    }
    
    //
    public static function olderThan($query, $age = 30)
    {
        $query->andWhere('age > :age', [':age' => $age]);
    }
}
</code>

<code php>
$customer = Customer::find(1);
$orders = $customer->orders;
$orders = $customer->getBigOrders(200)->all();
$customers = Customer::find()->olderThan(50)->all();
</code>

<code php>
$customer = Customer::find(1);
$order = new Order();
$order->comment = '';
$customer->link('orders', $customer);
</code>

==== Events ====

<code php>
class Post extends ActiveRecord
{
  public function init()
  {
    $this->on('beforeAction', function($event) {
      // отменяем действие
      $event->isValid = false;
    });
  }
}
</code>

<code php>
$component->on('beforeAction', $handler);
</code>
==== Как получить SQL и Параметры из ActiveQuery ====

<code php>
$query = Post::find()->where(array('id' => 10, 'status' => Post::READ))->createCommand();

// SQL
echo $query->sql

// Params:
print_r($query->params)  
</code>
==== Объекты доступа к данным (Data Access Objects, DAO) ====

=== Соеденение ===

<code php>
$connection = \Yii::$app->db;
</code>

**Подробно** 

  * https://github.com/yiisoft/yii2/blob/master/docs/guide/database-basics.md

=== Методы запроса ===

  * queryOne()
  * queryAll()
  * query()
  * queryScalar()
  * queryColumn()

**Подробно**  https://github.com/yiisoft/yii2/blob/master/framework/db/Command.php

== createCommand ==

<code php>
$command = $connection->createCommand('SELECT * FROM tbl_post WHERE id=1');
$post = $command->queryOne();
</code>

<code php>
$connection->createCommand()->insert('tbl_user', [
    'name' => 'Sam',
    'age' => 30,
])->execute();
</code>

<code php>
$command = $connection->createCommand('UPDATE tbl_post SET status=1 WHERE id=1');
$command->execute();
</code>

<code php>
$connection->createCommand()->batchInsert('tbl_user', ['name', 'age'], [
    ['Tom', 30],
    ['Jane', 20],
    ['Linda', 25],
])->execute();
</code>

<code php>
$connection->createCommand()->update('tbl_user', ['status' => 1], 'age > 30')->execute();
</code>

<code php>
$connection->createCommand()->delete('tbl_user', 'status = 0')->execute();
</code>

<code php>
$command = $connection->createCommand('SELECT * FROM tbl_post WHERE id=:id');
$command->bindValue(':id', $_GET['id']);
$post = $command->query();
</code>

==== Построитель запросов (Query Builder and Query) ====

<code php>
$rows = (new \yii\db\Query())
    ->select('id, name')
    ->from('user')
    ->limit(10)
    ->all();

// which is equivalent to the following code:

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

// Create a command. You can get the actual SQL using $command->sql
$command = $query->createCommand();

// Execute the command:
$rows = $command->queryAll();
</code>

<code php>
$query = (new \yii\db\Query())
    ->select('id, name')
    ->from('user')
    ->limit(10);

// Create a command. You can get the actual SQL using $command->sql
$command = $query->createCommand(Yii::$app->db);

// Execute the command:
$rows = $command->queryAll();
</code>

Простой спооб получить записи из указанной БД

<code php>
$rows = (new \yii\db\Query())
    ->select('id, name')
    ->from('user')
    //->where([...])
    //->innerJoin('', '', [...])
    ->limit(10)
    ->createComand(Yii::$app->some_bd)
    ->queryAll();
</code>

**Подробно** 

  * https://github.com/yiisoft/yii2/blob/master/docs/guide/db-query-builder.md

==== Transactions ====

<code php>
$transaction = $connection->beginTransaction();
try {
    $connection->createCommand($sql1)->execute();
    $connection->createCommand($sql2)->execute();
    // ... executing other SQL statements ...
    $transaction->commit();
} catch(Exception $e) {
    $transaction->rollback();
}
</code>

==== Batch ====

=== Batch ===


<code php>
foreach (Customer::find()->batch() as $customers) {

}

foreach (Customer::find()->batch(10) as $customers) {
    // $customers — массив из 10 или менее объектов Customer
}
</code>

<code php>
$rows = [];

foreach ($models as $model) {
    if (!$model->validate()) {
        // At least one model has invalid data

        break;
    }

    $rows[] = $model->attributes;
}
$rows =  \yii\helpers\ArrayHelper::getColumn($models, 'attributes;');
$postModel = new Post;

Yii::$app->db->createCommand()->batchInsert(Post::tableName(), $postModel->attributes(), $rows)->execute();
</code>

=== Each ===

<code php>
foreach (Customer::find()->each() as $customers) {

}

foreach (Customer::find()->each(10) as $customers) {
    // $customers — массив из 10 или менее объектов Customer
}
</code>

===== Controller =====

==== Как программно вызвать контроллер? ====

<code php>
$className = 'backend\controllers\SiteController';
$controller = Yii::createObject($className, [$id, $this]);
</code>

==== yii\helpers\Html (old) ====

<code php>
// ['label' => 'Добавление', 'url' => ['/admin/user/create']]
Html::a("Log in here", ["user/reset", "hash" => $hash, "sid" => $sid]);
Html::url(["user/reset", "hash" => $hash, "sid" => $sid]);
</code>

**Подробно** https://github.com/yiisoft/yii2/blob/master/docs/guide/url.md

===== Module =====

==== Submodule ====

Для работы сабмодуля, необходимо выполнить его подключение, через указание submodule namespace модуля
<code php>
namespace mirocow\eav;

class Module extends \yii\base\Module {
  
    // ...
    public function init() {

      // ..

      $this->setModule('admin', 'yii\user\modules\admin\Module');
    }
  
    // Пример перенаправления роута в саб модуль admin
    public function createController($route) {
      
        return $this->getModule('admin')->createController(str_replace('admin/','',$route));
      
    }  
  
}
</code>

==== Helpers ====

  * https://github.com/yiisoft/yii2/blob/master/docs/guide/security.md

==== Behaviors/Filters ====

<code php>
public function behaviors()
{
  return array(
    'access' => array(
      'class' => 'yii\web\AccessControl',
      'rules' => array(
        array('allow' => true, 'actions' => array('admin'), 'roles' => array('@')),
        array('allow' => false),
      ),
    ),
  );
}
</code>

==== Behaviors/Date ====

<code php>
public function behaviors() {
  return [
    [
      'class' => TimestampBehavior::className(),
      'createdAtAttribute' => 'create_time',
      //'updatedAtAttribute' => 'update_time',
      'value' => new Expression('NOW()'),
    ],
  ];
}
</code>
===== Session =====

<code php>
Yii::$app->session->get('key');
Yii::$app->session->set('key', 'value');
</code>

==== setFlash ====

В контролере
<code php>
Yii::$app->session->setFlash('info', $shell->output);
return $this->redirect('/site');
</code>
return делать обязательно. инчаче после редиректа сообщение не выведется

Вывод стандартным способом
<code php>
<?php foreach (Yii::$app->session->getAllFlashes() as $key => $message) {
  echo '<div class="alert alert-' . $key . '">' . $message . '</div>';
} ?>
</code>

Вывод с помощью виджета [[https://github.com/loveorigami/yii2-notification-wrapper|loveorigami/yii2-notification-wrapper]]
<code php>
<?= Wrapper::widget([
  'layerClass' => 'lo\modules\noty\layers\Noty',
]);?>
</code>
Данный виджет поддерживает большое кол-во виджетов обображения таких как:
| Library (Layer)      | Bower                        | Project homepage                                      | Docs                       |
| Bootstrap Alert      | -                            | http://getbootstrap.com/components/#alerts            | docs/Alert.md              |
| Bootstrap Notify     | remarkable-bootstrap-notify  | https://github.com/mouse0270/bootstrap-notify         | docs/BootstrapNotify.md    |
| Growl                | jquery-growl                 | https://github.com/ksylvest/jquery-growl              | docs/Growl.md              |
| iGrowl               | igrowl                       | https://github.com/catc/iGrowl                        | docs/Igrowl.md             |
| jQuery Notify        | jquery.notify                | https://github.com/CreativeDream/jquery.notify        | docs/JqueryNotify.md       |
| jQuery Notify Bar    | jqnotifybar                  | https://github.com/dknight/jQuery-Notify-bar          | docs/JqueryNotifyBar.md    |
| jQuery Toaster       | jquery.toaster               | https://github.com/scottoffen/jquery.toaster          | docs/JqueryToaster.md      |
| jQuery Toast Plugin  | jquery-toast-plugin          | https://github.com/kamranahmedse/jquery-toast-plugin  | docs/JqueryToastPlugin.md  |
| Lobibox              | lobibox                      | https://github.com/arboshiki/lobibox                  | docs/Lobibox.md            |
| Notie                | notie                        | https://github.com/jaredreich/notie                   | docs/Notie.md              |
| Notific8             | notific8                     | https://github.com/ralivue/notific8                   | docs/Notific8.md           |
| NotifIt              | notifit                      | https://github.com/naoxink/notifIt                    | docs/NotifIt.md            |
| Notify.js            | notifyjs                     | https://github.com/notifyjs/notifyjs                  | docs/Notifyjs.md           |
| Noty                 | noty                         | https://github.com/needim/noty                        | docs/Noty.md               |
| PNotify              | pnotify                      | https://github.com/sciactive/pnotify                  | docs/PNotify.md            |
| Sweetalert           | sweetalert                   | https://github.com/t4t5/sweetalert                    | docs/Sweetalert.md         |
| Toastr               | toastr                       | https://github.com/CodeSeven/toastr                   | docs/Toastr.md             |


===== Console =====

==== IsConsole ====

<code php>
 if(Yii::$app->request->isConsoleRequest){
   //
 }
</code>

==== Params / Параметры ====

<code php>
<?php

namespace console\controllers;

use yii\console\Controller;

class QueueController extends Controller
{
    public $pid_file = '';

    public function __get($name)
    {
        $name = str_replace('-', '_', $name);

        return $this->$name;
    }

    public function __set($name, $value)
    {
        $name = str_replace('-', '_', $name);

        $this->$name = $value;
    }


    public function options($actionID)
    {
        return ['pid-file'];
    }

    public function actionRun()
    {

    }
}
</code>


===== User =====

==== RBAC ====

  * [[yii2:user:rbac|RBAC]]

**Подробно** https://github.com/yiisoft/yii2/blob/master/docs/guide/authorization.md

==== Access ====

<code php>
    'access' => [
            'class' => \yii\web\AccessControl::className(),
            'rules' => [
                    [
                            'actions' => ['index'],
                            'allow' => false,
                            'roles' => ['?'],
                    ],
                    [
                            'actions' => ['index', 'update','view','create','delete'],
                            'allow' => true,
                            'matchCallback' => function() {
                            return \Yii::$app->user->identity->role <= \Yii::$app->user->identity->MANAGER;                    
                            }
                    ],
            ],
    ],  
</code>


===== Components =====

Создание объекта компанента
<code php>
$object = Yii::createObject(array(
    'class' => 'MyClass',
    'property1' => 'abc',
    'property2' => 'cde',
), $param1, $param2);
</code>

===== Theme =====

<code php>
'view' => array(
    'theme' => array(
        'pathMap' => array('@app/views' => '@webroot/themes/basic'),
        'baseUrl' => '@www/themes/basic',
    ),
),
</code>

===== Cache =====

<code php>
// Создать зависимость от времени модификации файла example.txt.
$dependency = new \yii\caching\FileDependency(['fileName' => 'example.txt']);

// Данные устаревают через 30 секунд.
// Данные могут устареть и раньше, если example.txt будет изменён.
$cache->set($key, $data, 30, $dependency);

// Кэш будет проверен, если данные устарели.
// Он также будет проверен, если указанная зависимость была изменена.
// Вернется false, если какое-либо из этих условий выполнено.
$data = $cache->get($key);
</code>

==== Зависимости ====

  * [[yii\caching\ChainedDependency]]: зависимость меняется, если любая зависимость в цепочке изменяется;
  * [[yii\caching\DbDependency]]: зависимость меняется, если результат некоторого определенного SQL запроса изменён;
  * [[yii\caching\ExpressionDependency]]: зависимость меняется, если результат определенного PHP выражения изменён;
  * [[yii\caching\FileDependency]]: зависимость меняется, если изменилось время последней модификации файла;
  * [[yii\caching\TagDependency]]: Связывает кэшированные данные элемента с одним или несколькими тегами. Вы можете аннулировать кэширование данных элементов с заданным тегом(тегами) по вызову. [[yii\caching\TagDependency::invalidate()]];

==== Кэширование запросов ====

<code php>
$result = $db->cache(function ($db) {

    // Результат SQL запроса будет возвращен из кэша если
    // кэширование запросов включено и результат запроса присутствует в кэше
    return $db->createCommand('SELECT * FROM customer WHERE id=1')->queryOne();

});

$result = Customer::getDb()->cache(function ($db) {
    return Customer::find()->where(['id' => 1])->one();
});
</code>

<code php>
$duration = 60;     // кэширование результата на 60 секунд
$dependency = ...;  // параметры зависимости

$result = $db->cache(function ($db) {

    // ... выполнять SQL запросы здесь ...

    return $result;

}, $duration, $dependency);
</code>

<code php>
$result = $db->cache(function ($db) {

    // SQL запросы, которые используют кэширование

    $db->noCache(function ($db) {

        // SQL запросы, которые не используют кэширование

    });

    // ...

    return $result;
});
</code>

<code php>
// использовать кэширование запросов и установить срок действия кэша на 60 секунд
$customer = $db->createCommand('SELECT * FROM customer WHERE id=1')->cache(60)->queryOne();
</code>

<code php>
$result = $db->cache(function ($db) {

    // Используется кэширование SQL запросов

    // не использовать кэширование запросов для этой команды
    $customer = $db->createCommand('SELECT * FROM customer WHERE id=1')->noCache()->queryOne();

    // ...

    return $result;
});
</code>

===== Локализация - i18N/intl =====

  apt=get install php5-intl

==== Перевод (локализация проекта) ====

  * https://github.com/lajax/yii2-translate-manager

===== PHPUnit =====

добавить в конфигуратор композера composer.json
<code>
{
    "require-dev": {
        "phpunit/phpunit": "3.7.*"
    }
}
</code>

    * php composer.phar update
    * php vendor/bin/phpunit vendor/yiisoft/yii2/yii/test/

====== Статьи ======

  * https://github.com/yiisoft/yii2/blob/master/docs/guide-ru/caching-data.md
  * https://gist.github.com/jkovacs618/ab225ecadf55cb1feca9
  * http://habrahabr.ru/post/208328/

====== Описание ======

  * https://github.com/yiisoft/yii2/blob/master/docs/guide/i18n.md#advanced-placeholder-formatting
  * http://userguide.icu-project.org/formatparse/messages
  * http://icu-project.org/apiref/icu4c/classMessageFormat.html
