Показать страницуИстория страницыСсылки сюдаCopy this pageExport to MarkdownODT преобразованиеНаверх Вы загрузили старую версию документа! Сохранив её, вы создадите новую текущую версию с этим содержимым. Медиафайлы{{tag>yii yii1 frameworks}} ====== Сборник советов для Yii1 ====== ===== Своё сообщение при выводе ошибки – параметр message: ===== <code php> public function rules() { return array( array('username, password', 'required', 'message' => 'Будьте любезны заполнить поле "{attribute}"'), ); } </code> ===== Капча не обновляет код при ошибочном вводе ===== <code php> public function actions() { return array( 'captcha' => array( 'class' => 'CCaptchaAction', 'backColor' => 0xFFFFFF, 'testLimit'=> 1, // ), ); } </code> По-умолчанию, 'testLimit' установлен в значении 3. Поэтому код обновляется только после третьего неверного ввода. ===== Если при ajax запросе вам необходимо обновить часть страницы и загрузить все скрипты ===== <code php> $this->renderPartial('index', array( 'criteria' => $criteria, ), false, true); </code> Именно, последний параметр, установленный в true, сообщает что нужно отдавать страницу со всеми скриптами. ===== Полностью на AJAX ===== * [[http://tpoxa.com/2011/04/19/fully-ajax-website-with-yii/|bbq]] ===== Меню на основе Cmenu, но вместо текста (label) необходимо изображение ===== ==== 1 Способ ==== <code php> $adminMenuItems = array( array('label' => '<img src="'.Yii::app()->request->baseUrl.'/images/adminmenu/manage_ads.png" />', 'url'=>array('/apartments/backend/main/admin'), 'linkOptions'=>array('title' => Yii::t('module_apartments', 'Manage apartments')) ) ); $this->widget('zii.widgets.CMenu', array( 'items'=>$adminMenuItems, 'encodeLabel' => false, )); </code> ==== 2 Способ ==== <code php> $adminMenuItems = array( array('label'=>'', 'url'=>array('/quicksearch/main/index'), 'template' => '<img src="'.Yii::app()->request->baseUrl.'/images/adminmenu/manage_ads.png" />' ) ); $this->widget('zii.widgets.CMenu', array( 'items'=>$adminMenuItems, )); </code> ===== Передача параметров в JS скрипт ===== <code php> $globalConfig = CJavaScript::encode(Yii::app()->params->toArray()); Yii::app()->clientScript->registerScript('globalConfig', "var globalConfig = ".$globalConfig.";", CClientScript::POS_HEAD); </code> <code php> Yii::app()->clientScript->registerScript('testConfig', ' if(globalConfig){ alert(globalConfig["languages"]); } ', CClientScript::POS_END); </code> ===== Автоматическое обновление поля date в модели ===== <code php> public function behaviors(){ return array( 'AutoTimestampBehavior' => array( 'class' => 'zii.behaviors.CTimestampBehavior', 'createAttribute' => 'date_updated', 'updateAttribute' => 'date_updated', ), ); } </code> ===== Вставка фотографии из модели в GridView ===== <code php> $this->widget('zii.widgets.grid.CGridView', array( 'dataProvider'=>$model->search(), 'filter'=>$model, 'columns'=>array( array ( 'name' => 'img', 'type' => 'image', 'value'=> 'url/to/image' /* например: 'Yii::app()->request->baseUrl."/".$data->sliderThumbPath."/".$data->img' - обязательно в ковычках */ 'filter' => false, ), ... )); </code> ===== Задание имени сценария перед валидацией и его правила валидации ===== <code php> $model->scenario = 'upload'; // Обязадельно должен объявляться до присвоения атрибутов $model->attributes = $_POST['form_name']; if($model->validate()) { //... } </code> в правилах валидации указываем сценарий **'on' => 'upload'**: <code php> public function rules() { return array( array( 'upload', 'file', 'types' => "{$this->supportExt}", 'maxSize' => $this->fileMaxSize, 'tooLarge' => Yii::t('module_slider', 'The file was larger than {size}MB. Please upload a smaller file.', array('{size}' => $this->fileMaxSize)), 'on' => 'upload', ), ); } </code> ===== расширение для ресайза ===== * http://www.yiiframework.com/extension/image/ <code php> if(isset($_POST["{$this->modelName}"])){ $model->attributes = $_POST; $model->scenario = 'upload'; if($model->validate()) { $model->upload = CUploadedFile::getInstance($model,'upload'); $model->img = md5(uniqid()).'.'.$model->upload->extensionName; if($model->save()){ $model->upload->saveAs($model->uploadPath.'/'.$model->img); Yii::import('application.extensions.image.Image'); $image = new Image($model->uploadPath.'/'.$model->img); $image->resize($model->maxWidth, $model->maxHeight); $image->save(); Yii::app()->user->setFlash( 'mesSlider', tt('Image succesfullty added to slider.') ); $model->unsetAttributes(); } } } </code> ===== Информирование пользователя ===== * [[yii:setFlash|Подробнее]] <code php> Yii::app()->user->setFlash( 'message', 'Image succesfullty added to slider.' ); </code> ===== Вставка javascript и css на страницы ===== <code php> // CSS Yii::app()->clientScript->registerCssFile(Yii::app()->assetManager->publish(Yii::app()->basePath . '/css/').'css1.css', 'screen'); // JS // JQuery Yii::app()->clientScript->registerCoreScript('jquery'); // Custom script Yii::app()->clientScript->registerScriptFile(Yii::app()->assetManager->publish(Yii::app()->basePath . '/js/'). '/jcarousel/lib/jquery.jcarousel.min.js', CClientScript::POS_END); </code> Втавка в темплайт <code php> Yii::app()->clientScript->registerScript('loading', ' $("#loading").bind("ajaxSend", function(){ $(this).show(); }).bind("ajaxComplete", function(){ $(this).hide(); }); ', CClientScript::POS_READY); </code> * POS_READY значит, что скрипт выполнится в $(document).ready(function() { }) * POS_LOAD - скрипт выполнится в window.onload * POS_END - вставка перед закрывающим тэгом body * POS_BEGIN - вставка перед открывающим тэгом body * POS_HEAD - вставка перед тэгом title Статьи: * [[http://www.yiiframework.com/forum/index.php/topic/11438-%D0%BF%D0%BE%D0%B4%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B5-css-%D0%B2-%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D0%B5%D1%80%D0%B5/|Подключение css в контролере]] * [[http://habrahabr.ru/post/150885/|Автоматическое подключение css и js файлов в Yii]] ===== Метод Action контроллера по-умолчанию ===== <code php> class MainController extends CController { public $defaultAction='test'; //.... public function actionTest() { } } </code> ===== Редирект ===== <code php> $this->redirect(Yii::app()->homeUrl); </code> ===== Доступ к объектам контролера ===== <code php> // Controller $controllerId = Yii::app()->controller->id; // Получение ID контролера $actionId = $this->getAction()->getId(); $actionId = Yii::app()->controller->action->id; // Обращение к модулю из чужого модуля или контролера $module = Yii::app()->getModule('userGroups'); $module->mailMessages(); // Вызов чужого контроллера $p = Yii::app()->createController('userGroups/user/login'); $act = $p[0]->createAction('login'); $act->run(); // Вызов чужого контроллера // Если необходимо наличие _action в контролере $controller = Yii::app()->createController('social/profile/friendsFeed')[0]; $action = $controller->createAction('friendsFeed'); $controller->runActionWithFilters($action, $controller->filters()); // Вызов чужого контроллера // Если необходимо наличие _owner Yii::app()->runController('social/profile/friendsFeed'); </code> ===== Вывод абсолютного пути ===== <code php> $url = Yii::app()->createAbsoluteUrl('user/activation',array('activationKey'=>$activationKey)); </code> ===== Своя функция - валидатор на примере капчи ===== <code php> public function rules() { return array( ... array('verifyCode', 'required', 'on' => 'registration'), array('verifyCode', 'captchaValidate', 'on' => 'registration'), ) } public function captchaValidate() { $code = Yii::app()->controller->createAction('captcha')->getVerifyCode(); if ($code != $this->verifyCode) $this->addError('verifyCode', 'Неверный код с капчи'); } </code> ===== Расширяем своё приложение на примере многоразового использования одного расширения для однотипных действий, на примере удаления записи ===== Объявляем расширение контролера в ext.test.testActionDelele <code php> <?php class testActionDelele extends CAction { public $modelName; public $redirectAfter = array('index'); public function run($id = null) { if (id) { CActiveRecord::model($this->modelName)->deleteByPk($id); } if(Yii::app()->getRequest()->getIsAjaxRequest()) { Yii::app()->end(200, true); } else { $this->getController()->redirect($this->redirectAfter); } } } </code> Создаем общий метод <code php> <?php class testController extends CController { public function actions() { return array( 'deleteUser' => array( 'class' => 'ext.test.testActionDelele', 'modelName' => 'User', 'redirectAfter' => array('indexUsers'), ), 'deletePost' => array( 'class' => 'ext.test.testActionDelele', 'modelName' => 'Post', 'redirectAfter' => array('indexPosts'), ), ); } } </code> ===== Jquery не работает после renderPartial. ===== <code php> if($isFancyBox){ Yii::app()->clientscript->scriptMap['jquery.js'] = false; Yii::app()->clientscript->scriptMap['jquery.min.js'] = false; Yii::app()->clientscript->scriptMap['jquery-ui.min.js'] = false; $this->renderPartial('form', array( 'model' => $model, ), false, true); } else{ $this->render('form', array( 'model' => $model, )); } </code> ===== Фильтры. На примере сжатия страницы ===== **ext.compress.compressPage** <code php> <?php class compressPage extends CFilter { protected function preFilter($filterChain) { ob_start(); return parent::preFilter($filterChain); } protected function postFilter($filterChain) { $html = ob_get_clean(); echo preg_replace("~>(\s+|\t+|\n+)<~", "><", $html); parent::postFilter($filterChain); } } </code> В контолере <code php> public function filters() { return array( array( 'ext.compress.compressPage + view, index' ), ); } </code> ===== Зависимый select от другого select'а ===== * [[yii:зависимые_select-списки|Зависимые select-списки в Yii]] ===== Сгруппированный раскрывающийся список ===== <code php> echo CHtml::dropDownList('Cars', 'car_id', array( 'Toyota'=>array( 1=>'Avensis', 2=>'Camry', ), 'Volvo'=>array( 3=>'S60', 4=>'XC70', ), )); </code> <code php> $records = array( array('id' => 1, 'name' => 'Yii', 'group' => 'Фреймворк'), array('id' => 2, 'name' => 'Drupal', 'group' => 'Фреймворк'), array('id' => 3, 'name' => 'Joomla', 'group' => 'Фреймворк'), array('id' => 4, 'name' => 'Сodeigniter', 'group' => 'Фреймворк'), array('id' => 5, 'name' => 'Mercurial', 'group' => 'Система контроля версий'), array('id' => 6, 'name' => 'Git', 'group' => 'Система контроля версий'), array('id' => 7, 'name' => 'SVN', 'group' => 'Система контроля версий'), ); $dropDownList = CHtml::listData($records, 'id', 'name', 'group'); echo CHtml::dropDownList('dropDownList', '', $dropDownList); </code> ===== Label, помеченный как обязательный для заполнения ===== <code php> echo CHtml::activeLabel($model, 'name', array('required' => true)); </code> ===== CGridView. Добавляем раскрывающийся список для сортировки/поиска. ===== * **'filter' => array(0 => 'Все', 1 => 'Продажа', 2 => 'Аренда'),** <code php> $this->widget('zii.widgets.grid.CGridView', array( 'id'=>'apartments-grid', 'dataProvider'=>$model->search(), 'filter'=>$model, 'columns'=>array( ... array( 'name' => 'type', 'type' => 'raw', 'value' => 'Apartment::getNameByType($data->type)', 'filter' => array(0 => 'Все', 1 => 'Продажа', 2 => 'Аренда'), ), ... ) )); </code> Добавить в модели метода search <code php> if ($this->type) $criteria->compare('type', $this->type); </code> ===== Форма с шагами ===== * [[:yii_multi_page_form_wizard|Форма из нескольких шагов]] ===== Одна форма с данными из двух и более моделей ===== <code php> public function actionCreate() { $category = new Category; $subCategory = new SubCategory; if(isset($_POST['Category'], $_POST['SubCategory'])) { // собираем входные данные $model->attributes = $_POST['Category']; $sub->attributes = $_POST['SubCategory']; // валидация $valid = $model->validate(); $valid = $sub->validate() && $valid; if($valid) { // сохраняем данные без валидации (параметр false), так как уже валидация была выше. if($model->save(false)) { $sub->category_id = $model->id; $sub->save(false); $this->redirect(array('view','id'=>$model->id)); } } } $this->render('create', array( 'model'=>$model, 'sub'=>$sub, )); } ?> </code> Представление create модели Category имеет вид: <code php> <?php $this->breadcrumbs=array( 'Управление категориями' => array('admin'), 'Добавить категорию', ); $this->renderPartial('_form',array( 'model'=>$model, 'sub' => $sub, )); ?> </code> И представление _form: <code php> <div class="form"> <?php $form=$this->beginWidget('CActiveForm', array( 'id'=>'category-form', 'enableAjaxValidation'=>false, )); ?> <p class="note">Поля, отмеченные <span class="required">*</span> являются обязательными.</p> <?php echo $form->errorSummary(array($model, $sub)); ?> <div class="row"> <?php echo $form->labelEx($model, 'model_field1'); ?> <?php echo $form->textField($model, 'model_field1'); ?> <?php echo $form->error($model, 'model_field1'); ?> </div> <div class="row"> <?php echo $form->labelEx($sub, 'sub_field1'); ?> <?php echo $form->textField($sub, 'sub_field1'); ?> <?php echo $form->error($sub, 'sub_field1'); ?> </div> <div class="row buttons"> <?php echo CHtml::submitButton($model->isNewRecord ? 'Добавить' : 'Сохранить'); ?> </div> <?php $this->endWidget(); ?> </div> </code> ===== Кэширование запросов ===== * [[yii:cache|Подробнее]] **config/main.php** <code php> 'cache'=>array( 'class'=>'system.caching.CFileCache', ), </code> Выставляем время кеша в 1000 секунд для DAO: <code php> $sql = 'SELECT field1, field2 FROM {{apartment_reference}}'; $dependency = new CDbCacheDependency('SELECT MAX(date_updated) FROM apartment_reference'); $apReference = Yii::app()->db->cache(1000, $dependency)->createCommand($sql)->queryAll(); </code> То же самое для AR: <code php> $dependency = new CDbCacheDependency('SELECT MAX(date_updated) FROM apartment_reference'); $apReference = apReference::model()->cache(1000, $dependency)->findAll(); </code> Для очистки всего кэша вызываем метод flush(): <code php> Yii::app()->cache->flush(); </code> ===== Отладка SQL запросов ===== **config/main.php** <code php> 'db'=>array( 'charset' => 'utf8', 'enableParamLogging' => 0, 'enableProfiling' => true, 'schemaCachingDuration' => 0, ), 'log'=>array( 'class'=>'CLogRouter', 'routes'=>array( array( 'class'=>'CWebLogRoute', 'levels'=>'trace', 'showInFireBug'=>true, ), ), ), </code> Запрос, созданный при помощи построителя запросов, можно посмотреть при помощи CDbCommand::getText(). <code php> var_dump(Yii::app()->db->createCommand($sql)->text); </code> ===== Построитель запросов ===== * [[yii:dao|Подробнее]] **Удаление записи** <code php> Yii::app()->db->createCommand()->delete('{{apartment_reference}}', 'apartment_id=:id', array(':id'=>$this->id)); </code> **Вставка записи** <code php> Yii::app()->db->createCommand()->insert('{{apartment_reference}}', array( 'field1'=>'valueField1', 'field2'=>'valueField2', )); </code> **Изменение значения с строке** <code php> Yii::app()->db->createCommand()->update('{{apartment_reference}}', array( 'field1'=>'valueField1', ), 'id=:id', array(':id'=>1)); </code> **Выборка данных** <code php> $apReference = Yii::app()->db->createCommand() ->select('field1, field2') ->from('{{apartment_reference}}') ->where('id=:id', array(':id'=>1)) ->queryRow(); </code> ===== Пример использования CArrayDataProvider ===== Контролер: <code php> public function actionViewGrid() { $items = array( array('id' => 1, 'title'=>'Title1', 'description' => 'Description1'), array('id' => 2, 'title'=>'Title2', 'description' => 'Description2'), array('id' => 3, 'title'=>'Title3', 'description' => 'Description3'), array('id' => 4, 'title'=>'Title4', 'description' => 'Description4') ); $itemsProvider = new CArrayDataProvider($items, array( 'pagination' => array( 'pageSize' => 2, ), )); $this->render('viewgrid', array('itemsProvider' => $itemsProvider)); } </code> Представление: <code php> $this->widget('zii.widgets.grid.CGridView', array( 'id' => 'itemGrid', 'dataProvider' => $itemsProvider, 'enablePagination' => true, 'columns' => array( array( 'name' => 'ID', 'value' => '$data["id"]', 'sortable' => true, 'filter' => false, ), array( 'name' => 'Название', 'value' => '$data["title"]' ), array( 'name' => 'Описание', 'value' => '$data["description"]' ), ) )); </code> ===== Для получения IP адреса пользователя используйте ===== <code php> echo Yii::app()->request->userHostAddress; </code> ===== CDbExpression ===== * [[yii:cdbexpression|Подробнее]] ===== datePicker в CGridView ===== * [[yii:widgets:cgridview|CGridView]] ===== Мета тэги ===== <code php> Yii::app()->clientScript->registerMetaTag('описание сайта', 'description'); Yii::app()->clientScript->registerMetaTag('ключевые слова сайта', 'keywords'); </code> ===== Действия до валидации и после ===== **onBeforeValidate** <code php> public function onBeforeValidate($event) { $scenarioArray = array( 1 => 'scanario1', 2 => 'scanario2', 3 => 'scanario3', 4 => 'scanario4', 5 => 'scanario5', ); $this->scenario = $scenarioArray[$this->fieldFromDB1]; if (!$this->field2 || !$this->field3) $this->addError('phone', 'Заполните поля field2 и field3'); else $this->fieldFromDB2 = $this->field2.$this->field3; } public function onAfterValidate($event) { // здесь некий код } public function beforeValidate(){ } public function AfterValidate(){ } </code> * [[http://yiiframework.ru/doc/cookbook/ru/core.events|Отличия событий beforeValidate от onbeforeValidate]] ===== Добавляем индикатор загрузки при ajax запросах ===== Добавим дивчик на страницу: <code php> <div id="loading" style="display:none;">Загрузка ...</div> </code> CSS: <code css> #loading{ position: fixed; top: 40px; leftleft: 0; z-index: 5000; background-color: #3C69AC; font-size: 100%; color: #FFFFFF; padding: 5px; } </code> Отображение и скрытие дивчика: <code php> Yii::app()->clientScript->registerScript('loading', ' $("#loading").bind("ajaxSend", function(){ $(this).show(); }).bind("ajaxComplete", function(){ $(this).hide(); }); ', CClientScript::POS_READY); </code> Установка путей загрузки картинки <code php> Yii::getPathOfAlias('webroot.uploads'); </code> ===== Проверка запроса на наличие Ajax ===== <code php> if( Yii::app()->request->isAjaxRequest) { // do some thing…. } </code> ===== Обновление грида через ajax ===== * [[yii:widgets:cgridview|CGridView]] ===== Обновление представления через ajax ===== ===== Постраничная разбивка ===== * [[yii:pagination|Примеры постраничной навигации]] ===== Сессии session ===== <code php> Yii::app()->session->add(‘product’, $productId); Yii::app()->session->get(‘product’); Yii::app()->session->remove(‘product’); unset(Yii::app()->session[$variable][$key]); </code> ===== Cookie ===== <code php> $cookie=Yii::app()->request->cookies[$name]; $value=$cookie->value; $cookie=new CHttpCookie($name,$value); Yii::app()->request->cookies[$name]=$cookie; </code> СохранитьПросмотрРазличияОтменить Сводка изменений Примечание: редактируя эту страницу, вы соглашаетесь на использование своего вклада на условиях следующей лицензии: CC0 1.0 Universal