Представление

 

Всем доброго времени суток. Сегодня мы продолжаем реализацию ядра CMS RS-MINI. Мы уже собрали и запустили контроллеры, и написали алгоритм сборки шаблонов контроллера. Теперь нужно позаботиться о классе, где будут собираться все остальные шаблоны (это я про главный шаблон и шаблон узла)

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

Что же мы будем делать сегодня? Я предлагаю создать основу класса который будет запускать наши шаблоны, а так же написать метод, который покажет нам содержимое объекта класса dom.class.php, в приятном, для глаза, виде

Регистрируем константу DOM

Для чего нужна эта константа? Метод который мы напишем, позволит нам посмотреть содержимое объекта dom.class.php. Как Вы понимаете, в этом объекте может храниться информация, которую не стоит показывать обычным пользователям (к такой информации относятся например почтовые ящики комментаторов на блоге). Эта константа будет призвана включать и отключать просмоторщик этой информации.

У нас есть конфиг движка, поэтому разумно эту константу прописать именно там. (файл config.class.php который лежит в папке /project/conf/)

    /*
     * установка настроек движка
     *
     * @access - public
     */
    
    public static function setConfig()
    {
        define('DOM',               TRUE);       // включить/отключить просмотр данных с генерированных контроллером
        define('CMS',               'RS-MINI');  // имя движка
        define('VERSION',           '0.0.1');    // версия движка
        
        self::$db = array(
            'server'  => 'localhost',
            'user'    => 'root',
            'pass'    => '123456',
            'name'    => 'rs_mini'
        );                                       // настройки базы
    }

Кстати, в скором будущем, мы вообще перепишем этот класс. Я решил все константы (почти все) хранить в самой базе данных, а этот класс будет лишь получать и регать их.

Реализуем класс представления

Сейчас у нас есть возможность получить ассоциативный массив с домом посредством вызова метода getDom() класса dom.class.php. Нам лишь остается рекурсивно разобрать этот массив и отобразить его в html формате.

По сути метод который мы собираемся написать очень простой и разглагольствовать про его логику долго у меня не получится (если быть точнее, то мне уже нечего сказать) поэтому давайте я Вам продемонстрирую полный код класса, и вкратце поясню что к чему (файл будет лежать в папке /rs-mini/core/ и называть view.class.php)

<?php

/*
 * @package RS-MINI
 * @copyright (c) 2015 Alexey Glumov aka Rio-Shaman (support@rio-shaman.ru)
 * @license GNU General Public License version 2; see LICENSE.txt
 *
 */
 
namespace core;

if(!defined('RS-MINI')) die();

/*
 * view v 1.0
 *
 * класс собирает и запускает шаблоны
 *
 */

class view
{   
    
    /*
     * массив с шаблонами
     *
     * @var    - array
     * @access - private
     */
    
    private $tplList;
    
    /*
     * путь к шаблону узла
     *
     * @var    - string
     * @access - private
     */
    
    private $tplPage;
    
    /*
     * объект дома
     *
     * @var    - object
     * @access - private
     */
    
    private $dom;
    
    /*
     * создание объекта
     *
     * @access - public
     *
     * @param array  tplList - массив с шаблонами
     * @param string tplPage - путь к шаблону узла
     * @param object dom     - объект дома
     */
    
    public static function create($tplList, $tplPage, $dom)
    {
        // получаем имя вызываемого класса
        $who = get_called_class();
        
        // поднимает объект этого класса
        return new $who($tplList, $tplPage, $dom);
    }
    
    /*
     * конструктор
     *
     * @access - public
     *
     * @param array  tplList - массив с шаблонами
     * @param string tplPage - путь к шаблону узла
     * @param object dom     - объект дома
     */
    
    public function __construct($tplList, $tplPage, $dom)
    {
        // массив с шаблонами контроллера
        $this->tplList     = $tplList;
        // имя шаблона узла
        $this->tplPage     = $tplPage;
        // дом
        $this->dom         = $dom;
    }
    
    /*
     * запуск шаблонизатора
     *
     * @access - public
     *
     */
    
