Документация по 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',],]];
PHPUnit
добавить в конфигуратор композера composer.json
{ "require-dev": { "phpunit/phpunit": "3.7.*" } }
- php composer.phar update
- php vendor/bin/phpunit vendor/yiisoft/yii2/yii/test/
URL Management
$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);
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
Blocks
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]);?>
Добавление csrfToken в Ajax запрос (Yii2)
через ajaxSetup
$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) { });
Image
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
- $schema = true - Абсолютный адрес
- $schema = 'https' - Указание на испоользование шифрованного протокола
Синоним для 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
urlManager
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/
Custom
<?phpreturn[// ...'components'=>['urlManager'=>['enablePrettyUrl'=>true,'showScriptName'=>false,'enableStrictParsing'=>true,'suffix'=>'.html','rules'=>['<action:(login|logout|about)>'=>'site/<action>', // ... ['class'=>'app\components\CarUrlRule','connectionID'=>'db',...],],],],];
Controller
Как программно вызвать контроллер?
$className='backend\controllers\SiteController';$controller= Yii::createObject($className,[$id,$this]);
yii\helpers\Html (old)
// ['label' => 'Добавление', 'url' => ['/admin/user/create']] Html::a("Log in here",["user/reset","hash"=>$hash,"sid"=>$sid]); Html::url(["user/reset","hash"=>$hash,"sid"=>$sid]);
Подробноhttps://github.com/yiisoft/yii2/blob/master/docs/guide/url.md
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();?>
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;}],],],
Model
modules/user
$user= Yii::$app->getModule("user")->model("User",["scenario"=>"register"]);$profile= Yii::$app->getModule("user")->model("Profile"); if($user->load($_POST)){if($user->save()){$profile->user_id=$user->id;$profile->save(false);}}
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',// ...];} }
Пример использования в модели
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;}
- Список базовых валидаторов:https://github.com/yiisoft/yii2/blob/master/docs/guide/validation.md
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-
Connection/Command/QueryBuilder
Connection
$connection= \Yii::$app->db;
Подробно
Command
- queryOne()
- queryAll()
- query()
- queryScalar()
- queryColumn()
Подробноhttps://github.com/yiisoft/yii2/blob/master/framework/db/Command.php
$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();}
Active Record
class Post extends ActiveRecord {publicfunction getCreator(){return$this->hasOne('User',array('id'=>'user_id'));}publicfunction getComments(){return$this->hasMany('Comment',array('post_id'=>'id'));}publicfunction getTrustComments($isTrust=true){return$this->hasMany('Comment',array('post_id'=>'id'))->where('status = :status',array(':status'=>$isTrust ? self::TRUST:self::UNTRUST,))->orderBy('id');}}
// 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(array('id'=>10,'status'=> Post::READ))->one(); // or easier: "where" condition can be transmitted directly to the factory method$post= Post::find(array('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(array('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();
Как получить SQL и Параметры из ActiveQuery
$query= Post::find()->whwre(array('id'=>10,'status'=> Post::READ))->createCommand(); // SQLecho$query->sql // Params:print_r($query->params)
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}
Ключи в эллементах коллекции AR
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 }}
- Activedataprovider - Pager / Генерация страниц
- SqlDataProvider - Pager / Генерация страниц
Подробно:
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);
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',),),
Form
Assets
Console
IsConsole
if(Yii::$app->request->isConsoleRequest){//}
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),),),);}
Статьи
Локализация - i18N/intl
apt=get install php5-intl
Session
Yii::$app->session->get('key'); Yii::$app->session->set('key','value');
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\ChainedDependency: зависимость меняется, если любая зависимость в цепочке изменяется;
- yii\caching\DbDependency: зависимость меняется, если результат некоторого определенного SQL запроса изменён;
- yii\caching\ExpressionDependency: зависимость меняется, если результат определенного PHP выражения изменён;
- yii\caching\FileDependency: зависимость меняется, если изменилось время последней модификации файла;
- 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;});