Yii PHP framework: создаём игровой сайт. Часть 4. Работа с жанрами игр.

12 января, 2010
yii game site

Сегодня мы продолжим разработку игрового сайта и напишем код необходимый для создания, удаления и изменения жанров.

Но вначале два небольших объявления.

1) Я как-то упустил, что есть русский перевод документации Yii, причём очень качественный.

2) Я решил выложить весь исходный код этого сайта, думаю так будет проще экспериментировать. Все-таки копировать куски кода из блога неудобно.

архив с исходным кодом

Инструкция по установке.

1) В архиве находятся: папка public_html (в ней только исходные файлы сайта, без самого фреймворка), файл dump.sql (с дампом базы) и файл с инструкциями.

2) Распакуйте папку public_html так, чтобы DOCUMENT_ROOT вашего сервера указывал на ее содержимое (при желании, саму папку можно переименовать).

3) Откройте файл index.php и укажите путь к фреймворку Yii (строка 4).

4) Откройте файл \protected\config\main.php и укажите параметры подключения к базе данных (строки 45-47).

5) Импортируйте базу данных (файл dump.sql), например, с помощью phpMyAdmin.

6) Можно работать :)

7) Адрес входа в админку http://sitename.local/index.php?r=dashboard

Сразу хочу обратить ваше внимание, что это не окончательная версия сайта и, скорее всего, в ней есть баги и недоработки. Поэтому буду рад, если вы о них мне сообщите ;)

Возвращаемся к жанрам.

Открываем окно консоли и выполняем команды

>> yiic shell
>> model Types ygs_types
>> crud Types

В результате будут созданы:

1) Класс модели \protected\models\Types.php

2) Класс контроллера \protected\controllers\TypesController.php

3) Папка с представлениями \protected\views\types\

По-умолчанию, контроллер содержит 6 методов, которые предназначены для формирования страниц. Это:

actionShow (адрес types/show) – страница с выбранным жанром;
actionCreate (адрес types/create) – форма создания нового жанра;
actionUpdate (адрес types/update) – форма изменения жанра;
actionDelete (адрес types/delete) – удаление жанра;
actionList (адрес types/list) – список жанров;
actionAdmin (адрес types/admin) – список жанров с кнопками «Изменить» и «Удалить».

Тут я хочу обратить ваше внимание на один момент. Этот контроллер ничего не знает об играх. Поэтому на страницах show и list будут просто выведены отдельные жанры и их список, без игр.

Этот список мы оформим в виде виджета и поместим в сайдбаре, а для вывода игр, которые относятся к выбранному жанру, по-моему, будет логичнее использовать контроллер GamesController, который мы рассмотрим в следующий раз.

Я начинаю с жанров только потому, что они должны быть созданы до того как будет выполнен импорт игр из фида партнерки.

Т.е. методы actionShow и actionList нам не нужны, поэтому закроем к ним доступ. Чтобы не удалять эти методы из контроллера, я просто закомментировал первый элемент массива в методе accessRules. В результате при попытке доступа к ним посетитель увидит страницу с 403-ей ошибкой «У вас недостаточно прав для доступа к запрошенной странице».

Вносим небольшие изменения в методы actionCreate и actionUpdate. Нам нужно только изменить редирект. Посмотрите, например, на actionUpdate.

  1. public function actionUpdate()
  2. {
  3.     $model=$this->loadTypes();
  4.     //если запрос отправлен через форму изменения жанра
  5.     if(isset($_POST['Types']))
  6.     {
  7.         $model->attributes=$_POST['Types'];
  8.         //если жанр сохранен, переходим на страницу управления жанрами
  9.         if($model->save())
  10.             $this->redirect(array('admin'));
  11.     }
  12.     $this->render('update',array('model'=>$model));
  13. }

Прежде всего, мы создаём модель. Для этого метод loadTypes читает $_GET['id'] и выполняет запрос к базе.

Затем проверяем, заполнял ли пользователь форму. Если нет – показываем страницу с формой (используется представление \protected\views\types\update.php), и в этом представлении мы можем получить данные из базы, используя переменную $model (об этом чуть позже).

Если пользователь заполнил и отправил форму, сохраняем модель и отправляем редирект на страницу types/admin.

Тут есть несколько интересных моментов.

Взгляните на строку

  1. $model->attributes=$_POST['Types'];

При её выполнении используется метод setAttributes, который при присваивании элементов $_POST['Types'] будет использовать только безопасные атрибуты (safe attributes).

Определить список безопасных атрибутов можно с помощью метода модели safeAttributes

  1. public function safeAttributes() {
  2.     return array('t_id', 't_name');
  3. }

Таким образом, фреймворк автоматически фильтрует все данные, которые не относятся к форме.

UPD. В версии 1.1 метод safeAttributes можно не использовать. Атрибуты считаются безопасными, если они упоминаются в правилах, которые возвращает метод rules(). При этом, правила должны относиться к данному сценарию (подробнее здесь). Спасибо, SAM!

При вызове $model->save() перед сохранением выполняется валидация данных. Правила валидации возвращает метод rules модели

  1. public function rules()
  2. {
  3.     return array(
  4.         array('t_name','length','max'=>45),
  5.         array('t_id', 'required'),
  6.         array('t_id', 'numerical', 'integerOnly'=>true),
  7.     );
  8. }

Как видите, по-умолчанию, для создания правил используются данные таблиц БД.

Переходим к работе с представлениями.

Как видите, для отображения представления используется метод render. В его первом параметре нужно указать имя файла представления (без расширения), а во втором – массив со всеми переменными к которым мы хотим получить доступ в представлении.