    public function run()
    {
        // выгрузка на страницу дома
        if (DOM === TRUE && !is_null(request::getHttpGet('dom')->getData())) {
            echo ''
                 .'<!DOCTYPE html>'
                 .'<html>'
                     .'<head>'
                         .'<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">'
                         .'<title>'. CMS .' v'. VERSION .' DOM</title>'
                     .'</head>'
                     .'<body>'
            ;
            
                 echo $this->getData($this->dom->getDom());
            
            echo ''
                    .'</body>'
                 .'</html>'
            ;
            
            // закрываем подключение к БД
            sql::close();
            die();
        }
        
        // или получаем страницу
        $this->getPage();
    }
    
    /*
     * получаем страницу (подключаем все нужные шаблоны)
     *
     * @access - private
     *
     */
    
    private function getPage()
    {
        // закрываем подключение к БД
        sql::close();        
    }
    
    /*
     * метод позволяет выгрузить дом на страницу (для разработчика).
     * Отладочный метод
     *
     * @access - private
     * @return - string с html кодом
     *
     * @param array data - массив с домом
     */
    
    private function getData($data)
    {
        // строка с html кодом дерева
        $result = '';

        // если массив с узлами не пустой
        if (!empty($data))
            // листаем его
            foreach ($data as $key => $node) {
                // формируем кусочек хтмла (имя узла)
                $row = '<ul style="list-style:none; padding-left:35px;"><li>[<b>' . $node['name'] . '</b>';
                
                // если есть атрибуты
                if (!empty($node['attr']))
                    // листаем их
                    foreach ($node['attr'] as $name => $value) {
                        
                        // чистим значение атрибута от html
                        $value = strip_tags($value);

                        // если значение больше 100 символов
                        if (mb_strlen($value, 'UTF-8') > 100)
                            // отрезаем для показа только 100 символов
                            $value = mb_substr($value, 0, 100, 'UTF-8') . '...';
                            
                        // формируем кусочек хтмл кода (имя и значение атрибута)
                        $row .= ''
                            . '<div style="padding-left:25px;">'
                                . '<span style="text-decoration:underline;">'
                                    . $name
                                . '</span>'
                                . '&nbsp;&rarr;&nbsp;'
                                . '<span style="font-style:italic;">'
                                    . $value
                                . '</span>'
                            . '</div>';
                    }
                
                // формируем кусочек хтмла
                $row .= ']';
                
                // если внутри текущего узла, есть еще узлы
                if (!empty($node['node']))
                    // перезапускаем метод с новыми данными
                    $row .= $this->getData($node['node']);

                // формируем кусочек хтмла
                $result .= $row . '[<b>/' . $node['name'] . '</b>]</li></ul>';
            }
        // если массив с узлами пустой, формируем сообщение об этом
        else
            $result = 'Нет данных';
        
        // возвращаем html
        return $result;
    }
}

(Как видите класс хорошо задокументирован, так что при желании его можно понять)

Все начнется у нас в классе application.class.php. Именно оттуда будет вызван статичный метод create() класса view.class.php. Вызов этого метода поднимет нам объект этого класса. В параметры конструктора передается

  • массив tplList который содержит объекты шаблонов контроллера
  • строка tplPage являющейся именем шаблона узла
  • и объект класса dom.class.php

и именно в конструкторе заполняются свойства класса tplList, tplPage и dom.

Далее из того же application.class.php будет запущен метод run() объекта класса view.class.php, тем самым запуститься главная логика представления. Этот метод разделен на две составляющие

  • показ содержимого объекта класса dom.class.php (собственно этим мы сегодня и занимаемся)
  • и запуска шаблонов сайта (то есть фактически отображения страницы для пользователя)

