Контроллеры и виды в Yii 2. Создание новостного блога

Контроллеры и виды в Yii 2. Создание новостного блога

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

Контроллеры в Yii Framework являются составной частью MVC архитектуры [1]. Подразумевается, что это объекты классов, которые унаследованы от yii\base\Controller и отвечают за обработку запросов пользователей и генерацию ответа. Контроллеры включают в себя действия, являющиеся основными блоками, к которым обращается конечный пользователь и запрашивает исполнение какого-либо функционала. В контроллере может быть как  одно, так и несколько действий. Поэтому для того, чтобы приложение могло обрабатывать запросы, то первое, что необходимо - это создать соответствующий контроллер. Вещи, которые вы должны помнить при создании файла контроллера, можно сформулировать следующим образом:

•    Указать пространство имен в верхней части файла, в базовом приложении это обычно - namespace app\controllers;
•    Указать ключевое слово use для пути используемого класса - use yii\web\Controller;
•    Класс контроллера должен быть расширением базового контроллера Yii фреймворка - class MyController extends Controller;
•    Действия обрабатываются из функций контроллера, чьи имена начинаются со слова action и первая буква каждого следующего слова должна быть в верхнем регистре.

Давайте создадим файл с именем NewsController.php, т.е. контроллер как расширение базового контроллера. Затем в нем создадим класс с тем же именем, что и файл и, наконец, создадим действие actionIndex() для подключения вида views/news/index.php и управления запросами:

 
<?php
namespace app\controllers;
use yii\web\Controller;
class NewsController extends Controller
{
     public function actionIndex()
         {
           return $this->render('index'); //подключение вида
         }
 }

Затем создадим файл index.php в каталоге views/news/index.php:

<?php
use yii\helpers\Html;
$this->title = 'Блог';
$this->params['breadcrumbs'][] = $this->title; // меню хлебные крошки
?>
<div class="site-about">
    <h1><?= Html::encode($this->title) ?></h1>
    <h2>Блог последних новостей</h2>
<p>
       Изменить содержание страницы вы можете здесь:
    </p>
    <code><?= __FILE__ ?></code>
</div>

Если мы укажем браузеру http://basic.loc/web/index.php?r=news/index, мы увидим следующее:

Контроллеры и виды. Создание новостного блога

Если в контроллере вместо строки return $this->render('index'); указать  return 'Блог последних новостей'; то мы увидим строку “Блог последних новостей”  на пустой белой странице.

Теперь об тех ошибках, которые встретятся, если мы будем игнорировать эти четыре вещи, о которых говорили в начале урока.

Пространство имен определяет иерархическую организацию для имен, используемых в нашем приложении. Если мы забываем объявить пространство имен, а Yii2 с YII_DEBUG установлен верно в web/index.php, то появится следующее сообщение об ошибке:

yii 4 3

Отсутствует пространство имен контроллера

Как мы видим, Yii2 выдает сообщение об ошибке таким образом, что позволяет нам понять и решить возникшую проблему путем проверки, когда мы видим, что отсутствует пространство используемого имени.

Затем, если не используется ключевое слово Use для того, чтобы указать полный путь к классу в приложения, то возникает следующее сообщение об ошибке:

Контроллеры и виды. Создание новостного блога

На класс, который имеет полный путь path/to/class/ClassName, можно ссылаться в приложении, используя только ClassName, если при этом использовать строку use path/to/class/ClassName сразу после объявления пространства имен:

use yii\web\Controller;

Однако, если мы используем только ClassName без определения использования декларации в верхней части файла, то мы увидим сообщение об ошибке.

Эта ошибка легко объясняется, но ее не просто бывает найти, особенно для начинающих. В данном случае, на скриншоте видно, что было использовано имя контроллера (после ключевого слова extends) в строке 5. Поскольку нет полного пути к имени класса контроллера, yii2 будет стараться искать класс контроллера среди app\controllers, не находя его.  Чтобы разрешить проблему, необходимо вставить использования декларации в верхней части файла, т.е. мы должны использовать use yii\web\Controller, либо указать полный адрес к базовому контроллеру в строкеобъявления класса:

class CountryController extends \yii\web\Controller {
.....................................
}

Контроллер новостей NewsController

Теперь создадим контроллер для вывода списка кратких новостей:

<?php
namespace app\controllers;
use yii\web\Controller;
class NewsController extends Controller
{
     public function actionItemsList()
         {
           return $this->render('itemslist');
         }
    
 }

