В этой части мы поговорим о том, какие средства предоставляет Yii для создания виджетов. Если верить википедии, виджет (widget) – это «контент модуль, который встраивается в веб-страницу или браузер» (вообще, это не совсем точно, в википедии есть несколько определений).
Правда здесь может возникнуть небольшая путаница в терминологии. Дело в том, что некоторые CMS (WordPress, например) используют термин виджет для обозначения особых плагинов, которые предназначены для отображения блоков с информацией в сайдбаре. Но сейчас нас интересует Yii PHP framework, поэтому мы будем считать виджетами объекты, которые наследуют класс CWidget.
Обычно виджеты используют для отображения какого-нибудь контента, который не зависит от основного содержимого страницы. Например, это может быть форма входа, перечень жанров игр, блок со случайными скриншотами, ссылки на страницы архива и т.п.
Для нас важно, что CWidget имеет особенность. Он является потомком класса CComponent, и, следовательно, является компонентом.
Рассмотрим, как создаются компоненты в фреймворке Yii.
Шаг 1. В папке protected/components создаём файл с классом компонента. Этот класс выполняет инициализацию компонента и подготовку данных (например, чтение из БД).
Шаг 2. В папке protected/components/views создаём файл с представлением компонента. По-сути это шаблон, который используется для отображения содержимого компонента.
Шаг 3. Добавляем компонент в макет (layout) нужных страниц сайта. Макеты находятся в папке protected/views/layouts.
Теперь рассмотрим конкретный пример. Создадим виджет, содержащий ссылки на страницы жанров игр.
Назовём класс TypesMenu.
Создаём файл protected/components/TypesMenu.php.
class TypesMenu extends CWidget {
public function run() {
$types = Types::model()->findAll();
$this->render('typesMenu',array('types'=>$types));
}
}
Как видите, класс содержит один метод (run), который будет вызван фреймворком при создании виджета.
В этом методе мы получаем список всех жанров игр (строка 3) и результат передаём представлению (строка 5).
Создаём представление (файл protected/components/views/typesMenu.php).
<h2>Жанры</h2>
<ul>
<?php
foreach ($types as $type) {
//каждый пункт списка - ссылка на страницу с играми данного жанра
//жанр указывается с помощью параметра в get запросе - type_id
echo '<li>'.CHtml::link($type->t_name, array('games/list', 'type_id'=>$type->t_id)).'</li>';
}
?>
</ul>
Обратите внимание, у нас доступна переменная $types. (её название мы указали при загрузке представления, метод render).
Сами ссылки создаём с помощью метода CHtml::link. В первом параметре указываем текст ссылки, а во втором – массив с параметрами. В данном случае будут созданы url вида
http://yiigame.domen/index.php?r=games/list&type_id=1
где type_id – id соответствующего жанра.
Вставляем виджет в макет страницы. Для этого в файл protected/views/layouts/main.php добавляем следующий код.
<div class="menu">
<?php $this->widget('application.components.TypesMenu'); ?>
</div><!-- menu -->
Посмотрите, как указано имя виджета. Перед названием файла виджета (без расширения) мы добавляем application.components, проще говоря, указываем путь к виджету.
Всё, мы получили работающий виджет, правда, самый примитивный. Давайте рассмотрим вариант немного посложнее.
На некоторых страницах сайта нам нужно выводить список с самыми популярными записями.
Популярность игры мы можем определить, используя поле g_rate (таблица ygs_games), т.е. нам нужно будет при поиске игр в базе просто отсортировать их по этому полю.
Показывать виджет нам нужно на страницах с общим перечнем игр и страницах отдельных жанров. И те, и другие страницы формирует метод actionList (класс GamesController). Но на страницах жанров мы будем показывать топ игр, которые относятся к данному жанру, а не все подряд, т.е. в наш запрос нужно будет добавить дополнительное условие.
Если задача ясна, приступаем.
Создаём файл виджета protected/components/TopGames.php.
class TopGames extends CWidget {
public $title = 'Популярные игры';
public $showOn = array();
public $count = 10;
public function run() {
//определяем название контроллера и метода (action)
$controller = Yii::app()->controller->id;
$action = Yii::app()->controller->action->id;
//проверяем нужно ли показывать виджет
if (!in_array($controller.'/'.$action, $this->showOn)) {
return;
}
//проверяем, нужно ли выводить игры только данного жанра
if (isset($_GET['type_id'])) {
$id = $_GET['type_id'];
$params = array('limit'=>$this->count,'order'=>'g_rate DESC'
,'condition'=>'t_id=:id'
,'params'=>array(':id'=>$id));
//ищем игры
$games = Games::model()->getTopGames($params)->published()->with('ygs_types')->findAll();
} else {
$params = array('limit'=>$this->count,'order'=>'g_rate DESC');
//ищем игры
$games = Games::model()->getTopGames($params)->published()->findAll();
}
//заполняем массивы с жанрами игр для каждой найденной игры
//для этого раскодируем поле g_type
foreach ($games as $key=>$game) {
$games[$key]->g_types = Yii::app()->controller->_decodeTypes($game->g_type);
}
//показываем виджет
$this->render('topGames'
, array('title'=>$this->title, 'games'=>$games));
}
}
Прежде всего, обратите внимание на три свойства класса $title, $showOn и $count. Фреймворк позволяет указывать значения для всех отрытых (public) свойств виджета при его создании, т.е. в макете (layout) мы можем задать значения для этих свойств. Таким образом, появляется возможность изменять вид виджета, не трогая его код.
В данном случае в свойстве $title мы указываем заголовок виджета, в свойстве $showOn – массив с перечнем страниц, на которых он должен отображаться, а в свойстве $count – количество игр.
Рассмотрим метод run.
Прежде всего, определяем название контроллера и метода (action) (строки 9, 10). И проверяем, нужно ли показывать виджет. Страницы, на которых нужно отображать виджет указываются в формате «название_контроллера/название_метода». Если массив $showOn не содержит подходящего элемента, мы завершаем работу виджета.
В противном случае, мы:
1) Проверяем, является ли эта страница, страницей жанра (получен параметр $_GET['type_id'] или нет). Если получен, формируем запрос, при этом в его параметрах мы указываем, что нам нужны игры только текущего жанра.
2) Если мы находимся на странице с общим перечнем игр, то просто получаем игры, отсортированные по полю g_rate.
Обратите внимание на метод getTopGames($params). Он объявлен в модели (Games) и нужен только для того, чтобы немного сократить запись запроса.
public function getTopGames($params) {
$this->getDbCriteria()->mergeWith($params);
return $this;
}
Примечание. Использовать его не обязательно. Можно было просто создать объект CDbCriteria, как мы и делали в предыдущих частях, но я хотел попробовать разные варианты работы.
3) Расшифровываем поле с перечнем жанров (эту операцию мы рассматривали в предыдущих частях).
4) Показываем представление при этом передаём ему заголовок виджета и данные игр.
Само представление выглядит так (файл protected/components/view/topGames.php).
<h1><?php echo $title; ?></h1>
<?php
$i = 0;
foreach($games as $n=>$model) {
//шаблон для вывода игры находится в views/games/_short_desc.php
$this->controller->renderPartial('_short_desc', array('game'=>$model));
if ($i % 2 !== 0) {
echo '<div class="clear"></div>';
}
$i++;
}
?>
Как видите, для вывода игры мы использовали представление, которое относится к контроллеру Games (views/games/_short_desc.php).
Последний шаг – подключение шаблона в макете (файл protected/views/layouts/main.php)
<div id="top_games" class="grid_9">
<?php $this->widget('application.components.TopGames'
, array('title'=>'Популярные игры'
,'showOn'=>array('games/list','types/show')
,'count'=>4)); ?>
</div><!-- top_games -->
Тут стоит отметить передачу параметров виджету. Они должны быть записаны в виде массива. При этом, ключ элемента должен совпадать с именем соответствующего свойства класса.
На этом мы остановимся. Думаю, общее представление о виджетах у вас появилось. Но в этой статье рассмотрены далеко не все их возможности, поэтому очень советую почитать соответствующий раздел справки.
Продолжение следует 😉
Все разделы цикла.
- Yii PHP framework: создаём игровой сайт. Часть 1. Постановка задачи.
- Yii PHP framework: создаём игровой сайт. Часть 2. База данных и установка фреймворка.
- Yii PHP framework: создаём игровой сайт. Часть 3. Аутентификация.
- Yii PHP framework: создаём игровой сайт. Часть 4. Работа с жанрами игр.
- Yii PHP framework: создаём игровой сайт. Часть 5. Импорт игр.
- Yii PHP framework: создаём игровой сайт. Часть 6. Формируем страницы игр и жанров.
- Yii PHP framework: создаём игровой сайт. Часть 7. Работа с JavaScript и страницы игр.
- Yii PHP framework: создаём игровой сайт. Часть 8. Создаём виджеты.
- Yii PHP framework: создаём игровой сайт. Часть 9. Поиск ошибок.
- Yii PHP framework: создаём игровой сайт. Часть 10. Панель управления.
- Yii PHP framework: создаём игровой сайт. Часть 11. Человекопонятные URL.
- Архив с исходниками


