Описание механизма View

SKY / WINGS / FIRST /
VIEW1
Для фронтальной части приложений, при формировании ответа сервера, всегда используется функция view(), как минимум один раз (top-view). В ней всегда могут использоваться шаблоны парсера Jet, а также подготовленные переменные:

001
002
003
004
005
006
007
<?php
 
$view->body # имя шаблона Body
$view->_v # массив переменных представлений, используемых в шаблонах Body
View::$layout # имя шаблона Layout
View::$_y # массив переменных представлений, используемых в Layout
$sky->style

View::$layout - содержит имя layout. По умолчанию, перед запуском action (метода) контроллера, для top-view, для не ajax запросов, устанавливается `desktop` или `mobile`. Для ajax, по умолчанию - пустая строка. Пример шаблона layout: `view/y_desktop.php`. Префикс `y_` указывает на то что это файл layout. Если View::$layout - пустая строка, значит layout макет не используется. Если и $view->body и View::$layout - пустая строка, ответом сервера есть $view->stdout (перехватывается вывод echo.. в контроллерах). В этом случае, Jet и шаблоны не используются вообще.

Макеты layout обычно содержат одну директиву Jet @body, или @inc(*) или @require(*), в это место вставится результат рендеринга body-части.

В переменную `$view->body`, по умолчанию, для top-view, всегда устанавливается значение первого ключа массива $_GET (или строка 'main', для главных страниц). В контроллерах это значение может корректироваться. Если в контроллере сделано `echo ..`, не стоит заботиться о том, чтобы подкорректировать значение $view->body, пустая строка присвоится автоматически. В конечном итоге, в функцию view() может передаваться:

1) пустая строка - это значит, что шаблон body не используется и необходимый вывод данных уже сделан в контроллере, остальные переменные и layout при этом могут использоваться;
2) не пустая строка - используется шаблон из файла, например: 'news' соответствует файлу `view/_news.php`;
3) строка с точкой, например 'news.edit' соответствует части файла `view/_news.php` с маркером `edit`;

Подробно о маркерах можно прочесть в узле JET.

Приложения редко используют множественные стили, поэтому $sky->style часто не используется и по умолчанию содержит пустую строку. Для приложений со стилями $sky->style содержит имя стиля, а шаблоны Jet помещаются в папку `view/имя стиля`, файлы в папке pub, также: `pub/имя стиля`, например view/summer/_main.php или pub/summer/front.css. Выбранные пользователями стили можно помещать в $user->v_style или $user->u_style. После идентификации, присваивать стиль: $sky->style = $user->v_style;

Вспомогательные view, метки и hardcache

Вызовы функции view() могут быть вложенными, т.е. в шаблоне можно использовать директиву Jet @view(..). Вместо нее, в шаблон вставится результат рендеринга. Также view() можно вызвать до заполнения переменных $view->_v и View::$_y и использовать ее рендеринг в подготовке top-view или другого промежуточного view.

Запуск top-view происходит автоматически, при этом функция view() вызывается без параметров. Вспомогательные view вызывают функцию с параметрами:

mixed view([$action_name = false, [$return_string = false, [$parameter = null]]])

Первый параметр - прототип имени action контроллера, второй - вернуть ли рендеринг в строке или выдать в stdout и третий - параметр передаваемый в action. Если $action_name не имеет префикса, автоматически добавится `x_`. Метод контроллера будет искаться вначале в "своем" контроллере, и если не найдет, то в общем `common_c`. Пример главного контроллера:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
<?php
 
class c_main extends Controller
{
    function empty_a() {
        echo cache('main', function() { # на самом деле, в данном случае, можно написать только лишь:
            return view('main'true);  # echo cache('main', 'view');
        });
    }
 
    function x_main() {
        $row $this->t_article->get_article('main'3);
        $this->_v = [
            'e_packs' => $this->m_gate->listing(0false),
            'e_blogs' => $this->t_blog->listing(0true),
            'content' => label($row->content),
        ];
    }
# ...
}