Создание вида для отображения списка новостей

Теперь мы будем создавать простой список новостей в виде под названием itemsList. Мы будем указывать на этот вид из NewsController, так что мы должны создать папку новостей в каталоге views/news, а в ней создать файл itemsList.php. Следовательно, контроллер NewsController будет использовать вид для подключения (в соответствии с правилами названия представлений, которые мы уже описали в предыдущих уроках). Теперь в файле itemsList.php создадим массив со списком данных в виде простой таблицы элементов:

<?php
use yii\helpers\Html;
$this->title = 'Блог';
$this->params['breadcrumbs'][] = $this->title;
$newsList = [
[ 'title' => 'О чем говорят программисты. Интересный опрос', 'category' => 'Последние новости', 'date' => '25 сентября 1916'],
[ 'title' => 'Веб-дизайн для начинающих. Бесплатный курс', 'category' => 'Последние новости','date' => '4 марта 1916'],
[ 'title' => 'Slim микрофреймворк для PHP для ваших проектов', 'category' => 'Последние новости', 'date' => '23 февраля 1916']
];
?>
<table width="600" cellspacing="15" cellpadding="10">
<tr>
<th>Заголовок</th>
<th>Категория</th>
<th>Дата</th>
</tr>
<?php foreach($newsList as $item) { ?>
<tr>
<td><?php echo $item['title'] ?></td>
<td><?php echo $item['category'] ?></td>
<td><?php echo $item['date'] ?></td>
</tr>
<?php } ?>
</table>

Наберем в адресной строке браузера следующее, чтобы увидеть результат http://basic.loc/web/index.php?r=news/items-list

Контроллеры и виды в Yii 2. Создание новостного блога

Как контроллер посылает данные для просмотра

Итак, мы создали вид для отображения списка новостей, которые представляют собой статические данные, оформленные в виде таблицы. Вид также является частью MVC архитектуры, т.е. это код, отвечающий за представление данных пользователям. В Web-приложениях виды оформляются, как правило, в виде шаблонов, являющихся PHP скриптами, которые могут содержать HTML и PHP код, отвечающий и за представление, и за внешний вид. В нашем примере PHP код генерирует динамическое содержание в виде заголовка страницы, меню “Хлебные крошки” и выводит в цикле массив данных, а HTML код организует полученные данные в табличной форме в конечную html страницу, используя общий для сайта шаблон views/layouts/main.php.

В Yii2 фреймворке для видов существуют определенные соглашения, касающиеся их организации:
•    Виды, которые подключаются из контроллеров, располагаться в папке @app/views/ControllerID, где ControllerID это имя контроллера. Например, если имя класса контроллера - NewsController, то название папки будет @app/views/news; если контроллер - NewsCommentController, то название папки будет @app/views/news-comment. Если же контроллер принадлежит модулю, то каталог будет views/ControllerID в подкаталоге модуля.
•    Виды, которые подключаются из виджетов, должны располагаться в VidgetPatch/views, где VidgetPatch - это каталог, который содержит класс виджета.
•    С видами, которые подключаются из других объектов рекомендуется обходиться аналогично с видами виджетов.

Данные могут быть переданы в вид разными способами, тем не менее, вид должен отвечать только за отображение данных, а не за манипуляции ими. Следовательно, любая работа по сбору данных должна быть реализована в действиях контроллера, а уже затем передаваться для просмотра. Метод render() в действии контроллера имеет второй параметр, который является массивом, ключи которого являются именами переменных, а значения является содержанием этих переменных, доступных в контексте вида.

Теперь, давайте переместим все манипуляции с данными из нашего примера itemsList, в контроллер, оставив только код для форматирования вывода (например, HTML).
Ниже приводится содержание actionItemsList () контроллера:

<?php
namespace app\controllers;
use yii\web\Controller;
class NewsController extends Controller
{
     public function actionItemsList()
         {
            $newsList = [
[ 'title' => 'О чем говорят программисты. Интересный опрос', 'category' => 'Последние новости', 'date' => '25 сентября 1916'],
[ 'title' => 'Веб-дизайн для начинающих. Бесплатный курс', 'category' => 'Последние новости','date' => '4 марта 1916'],
[ 'title' => 'Slim микрофреймворк для PHP для ваших проектов', 'category' => 'Последние новости', 'date' => '23 февраля 1916']
];
           return $this->render('itemsList', ['newsList' => $newsList]);
         }
     }


В views/news/itemslist.php мы оставим только следующее:

