Yii PHP framework: создаём игровой сайт. Часть 8. Создаём виджеты.

30 января, 2010
yii_game_site_widgets

В этой части мы поговорим о том, какие средства предоставляет 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.

  1. class TypesMenu extends CWidget {
  2.     public function run() {
  3.         $types = Types::model()->findAll();
  4.        
  5.         $this->render('typesMenu',array('types'=>$types));
  6.     }
  7. }

Как видите, класс содержит один метод (run), который будет вызван фреймворком при создании виджета.

В этом методе мы получаем список всех жанров игр (строка 3) и результат передаём представлению (строка 5).

Создаём представление (файл protected/components/views/typesMenu.php).

  1. <h2>Жанры</h2>
  2. <ul>
  3. <?php
  4. foreach ($types as $type) {
  5.     //каждый пункт списка – ссылка на страницу с играми данного жанра
  6.     //жанр указывается с помощью параметра в get запросе – type_id
  7.     echo '<li>'.CHtml::link($type->t_name, array('games/list', 'type_id'=>$type->t_id)).'</li>';
  8. }
  9. ?>
  10. </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 добавляем следующий код.

  1. <div class="menu">
  2. <?php $this->widget('application.components.TypesMenu'); ?>
  3. </div><!– menu –>

Посмотрите, как указано имя виджета. Перед названием файла виджета (без расширения) мы добавляем application.components, проще говоря, указываем путь к виджету.

Всё, мы получили работающий виджет, правда, самый примитивный. Давайте рассмотрим вариант немного посложнее.

На некоторых страницах сайта нам нужно выводить список с самыми популярными записями.

Популярность игры мы можем определить, используя поле g_rate (таблица ygs_games), т.е. нам нужно будет при поиске игр в базе просто отсортировать их по этому полю.

Показывать виджет нам нужно на страницах с общим перечнем игр и страницах отдельных жанров. И те, и другие страницы формирует метод actionList (класс GamesController). Но на страницах жанров мы будем показывать топ игр, которые относятся к данному жанру, а не все подряд, т.е. в наш запрос нужно будет добавить дополнительное условие.

Если задача ясна, приступаем.

Создаём файл виджета protected/components/TopGames.php.

  1. class TopGames extends CWidget {
  2.    
  3.     public $title = 'Популярные игры';
  4.     public $showOn = array();
  5.     public $count = 10;
  6.    
  7.     public function run() {
  8.         //определяем название контроллера и метода (action)
  9.         $controller = Yii::app()->controller->id;
  10.         $action = Yii::app()->controller->action->id;
  11.         //проверяем нужно ли показывать виджет
  12.         if (!in_array($controller.'/'.$action, $this->showOn)) {
  13.             return;
  14.         }
  15.         //проверяем, нужно ли выводить игры только данного жанра
  16.         if (isset($_GET['type_id'])) {
  17.             $id = $_GET['type_id'];
  18.             $params = array('limit'=>$this->count,'order'=>'g_rate DESC'
  19.                 ,'condition'=>'t_id=:id'
  20.                 ,'params'=>array(':id'=>$id));
  21.             //ищем игры
  22.             $games = Games::model()->getTopGames($params)->published()->with('ygs_types')->findAll();
  23.         } else {
  24.             $params = array('limit'=>$this->count,'order'=>'g_rate DESC');
  25.             //ищем игры
  26.             $games = Games::model()->getTopGames($params)->published()->findAll();
  27.         }
  28.        
  29.         //заполняем массивы с жанрами игр для каждой найденной игры
  30.         //для этого раскодируем поле g_type
  31.         foreach ($games as $key=>$game) {
  32.             $games[$key]->g_types = Yii::app()->controller->_decodeTypes($game->g_type);
  33.         }
  34.         //показываем виджет
  35.         $this->render('topGames'
  36.             , array('title'=>$this->title, 'games'=>$games));
  37.     }
  38. }

Прежде всего, обратите внимание на три свойства класса $title, $showOn и $count. Фреймворк позволяет указывать значения для всех отрытых (public) свойств виджета при его создании, т.е. в макете (layout) мы можем задать значения для этих свойств. Таким образом, появляется возможность изменять вид виджета, не трогая его код.

В данном случае в свойстве $title мы указываем заголовок виджета, в свойстве $showOn – массив с перечнем страниц, на которых он должен отображаться, а в свойстве $count – количество игр.