В примере выше, при открытии главной страницы сайта, автоматически запускается метод c_main::empty_a(), после его отработки, автоматически запускается top-view, формируется ответ сервера. Так как в контроллере есть `echo`, значение выставленное по умолчанию 'main' в $view->body автоматически заменится на пустую строку и в view/y_desktop.php для секции body будет использовано <?php echo $view->stdout ?>. Так как View::$layout не пустая строка, в методе common_c::tail_a() заполнится массив View::$_y для layout. Функция `cache` проверяет наличие и TTL файла `var/cache/ru_main.html`, если ОК, то считывает файл и возвращает его содержимое, при этом view('main', true) не вызывается вообще. Иначе вызывает view, который, в свою очередь вызывает c_main::x_main(). Для этого метода автоматически установлено View::$layout - пустая строка и шаблон $view->body равен 'main', т.е. будет использован файл `view/_main.php`. В методе проходят вызовы к моделям, заполняется массив ->_v для шаблона. Функция label() заменяет метки в строке, считанной из БД, на рендеринг вызовов view(), чтобы обеспечить сложный вывод для которого требуется PHP.

Переменные для шаблонов


Переменные для master-layout обычно заполняются в common_c::tail_a() в массив View::$_y. Общий контроллер вызывается автоматически для всех страниц, подробные детали смотрите в узле MVC. В массиве ключами являются прототипы имен переменных в шаблонах. Значениями этих переменных, обычно являются значения, что присваиваются элементам массива View::$_y. Если ключ не имеет префикса, автоматически добавляется `y_`. В шаблонах переменные с префиксом $y_ это основные переменные для layout. Но в массиве View::$_y можно явно указывать ключи и с другими префиксами:
1) d_ - позволяет получить в шаблоне переменную без префикса. Этим нужно пользоваться в крайнем случае;
2) v_ - определяет или переопределяет переменную для `body` шаблона. Это редко может понадобиться, так как для `body` есть свой массив $view->_v;
3) h_ - переменные прошедшие через функцию htmlentities(). Тоже может редко понадобиться так как проще делать вывод в шаблоне через оператор Jet {{ $var }} который также применяет htmlentities(). Однако используя этот префикс, можно автоматически заескейпить рекурсивно массив строк.
4) k_ - корректирование или определение переменных массива $sky->vars. В этот массив собираются автоматически вычисленные ядром переменные, который передается во все шаблоны и даже в файлы админ. раздела. Например $k_tkd содержит массив из 3 элементов: title, keywords, description, значения которым присваиваются в админ. разделе, в конфигурации. Если вы забудете определить ключевые слова для конкретной страницы, то используются ключевые слова по умолчанию из переменной $k_tkd. Или же $k_type всегда содержит эвристически вычисленный тип CRUD операции. $k_type может быть автоматически предустановлена в 'list', 'edit', 'new' или 'show'.
5) e_ - ключам с этим префиксом, необходимо присваивать массив, но в шаблонах массив преобразуются в объект типа stdObject. Это позволяет группировать переменные в один объект, но и также используется для итераторов Jet.

Для массива $view->_v, который передает переменные в шаблон @body все работает аналогичным образом, но только переменным без префикса, автоматически присваивается префикс `v_`.

Метод общего контроллера common_c::head_a() вызывается раньше главного метода центрального контроллера, поэтому можно определить часть переменных массива View::$_y в common_c::head_a(), потом в центральном контроллере подкорректировать значение переменной для layout и в common_c::tail_a() до-собирать переменные для layout. В общем такая система сбора переменных имеет довольно большие, удобные возможности.

Подробно об итераторах Jet


Присвоенный, в контроллере массив переменных, элементу массива ->_v с ключем, который имеет префикс `e_`, в шаблоне преобразуется в stdObject. У переменных с префиксом $e_ есть три специальных свойства объекта stdObject, с их помощью организуются отложенные вызовы для организации листингов, это 'query', 'row_c', 'max_i' и 'after_c'. Смотрите пример, код в контроллере:

001
002
003
004
005
006
007
008
009
010
011
012
013
<?php
 