<?php
use yii\helpers\Html;
$this->title = 'Блог';
$this->params['breadcrumbs'][] = $this->title;
?>
<table width="400" cellspacing="15" cellpadding="10">
<tr>
<th>Заголовок</th>
<th>Категория</th>
<th>Дата</th>
</tr>
<?php foreach($newsList as $item) { ?>
<tr>
<td><?php echo $item['title'] ?></td>
<td><?php echo $item['category'] ?></td>
<td><?php echo $item['date'] ?></td>
</tr>
<?php } ?>
</table>

Таким образом, мы более оптимально разделили работу контроллера и вида.

Пример создания контроллера для отображения статического списка новостей и вывод подробностей по выбранной одной статье

Наша следующая задача состоит в том, чтобы завершить программу чтения новостей, отображающей детали полной новости на другой странице. Так как мы будем использовать те же данные списка и детализации, мы будем извлекать данные из переменной $newsList действием по отношению к функция dataItems(), для того, чтобы их можно было повторно использовать для большего количества действий.

Итак, NewsController будет содержать следующий код:

public function dataItems()
{
$newsList = [
                              [ 'title' => 'О чем говорят программисты. Интересный опрос', 'category' => 'Последние новости', 'date' => '25 сентября 1916'],
                              [ 'title' => 'Веб-дизайн для начинающих. Бесплатный курс', 'category' => 'Последние новости','date' => '4 марта 1916'],
                              [ 'title' => 'Slim микрофреймворк для PHP для ваших проектов', 'category' => 'Последние новости', 'date' => '23 февраля 1916']
                   ];
return $newsList;
}
public function actionItemsList()
{
$newsList = $this->dataItems();
return $this->render('itemsList', ['newsList' => $newsList]);
}

После этого, мы создадим новую функцию в NewsController actionItemDetail, которая будет использована для обработки запросов деталей составляющих элементы новостей. Эта функция будет ожидать параметр, который позволит отфильтровать соответствующие элементы из $newsList, например, заголовок. Ниже приводится содержание экшена actionItemDetail:

public function actionItemDetail($title)
{
$newsList = $this->dataItems();
$item = null;
foreach($newsList as $n)
{
if($title == $n['title']) $item = $n;
}
return $this->render('itemDetail', ['item' => $item]);
}

Далее мы должны создать новый файл вида в views/news по имени itemDetail.php. Ниже приводится содержание itemDetail.php, который находится в views/news:

<?php // $item is from actionItemDetail ?>
<h2>Новости: подробности<h2>
<br />
Заголовок: <b><?php echo $item['title'] ?></b>
<br />
Категория: <b><?php echo $item['category'] ?></b>
<br />
Дата: <b><?php echo $item['date'] ?></b>

Если мы набираем в адресной строке http://basic.loc/web/index.php?r=news/item-detail без указания параметра заголовка, то мы увидим сообщение об ошибке - Bad Request (#400)  Missing required parameters: title. Но если набрать в качестве параметра заголовка URL так, как приведено ниже http://basic.loc/web/index.php?r=news/item-detail&title=Slim%20%D0%BC%D0%B8%D0%BA%D1%80%D0%BE%D1%84%D1%80%D0%B5%D0%B9%D0%BC%D0%B2%D0%BE%D1%80%D0%BA%20%D0%B4%D0%BB%D1%8F%20PHP%20%D0%B4%D0%BB%D1%8F%20%D0%B2%D0%B0%D1%88%D0%B8%D1%85%20%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82%D0%BE%D0%B2,  то вы получите следующие подробные данные о выбранной одной статье:

 Контроллеры и виды. Создание новостного блога
В нашем случае, у нас news/item-detail выступает как указание маршрута при вызове подробностей  и в качестве параметра в URL должен быть указан заголовок.

 

Литература

  1. guide.yii-info.by (оф.руководство)
  2. Полное руководство Yii2 (рус.)
  3. Fabrizio Caldarelli. Yii2 By Example, 2015, с. 283


Проект IRBIS

Проект IRBIS

Проект IRBIS - это проект развития интеллектуальных ресурсов и содействие преобразованию специалистов в технологически грамотных и социально ответственных профессионалов в области информационных технологий.

Разработка веб-приложений

Проект IRBIS

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

Back-end разработка

HTML-верстка: инструменты и приемы профессиональной front-end разработки c 29 января 2016 по 23 марта 2016

Front-end разработчик

HTML-верстка: инструменты и приемы профессиональной front-end разработки