Документация по Yii 2 Framework
Configuration
<?phpreturn['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',],]];
URL Management
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=105echo \Yii::$app->urlManager->createAbsoluteUrl('blog/post/index');// http://www.example.com/index.php/blog/post/index/
$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);
Конфигурация
<?phpreturn[// ...'components'=>['urlManager'=>['enablePrettyUrl'=>true,'showScriptName'=>false,'enableStrictParsing'=>true,'suffix'=>'.html','rules'=>['<action:(login|logout|about)>'=>'site/<action>',
// ...
['class'=>'app\components\CarUrlRule','connectionID'=>'db',...],],],],];
Url
yii\helpers\Url::toRoute
echo Url::toRoute([''],$schema=false);// currently active routeecho Url::toRoute(['view','id'=>'contact'],$schema=false);// same controller, different actionecho Url::toRoute(['post/index'],$schema=false);// same module, different controller and actionecho Url::toRoute(['/site/index'],$schema=false);// absolute route no matter what controller is making this callecho Url::toRoute(['post/read','id'=>100,'#'=>'title'],$schema=false)
echo Url::toRoute('',$schema=false);// currently active routeecho Url::toRoute('post/index',$schema=false);// same module, different controller and actionecho Url::toRoute('/site/index',$schema=false);// absolute route no matter what controller is making this call
yii\helpers\Url::to
echo Url::to('',$schema=false);// currently active routeecho Url::to('post/index',$schema=false);// same module, different controller and actionecho Url::to('/site/index',$schema=false);// absolute route no matter what controller is making this call
echo Url::to('@web',$schema=false);echo Url::canonical();// get canonical URL for the curent pageecho Url::home();// get home URLecho Url::remember();// save URL to be used laterecho Url::previous();// get previously saved URL
Синоним для yii\helpers\Url::toRoute
echo Url::to([''],$schema=false);// currently active routeecho Url::to(['view','id'=>'contact'],$schema=false);// same controller, different actionecho Url::to(['post/index'],$schema=false);// same module, different controller and actionecho Url::to(['/site/index'],$schema=false);// absolute route no matter what controller is making this callecho Url::to(['post/read','id'=>100,'#'=>'title'],$schema=false)
Примеры использоватия можно глянуть в тестах https://github.com/yiisoft/yii2/blob/master/tests/unit/framework/helpers/UrlTest.php
yii\helpers\Html::url (old)
echo Html::url(['']);// currently active routeecho Html::url(['view','id'=>'contact']);// same controller, different actionecho Html::url(['post/index']);// same module, different controller and actionecho Html::url(['/site/index']);// absolute route no matter what controller is making this callecho Html::url(['post/read','id'=>100,'#'=>'title'])
echo Html::url('');// currently active routeecho Html::url('post/index');// same module, different controller and actionecho Html::url('/site/index');// absolute route no matter what controller is making this call
вместо старых методов нада использовать yii\helpers\Url::to
Примеры использоватия можно глянуть в тестах https://github.com/yiisoft/yii2/blob/master/tests/unit/framework/helpers/UrlTest.php
createUrl
echo$this->createUrl([''],$schema=null);// currently active routeecho$this->createUrl(['view','id'=>'contact'],$schema=null);// same controller, different actionecho$this->createUrl(['post/index'],$schema=null);// same module, different controller and actionecho$this->createUrl(['/site/index'],$schema=null);// absolute route no matter what controller is making this callecho$this->createUrl(['post/read','id'=>100,'#'=>'title'],$schema=null)
echo$this->createUrl('',$schema=null);// currently active routeecho$this->createUrl('post/index',$schema=null);// same module, different controller and actionecho$this->createUrl('/site/index',$schema=null);// absolute route no matter what controller is making this call
createAbsoluteUrl (old)
Усли $this - это yii\web\Controller
echo$this->createAbsoluteUrl([''],$schema=null);// currently active routeecho$this->createAbsoluteUrl(['view','id'=>'contact'],$schema=null);// same controller, different actionecho$this->createAbsoluteUrl(['post/index'],$schema=null);// same module, different controller and actionecho$this->createAbsoluteUrl(['/site/index'],$schema=null);// absolute route no matter what controller is making this callecho$this->createAbsoluteUrl(['post/read','id'=>100,'#'=>'title'],$schema=null)
вместо старых методов надо использовать yii\helpers::toRoute
Усли $this - это yii\web\Controller
echo$this->createAbsoluteUrl('',$schema=null);// currently active routeecho$this->createAbsoluteUrl('post/index',$schema=null);// same module, different controller and actionecho$this->createAbsoluteUrl('/site/index',$schema=null);// absolute route no matter what controller is making this call
вместо старых методов надо использовать yii\helpers::toRoute
Request
GET
Yii::$app->request->get();
Yii::$app->request->getQueryParams();
Yii::$app->request->getQueryParam('File');
Yii::$app->request->get('File');
POST
Yii::$app->request->post();
Yii::$app->request->getBodyParams();
Yii::$app->request->getBodyParam('File');
Yii::$app->request->post('File');
View
CSS
$this->registerCssFile();
JS
Вставка кода внутри представления
В примере производится вставка JS кода из assets c применением переменной в скрипте JS_FABRIC_CAR_URL
$this= Yii::$app->view;
<?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]);?>
assetManager
'components'=>['assetManager'=>['class'=>'yii\web\AssetManager','forceCopy'=>true,],],
через ajaxSetup
Добавление csrfToken в Ajax запрос (Yii2)
$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');
или через header
$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');
или через JQuery
$.ajax({
url: 'http://site?controller/action',
type: 'post',
data: {payload: payload, _csrf: yii.getCsrfToken()},
dataType: 'json',
}).success(function(response) {
});
Ajax
Pjax
use app\modules\cabinet\components\CabinetController;use app\models\Image;
class CameraController extends CabinetController
{publicfunction actionFavorite(){$id=(int) Yii::$app->request->post('id');
if(!$id){returnfalse;}
$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]);}
returnfalse;}}
Вывод партиала в main.php
<?=$this->render('favorite',['id'=>1,'f_fav'=>true);?>
Отображаемая вьюха favorite.php
<?phpuse 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();?>
Model / AR / DAO / Запросы к БД
Как получить модель из модуля
$user= Yii::$app->getModule("user")->model("User",["scenario"=>"register"]);$profile= Yii::$app->getModule("user")->model("Profile");
Active Record
class Post extends ActiveRecord
{publicfunction getCreator(){return$this->hasOne('User',['id'=>'user_id']);}publicfunction getComments(){return$this->hasMany('Comment',['post_id'=>'id']);}publicfunction getTrustComments($isTrust=true){return$this->hasMany('Comment',['post_id'=>'id'])->where('status = :status',[':status'=>$isTrust ? self::TRUST:self::UNTRUST,])->orderBy('id');}}
$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();
// 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();
User::find()->where(['and',['phone_number'=>$phone],['<>','id',$user->id]])->exists();
User::find()->where(['or',['phone_number'=>$phone],['=','id',$user->id]])->exists();
Ключи в эллементах коллекции AR
$query= SparesCategory::find()->where(['parent_id'=>0]);$query->indexBy=function($row){// Ключ в который будет помещена возвращаемая модельreturn$row->id;};$categories=$query->all();
$quey= CarMark::find()->indexBy(function($row){return$row->id;})->all();
Создание модели из возвращаемы данных Command (с помощью populateRecord())
$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($marksas$row){
// Only yii2 alpha//$mark = SparesCategoryForm::create($row);
$mark=new SparesCategoryForm;
SparesCategoryForm::populateRecord($mark,$row);
if(isset($mark->id)){
// do somethig
}}
Join
with()
Не делает SQL JOIN(), применяется не только в реляционых БД (NoSql)
Применяется только для построений конструкций вида WHERE IN(), плюс наполняют relation
leftJoin()
Добавляет SQL LEFT JOIN(), применяется только в реляционыых БД, плюс наполняют relation
$this->joinWith([[relation_name]],true,'LEFT JOIN')
joinWith()
Добавляет SQL JOIN(), применяется только в реляционыых БД, плюс наполняют relation
// Выбираем 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();
https://github.com/yiisoft/yii2/blob/master/docs/guide/active-record.md#joining-with-relations
innerJoinWith()
Validate (Rules)
class User extends \yii\db\ActiveRecord
{// ...
publicfunction 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',// ...],];}
}
Пример использования в модели
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 requestif($User->validate() and $Profile->validate()){// do somthing}}
Пример применения валидатора без использования модели
$email='test@example.com';$validator=new yii\validators\EmailValidator();if($validator->validate($email,$error)){echo'Email is valid.';}else{echo$error;}
Scenario
class User extends \yii\db\ActiveRecord
{// ...
publicfunction getProduct(){return$this->hasOne(Order::className(),['product_id'=>'id']);}
publicfunction scenarios(){return['userCreates'=>['attributes'=>['name','value'],'atomic'=>[self::OP_INSERT],],];}
publicfunction afterSave($insert){
parent::afterSave($insert);if($this->getScenario()===='userCreates'){// FIXME: TODO: WIP, TBD}}}
Подробноhttps://github.com/yiisoft/yii2/blob/master/docs/guide/structure-models.md#scenarios-
Relation
class Customer extends \yii\db\ActiveRecord
{//publicfunction getOrders(){return$this->hasMany(Order::className(),['customer_id'=>'id']);}
//publicfunction getBigOrders($threshold=100){return$this->hasMany(Order::className(),['customer_id'=>'id'])->where('subtotal > :threshold',[':threshold'=>$threshold])->orderBy('id');}
// Вытащить данные из таблицы модели Item, используя связи из таблицы tbl_order_itempublicfunction getItems(){// Получить данные через таблицу tbl_order_itemreturn$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]);}}
$customer= Customer::find(1);$orders=$customer->orders;$orders=$customer->getBigOrders(200)->all();$customers= Customer::find()->olderThan(50)->all();
$customer= Customer::find(1);$order=new Order();$order->comment='';$customer->link('orders',$customer);
Events
class Post extends ActiveRecord
{publicfunction init(){$this->on('beforeAction',function($event){// отменяем действие$event->isValid=false;});}}
$component->on('beforeAction',$handler);
Как получить SQL и Параметры из ActiveQuery
$query= Post::find()->where(array('id'=>10,'status'=> Post::READ))->createCommand();
// SQLecho$query->sql
// Params:print_r($query->params)
Объекты доступа к данным (Data Access Objects, DAO)
Соеденение
$connection= \Yii::$app->db;
Подробно
Методы запроса
createCommand
$command=$connection->createCommand('SELECT * FROM tbl_post WHERE id=1');$post=$command->queryOne();
$connection->createCommand()->insert('tbl_user',['name'=>'Sam','age'=>30,])->execute();
$command=$connection->createCommand('UPDATE tbl_post SET status=1 WHERE id=1');$command->execute();
$connection->createCommand()->batchInsert('tbl_user',['name','age'],[['Tom',30],['Jane',20],['Linda',25],])->execute();
$connection->createCommand()->update('tbl_user',['status'=>1],'age > 30')->execute();
$connection->createCommand()->delete('tbl_user','status = 0')->execute();
$command=$connection->createCommand('SELECT * FROM tbl_post WHERE id=:id');$command->bindValue(':id',$_GET['id']);$post=$command->query();
Построитель запросов (Query Builder and Query)
$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();
$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();
Простой спооб получить записи из указанной БД
$rows=(new \yii\db\Query())->select('id, name')->from('user')//->where([...])//->innerJoin('', '', [...])->limit(10)->createComand(Yii::$app->some_bd)->queryAll();
Подробно
Transactions
$transaction=$connection->beginTransaction();
try {$connection->createCommand($sql1)->execute();$connection->createCommand($sql2)->execute();// ... executing other SQL statements ...$transaction->commit();} catch(Exception $e){$transaction->rollback();}
Batch
Batch
foreach(Customer::find()->batch()as$customers){
}
foreach(Customer::find()->batch(10)as$customers){// $customers — массив из 10 или менее объектов Customer}
$rows=[];
foreach($modelsas$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();
Each
foreach(Customer::find()->each()as$customers){
}
foreach(Customer::find()->each(10)as$customers){// $customers — массив из 10 или менее объектов Customer}
Controller
Как программно вызвать контроллер?
$className='backend\controllers\SiteController';$controller= Yii::createObject($className,[$id,$this]);
yii\helpers\Html (old)
Module
Submodule
Для работы сабмодуля, необходимо выполнить его подключение, через указание submodule namespace модуля
namespace mirocow\eav;
class Module extends \yii\base\Module {
// ...publicfunction init(){
// ..
$this->setModule('admin','yii\user\modules\admin\Module');}
// Пример перенаправления роута в саб модуль adminpublicfunction createController($route){
return$this->getModule('admin')->createController(str_replace('admin/','',$route));
}
}
Helpers
Behaviors/Filters
publicfunction behaviors(){returnarray('access'=>array('class'=>'yii\web\AccessControl','rules'=>array(array('allow'=>true,'actions'=>array('admin'),'roles'=>array('@')),array('allow'=>false),),),);}
Behaviors/Date
publicfunction behaviors(){return[['class'=> TimestampBehavior::className(),'createdAtAttribute'=>'create_time',//'updatedAtAttribute' => 'update_time','value'=>new Expression('NOW()'),],];}
Session
Yii::$app->session->get('key');
Yii::$app->session->set('key','value');
setFlash
В контролере
Yii::$app->session->setFlash('info',$shell->output);return$this->redirect('/site');
return делать обязательно. инчаче после редиректа сообщение не выведется
Вывод стандартным способом
<?phpforeach(Yii::$app->session->getAllFlashes()as$key=>$message){echo'<div class="alert alert-'.$key.'">'.$message.'</div>';}?>
Вывод с помощью виджета loveorigami/yii2-notification-wrapper
<?= Wrapper::widget(['layerClass'=>'lo\modules\noty\layers\Noty',]);?>
Данный виджет поддерживает большое кол-во виджетов обображения таких как:
Console
IsConsole
if(Yii::$app->request->isConsoleRequest){//}
Params / Параметры
<?php
namespace console\controllers;
use yii\console\Controller;
class QueueController extends Controller
{public$pid_file='';
publicfunction __get($name){$name=str_replace('-','_',$name);
return$this->$name;}
publicfunction __set($name,$value){$name=str_replace('-','_',$name);
$this->$name=$value;}
publicfunction options($actionID){return['pid-file'];}
publicfunction actionRun(){
}}
User
RBAC
Access
'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;}],],],
Components
Создание объекта компанента
$object= Yii::createObject(array('class'=>'MyClass','property1'=>'abc','property2'=>'cde',),$param1,$param2);
Theme
'view'=>array('theme'=>array('pathMap'=>array('@app/views'=>'@webroot/themes/basic'),'baseUrl'=>'@www/themes/basic',),),
Cache
// Создать зависимость от времени модификации файла example.txt.$dependency=new \yii\caching\FileDependency(['fileName'=>'example.txt']);
// Данные устаревают через 30 секунд.// Данные могут устареть и раньше, если example.txt будет изменён.$cache->set($key,$data,30,$dependency);
// Кэш будет проверен, если данные устарели.// Он также будет проверен, если указанная зависимость была изменена.// Вернется false, если какое-либо из этих условий выполнено.$data=$cache->get($key);
Зависимости
yii\caching\TagDependency: Связывает кэшированные данные элемента с одним или несколькими тегами. Вы можете аннулировать кэширование данных элементов с заданным тегом(тегами) по вызову.
invalidate();
Кэширование запросов
$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();});
$duration=60;// кэширование результата на 60 секунд$dependency=...;// параметры зависимости
$result=$db->cache(function($db){
// ... выполнять SQL запросы здесь ...
return$result;
},$duration,$dependency);
$result=$db->cache(function($db){
// SQL запросы, которые используют кэширование
$db->noCache(function($db){
// SQL запросы, которые не используют кэширование
});
// ...
return$result;});
// использовать кэширование запросов и установить срок действия кэша на 60 секунд$customer=$db->createCommand('SELECT * FROM customer WHERE id=1')->cache(60)->queryOne();
$result=$db->cache(function($db){
// Используется кэширование SQL запросов
// не использовать кэширование запросов для этой команды$customer=$db->createCommand('SELECT * FROM customer WHERE id=1')->noCache()->queryOne();
// ...
return$result;});
Локализация - i18N/intl
apt=get install php5-intl
Перевод (локализация проекта)
PHPUnit
добавить в конфигуратор композера composer.json
{
"require-dev": {
"phpunit/phpunit": "3.7.*"
}
}
Статьи
Описание