class c_posts extends Controller
{
    function empty_a() { #list
        if ($_POST$this->a_delete();
        $this->_v = [
            'h1' => 'Листинг постов',
            'e_posts' => $this->t_posts->listing(),
        ];
    }
# ... другие методы контроллера
}

Код в модели:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
<?php
 
class t_posts extends Model_t
{
    static $rubrics = [
        'Строительство',
        'Сад и огород',
        # ...
    ];
 
    function listing() {
        return [
            'query' => 'select * from $_ order by id',
            'btn' => false,
            'row_c' => function ($row) {
                global $user;
                if ($user->root || $row->user_id == $user->id)
                    $row->checkbox sprintf(TPL_CHECKBOX$row->id'');
                $row->rubric self::$rubrics($row->rubric_id);
            },
            'after_c' => function ($row) {
            // вызывается после окончания отработки текущего итератора. Это может быть полезно,
            // когда за текущим следует еще один итератор и необходимо установить начальные значения
            }
        ];
    }
# ... другие методы модели
}

Код в шаблоне:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
<?php #файл view/_posts.php ?>
 
<h1>{{ $v_h1 }}</h1>
 
<form method="post">
@for ($e_posts : $item)
    #{{1 + $a}}. {{ $item->rubric }} / {{ $item->text }}
    @if (isset($item->checkbox))
        {! $item->checkbox !}
        @php $e_posts->btn = true ~php
    ~if
    <br>
    @empty
        Нет постов
    @else
        Total items: {{ $a }} ~{- Это напечатается только если посты были -}
~for
 
@if ($e_posts->btn)
    <input type="submit" value="delete checked">
~if
</form>
 

Чтобы использовать итераторы Jet, в модели, практически всегда, нужно делать так: из функции листинга возвратить массив, в котором ключу 'query' должен быть присвоен ресурс (объект) запроса, а ключу 'row_c' Closure или callback функция, которая корректирует считанные ряды из БД. В контроллере возвращенный из модели массив присвоить ключу с префиксом e_, как в примере, тогда в шаблоне, можно использовать итераторы Jet. По сути, специальный синтаксис циклов @for ($e_posts), Jet превращает в код:

001
002
003
004
005
006
<?php
 
$a 0; foreach ($e_posts as $row):
# если не указать `: $item` в цикле @for, подставится переменная по умолчанию $row
 
?>


Итераторы Jet могут также, формировать значения динамически, без обращения к БД. Для этого, параметр 'query' не используем, а в 'row_c' просто возвращаем массив значений каждой итерации. Для прекращения итераций, необходимо вернуть false. На этапе написания кода, вы можете указать: 'query' => 100,, т.е. установить значение не ресурс запроса к БД, а значение integer. Это ограничит максимальное значение циклов итераций. Так вы гарантированно не подвесите компьютер на бесконечную итерацию. Когда код будет отлажен, 'query' => 100 можно будет удалить.

Возможность итераций без установленного ресурса MySQL в поле `query`, делает итераторы Jet функционально полными. Во-первых, все итерации в шаблонах предпочтительно делать по единой схеме. Непосредственная установка значений `$row`, дает возможность все итерации делать единым образом. Во-вторых, такие итерации, могут потребоваться функционально эксклюзивно. Например, в коде делается итерация с использованием запроса SELECT к БД, для одной цели, а позже, эти-же значения, необходимо перебрать в шаблоне. Можно сохранить нужные значения в массив и в массиве перебрать в шаблоне:

001
002
003
004
005
006
007
008
009
010
<?php # инструкция return в методе модели:
return [
    'total' => count($table),
    'e_list' => [
        'row_c' => function() use (&$table) {
            return $table array_shift($table) : false;
        }
    ],
];
 

Дело, в том, что и в случае использования итератора, получающего ряды из БД, и во втором случае, когда перебирается готовый массив, можно использовать один и тот-же шаблон представления: @for($e_list) ... ~for.
published ENERGY - 18 Mar 2016 13:36 GMT
last edit - 26 Apr 2021 02:45 GMT
 +  0  -  add comment