Показ содержимого объекта класса dom.class.php произойдет только тогда

  • когда в адресную строку браузера был послан параметр dom (http://mini.test.ru/?dom)
  • и константа DOM равна TRUE

Заметьте, что в этом классе я обрываю подключение к базе данных (sql::close()), тем самым, исключая возможность использовать запросы в шаблонах (практиковать запросы в шаблонах очень пагубная привычка)

Если условия соблюдены, то сформируется простая структура html документа, и в тег body рекурсивно выгрузится информация из массива который мы получили при помощи вызова метода getDom() класс dom.class.php

Вызов представления из application.class.php

Тут все очень просто. Пишем небольшой метод который поднимет объект класса view.class.php и запустит метод run()

Вот код этого метода: (файл application.class.php который находится в папке /rs-mini/core/)

    /*
     * метод стартует шаблонизатор
     *
     * @access  - private
     *
     * @param array  tplList  - массив с шаблонами
     * @param object page     - объект последний (открываемой) страницы
     */
     
    private static function viewRun($tplList, $page)
    {
        // запускаем представление
        view::create($tplList, $page->pageView, self::$dom)->run();
    }

Теперь осталось вызвать этот метод из метода controllerRun(). Вызывать нужно сразу после сборки шаблонов контроллера:

// если это последняя страница, запускаем контроллеры страницы и шаблонизатор
if ($key == (count(self::$map->pageList) - 1)) {
    
    // объявляем константу с заголовком открытой страницы
    define('PAGECAPTION', $caption);
    
    // массив с шаблонами контроллеров
    $tplList = array();

    // если в массиве runList есть контроллеры для запуска
    if (!empty($runList)) {
        // листаем контроллеры
        foreach ($runList as $data) {

            // стартуем контроллер
            if (!$data['obj']->run())
                self::notFound();
                
            // если среди параметров есть параметр шаблона
            if(!is_null($data['controller']->getParam('tpl'))) {
            
                // пропускаем отключенные контроллеры
                if ($data['controller']->getParam('tpl') == 'disable')
                    continue;
            
                // подставляем в путь доп папку
                // бьем имя шаблона на массив
                $tplClass                                      = explode('.', $data['controller']->getParam('tpl'));
                // отрезаем первые два элемента
                $tplSlice                                      = array_slice($tplClass, 2);
                // в третий элемент массива вставляем слово view
                $tplClass[2]                                   = 'view';
                // вертаем в массив оставшиеся элементы после отработки функции array_slice
                for ($i = 0; isset($tplSlice[$i]); $i++)
                    $tplClass[($i + 3)]                        = $tplSlice[$i];
                    
                // тем самым получаем полный путь к классу
                // пример: было pub.test.intro а стало pub\test\view\intro
                $tplClass                                      = implode('\\', $tplClass);
                // создаем объект в массиве ключем которого является
                // имя шаблона
                $tplList[$data['controller']->getParam('tpl')] = new $tplClass(self::$dom);
            }
        }
    }
    
    // запускаем шаблонизатор
    self::viewRun($tplList, $page);
}

Заключение

Теперь если мы перейдем вот по такому адресу http://mini.test.ru/about/?dom мы увидим наш пока единственный узел хлебных крошек:

отображение дома

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

Всего Вам наилучшего, на сегодня у меня все!

Прикрепленные файлы

 

Возможно Вам будут интересны следующие заметки

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

Ваше имя *
Сайт
Ваш E-mail *
Ваше сообщение *
 
Вы не подтвердили условия политики конфиденциальности.
Александр, 17 Сентября 2015 г. 10:42 пишет:
Читатель
Хорошая работа. Когда продолжение будет? И что будет в нем?=)
Алексей, 17 Сентября 2015 г. 21:12 пишет:
Автор
Когда продолжение будет?
Пытаюсь писать чаще.
И что будет в нем?
Еще много чего будет. Мы еще даже минимальный набор ядра не закончили
Ответ для пользователя: Александр
Александр, 17 Сентября 2015 г. 22:09 пишет:
Читатель
У Вас в заключении на картинке вроде не так идет вывод как Вы запланировали... или я могу ошибаться?)
[page]
caption-> Главная
patch -> /
[/page]
Так должно быть?
Ответ для пользователя: Алексей
Алексей, 17 Сентября 2015 г. 22:41 пишет:
Автор
Переходя по ссылке http://mini.test.ru/about/?dom я вижу именно то, что на изображение в заключение. Вы видите что-то иное?
Ответ для пользователя: Александр
Александр, 17 Сентября 2015 г. 23:03 пишет:
Читатель
Я имею ввиду квадратная скобка на своем месте?
Алексей, 17 Сентября 2015 г. 23:10 пишет:
Автор
Ах Вы про это... Да, так было задумано
Ответ для пользователя: Александр