Рассмотрим метод run.

Прежде всего, определяем название контроллера и метода (action) (строки 9, 10). И проверяем, нужно ли показывать виджет. Страницы, на которых нужно отображать виджет указываются в формате «название_контроллера/название_метода». Если массив $showOn не содержит подходящего элемента, мы завершаем работу виджета.

В противном случае, мы:

1) Проверяем, является ли эта страница, страницей жанра (получен параметр $_GET['type_id'] или нет). Если получен, формируем запрос, при этом в его параметрах мы указываем, что нам нужны игры только текущего жанра.

2) Если мы находимся на странице с общим перечнем игр, то просто получаем игры, отсортированные по полю g_rate.

Обратите внимание на метод getTopGames($params). Он объявлен в модели (Games) и нужен только для того, чтобы немного сократить запись запроса.

  1. public function getTopGames($params) {
  2.     $this->getDbCriteria()->mergeWith($params);
  3.     return $this;
  4. }

Примечание. Использовать его не обязательно. Можно было просто создать объект CDbCriteria, как мы и делали в предыдущих частях, но я хотел попробовать разные варианты работы.

3) Расшифровываем поле с перечнем жанров (эту операцию мы рассматривали в предыдущих частях).

4) Показываем представление при этом передаём ему заголовок виджета и данные игр.

Само представление выглядит так (файл protected/components/view/topGames.php).

  1. <h1><?php echo $title; ?></h1>
  2.  
  3. <?php
  4. $i = 0;
  5. foreach($games as $n=>$model) {
  6.     //шаблон для вывода игры находится в views/games/_short_desc.php
  7.     $this->controller->renderPartial('_short_desc', array('game'=>$model));
  8.     if ($i % 2 !== 0) {
  9.         echo '<div class="clear"></div>';
  10.     }
  11.     $i++;
  12. }
  13. ?>

Как видите, для вывода игры мы использовали представление, которое относится к контроллеру Games (views/games/_short_desc.php).

Последний шаг – подключение шаблона в макете (файл protected/views/layouts/main.php)

  1. <div id="top_games" class="grid_9">
  2. <?php $this->widget('application.components.TopGames'
  3.     , array('title'=>'Популярные игры'
  4.         ,'showOn'=>array('games/list','types/show')
  5.         ,'count'=>4)); ?>
  6. </div><!– top_games –>

Тут стоит отметить передачу параметров виджету. Они должны быть записаны в виде массива. При этом, ключ элемента должен совпадать с именем соответствующего свойства класса.

На этом мы остановимся. Думаю, общее представление о виджетах у вас появилось. Но в этой статье рассмотрены далеко не все их возможности, поэтому очень советую почитать соответствующий раздел справки.

Продолжение следует ;)

Все разделы цикла.

  1. Yii PHP framework: создаём игровой сайт. Часть 1. Постановка задачи.
  2. Yii PHP framework: создаём игровой сайт. Часть 2. База данных и установка фреймворка.
  3. Yii PHP framework: создаём игровой сайт. Часть 3. Аутентификация.
  4. Yii PHP framework: создаём игровой сайт. Часть 4. Работа с жанрами игр.
  5. Yii PHP framework: создаём игровой сайт. Часть 5. Импорт игр.
  6. Yii PHP framework: создаём игровой сайт. Часть 6. Формируем страницы игр и жанров.
  7. Yii PHP framework: создаём игровой сайт. Часть 7. Работа с JavaScript и страницы игр.
  8. Yii PHP framework: создаём игровой сайт. Часть 8. Создаём виджеты.
  9. Yii PHP framework: создаём игровой сайт. Часть 9. Поиск ошибок.
  10. Yii PHP framework: создаём игровой сайт. Часть 10. Панель управления.
  11. Yii PHP framework: создаём игровой сайт. Часть 11. Человекопонятные URL.
  12. Архив с исходниками

Понравилась статья? Подписывайтесь на продолжение rss link !

Или на мой твиттер twitter link

]]>

Добавьте эту страницу в google.com bobrdobr.ru del.icio.us technorati.com linkstore.ru news2.ru rumarkz.ru memori.ru moemesto.ru

]]>

Опубликовано в MySQL, PHP, Web разработка, Yii View Comments

]]>
blog comments powered by Disqus ]]>