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

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

001
002
003
004
005
006
007
<?php
 
$view->body # имя шаблона Body
$view->layout # имя шаблона Layout
$view->_v # массив переменных вида, используемых в шаблонах Body
$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() заполнится массив ->_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'. Смотрите пример, код в контроллере:

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
<?php
 
class t_posts extends Model_t
{
    static $rubrics = [
        'Строительство',
        'Сад и огород',
        # ...
    ];
 
    function listing() {
        return [
            'query' => sql(SQL::PARSE'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);
            },
        ];
    }
# ... другие методы модели
}

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

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; while ($row SQL::row($e_posts->query$e_posts->row_c)):
# если не указать `: $item` в цикле @for, подставится переменная по умолчанию $row
 
?>

Теперь посмотрите определение SQL::row(..)

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
<?php ... class SQL
    static function &row(&$q$func) {
        $is_ary is_array($q);
        if (!$q)
            return $q;
        if ($row $is_ary ? (object)$q mysqli_fetch_object($q)) {
            if (is_callable($func))
                call_user_func_array($func, [&$row]);
            if ($is_ary)
                $q false;
        } else {
            mysqli_free_result($q);
        }
        return $row;
    }
    ...
 
опубликовано ENERGY - 18 Mar 2016 13:36 GMT
последнее редактирование - 10 Jul 2018 14:30 GMT
 +  0  -  комментировать