При этом если мы будем использовать встроенные библиотеки фреймворка, то в большинстве случаев будет достаточно передать экземпляр модели. Прежде всего, это касается класса CHtml.

Он содержит методы для создания различных элементов, причем для многих элементов есть по два метода. Например, CHtml::activeLabel() и CHtml::label(). Оба используются для создания тега label, но первый в качестве параметра получает экземпляр модели и использует её в качестве источника данных, а для второго метода нужно передать все данные явно.

Кстати, обратите внимание на метод attributeLabels модели

  1. public function attributeLabels()
  2. {
  3.     return array(
  4.         't_id' => 'Id жанра',
  5.         't_name' => 'Жанр',
  6.     );
  7. }

Он возвращает массив с названиями полей, которые используются методами с приставкой active.

В качестве примера рассмотрим представление update.php

  1. <?php
  2. //страница "Изменить жанр"
  3. //используется шаблон dashboard
  4. $this->layout = 'dashboard'; ?>
  5. <h2>Изменить жанр: <?php echo $model->t_name; ?></h2>
  6.  
  7. <div class="actionBar">
  8. [<?php echo CHtml::link('Управление жанрами',array('admin')); ?>]
  9. [<?php echo CHtml::link('Создать жанр',array('create')); ?>]
  10. </div>
  11.  
  12. <?php echo $this->renderPartial('_form', array(
  13.     'model'=>$model,
  14.     'update'=>true,
  15. )); ?>

Начнем со строки 4. В ней мы указываем, какой макет страницы нужно использовать. Дело в том, что Yii при создании страницы использует так называемый Two-Step View Pattern.

При этом для создания страницы используются минимум два файла. Первый – макет (layout) (может, есть более удачный перевод?), находится в папке \views\layuots\. Второй – файл представления, который указан в методе render.

Макет – это обычный php файл, содержащий строку
<?php echo $content; ?>
При обработке этого файла переменная $content будет содержать всю разметку представления.

В данном случае мы указываем, что нужно использовать макет dashboard, который я сделал для панели управления. Для остальных страниц сайта будет использоваться макет main.

В представлении для отображения формы используется метод renderPartial. Разница между render и renderPartial в том, что при вызове первого будет использован макет, а при вызове второго – нет. Т.е. мы просто вставляем форму (она находится в файле \views\types\_form.php).

Теперь давайте рассмотрим метод actionAdmin контроллера.

  1. public function actionAdmin()
  2. {
  3.     //обработка команды удаления
  4.     $this->processAdminCommand();
  5.     //формируем запрос
  6.     $criteria=new CDbCriteria;
  7.  
  8.     $pages=new CPagination(Types::model()->count($criteria));
  9.     $pages->pageSize=self::PAGE_SIZE;
  10.     $pages->applyLimit($criteria);
  11.     //настраиваем сортировку
  12.     $sort=new CSort('Types');
  13.     $sort->applyOrder($criteria);
  14.     //выполняем запрос
  15.     $models=Types::model()->findAll($criteria);
  16.     //показываем страницу
  17.     $this->render('admin',array(
  18.         'models'=>$models,
  19.         'pages'=>$pages,
  20.         'sort'=>$sort,
  21.     ));
  22. }

Он создаёт таблицу с перечнем жанров. Напротив каждого жанра есть ссылки «Изменить» и «Удалить», а клик по заголовку столбца таблицы выполняет её сортировку.

Посмотрим, как работает этот метод.

Прежде всего, вызывается метод processAdminCommand. Он проверяет, был ли клик по ссылке «Удалить» и если был, удаляет соответствующую запись из базы.

Затем создаётся объект CDbCriteria. С его помощью можно изменять параметры запросов к БД. Например, можно указать список полей, которые должен вернуть запрос или ограничить количество строк.

Создаём объект CPagination, который используется для пагинации (разбивки записей на страницы). Обратите внимание, в качестве параметра конструктор получает общее количество записей. А это количество мы определяем с помощью метода count модели.

После этого, создаём объект CSort – сортировка записей. Этот объект использует параметр $_GET['sort'], который будет установлен при клике по заголовку столбца. С помощью метода applyOrder мы передаём параметры сортировки в объект CDbCriteria.

Таким образом, вызов Types::model()->findAll($criteria) возвращает записи таблицы, отсортированные в нужном порядке.

Заключительным этапом мы вызываем метод render. Ему передаём массив с найденными записями и объектами CPagination и CSort. CPagination используется для создания виджета с перечнем страниц, а CSort – для создания ссылок в заголовке таблицы.

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

Как видите, я не пытаюсь объяснить каждую строчку кода, да это и не реально :) . Вместо этого, я попытался объяснить общий принцип. Поэтому, если что-то непонятно, спрашивайте в комментариях.

В следующий раз я планирую рассказать о работе с играми. Это самая объемная часть. И в ней мы подробнее рассмотрим работу с моделями и библиотекой для работы с БД.

Удачи!

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

  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

]]>

Опубликовано в PHP, Web разработка, Yii Комментарии (7) »

]]>

Комментарии (7)

Вы можете отслеживать обсуждение записи с помощью RSS 2.0 rss link

Вы также можете оставить комментарий, или трекбек с Вашего сайта.

]]>
  1. Sam

    Стоит отметить, что safeAttributes в 1.1 задаётся в rules() как валидатор типа 'safe'.

  2. Судя по виду шаблона, шаблонизатор очень похож на Zend_Layout + Zend_View с характерными плагинами, типа renderPartial().

  3. Прикольно!)
    Так скоро сайтег по частям и соберёте!)

  4. Огромное вам спасибо! Особенно за архив

  5. Респект за русские доки!

]]>

Оставить комментарий

* - обязательные для заполнения поля

]]>