Шаблонизатор с синтаксисом PHP и наследованием.

Rin

*
В аббревиатуре MVC последнее слово -- Controller.
Выше я написал о ещё одном шаблоне проектирования, где последнее слово -- Component.
Чтобы не вносить путаницу, лучше его называть как Model-View-Component, без использования аббревиатуры.
Model-View-Component я с успехом применяю на практике уже 5-6 лет.
 

fixxxer

К.О.
Партнер клуба
Ну просто разнес говнокод по кусочкам помельче. Вариант, конечно, если не хочется делать по нормальному ))

И не сбивай с толку. Я вот тоже могу везде писать MVC и потом говорить что это Milk Vanilla and Chocolate
 

Rin

*
fixxxer
>Ну просто разнес говнокод по кусочкам помельче. Вариант, конечно, если не хочется делать по нормальному ))
У меня есть опыт использования обоих подходов, Model-View-Component, на мой взгляд, лучше.
У тебя есть такой опыт?
 

Ирокез

бессмертный пони
Команда форума
Партнер клуба
епте, а я вообще использую MMVC :)

Model, Module-View-Controller

все равно-ж уже с темы соскочили, о а если быть точнее MHMVC
 

fixxxer

К.О.
Партнер клуба
>> MHMVC

Хм. Ну может я как раз и о таком говорил. Надо понять, где что :)

Rin
да всякий опыт есть. Вопрос в том можешь ли ты реюзать то, что называешь Component. В том смысле, что использовать для _совсем_ других отображений с принципиально иной вью логикой, не меняя код того, что у тебя вместо контроллеров. А только view. Судя по твоему описанию выходит что не очень, и нормально работает только собиралка кубиков аля битрикс
 

Ирокез

бессмертный пони
Команда форума
Партнер клуба
>> MHMVC
Хм. Ну может я как раз и о таком говорил. Надо понять, где что :)
Model - модель объекта, что под ним подразумевается, к примеру модель AdWords, организует доступ к API G.Adwords, модель User extentds SqlObject (по модному ActiveRecord)
Module - обеспечивает подготовку данных для View, используя либо не используя Model
Controller - связывает вид и модуль
View - активный шаблон (в узком пониманнии), попросту шаблон
Hierarchy - обеспечивает наследование и вызовы контроллеров, либо вызовы Module::Messages()->GetUserNotices();
 

AmdY

Пью пиво
Команда форума
Ирокез правильно заметил про заигрались в паттерны. Если человек утверждает что использует чистый MVC, я такому лишь посочувствую и покручу пальцем у виска.

У меня помимо всего ярко выделены Form и List, хотя можно их назвать более ёмким - виджеты(сервисы).

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

Ирокез

бессмертный пони
Команда форума
Партнер клуба
У меня помимо всего ярко выделены Form и List, хотя можно их назвать более ёмким - виджеты(сервисы).
возвращаясь к шаблонизаторам, да у меня есть предкопилирование php, разбираются специальные теги
<widget:tabs>..</widget:tabs> <block:aa>.. и прочие печенюшки
 

Absinthe

жожо
Активный шаблон (Pull-шаблон) -- шаблон, который включает в себя элементы языка программирования, такие как ветвление, циклы, включения и т. д. Активный Шаблон можно "выполнить", как обычную программу. В активном шаблоне легко управлять последовательностью выполнения блоков и их зависимостью друг от друга.

Пассивный шаблон (Push-шаблон) -- шаблон, содержащий лишь основные элементы форматирования страницы, однако не включающий информации, в каком порядке и количестве они должны быть выведены. Пассивный шаблон нельзя "запустить", он может быть только обработан некоторым контроллером, воспринимающим его, как обычный набор данных.
Вот именно такое определение я по книге и читал. И задавал вопрос месяца 2 назад.
Но на этом форуме под определение активных шаблонов пытаются лапшу подвести.
 

С.

Продвинутый новичок
Совершенно неверное определение. Ветвления и пр. управляющие структуру перпендикулярны (могут быть, а могут не быть) понятию активости/пассивности шаблона.

Отличительное свойство активного шаблона в том, что он танцует девушку. Если в шаблоне встречается некая управляюшая структура (напр. "вставить здесь 5 последних новостей"), то это запускает всю цепочку процессов через контролер и модель по добыче данных из базы, определению, какой под-шаблон будет вызван и т.п. То есть информация, заданная в шаблоне работает в двух направлениях: во-первых определяет, где что находится на странице, а во-вторых задает информацию контролеру, что нужно сделать.

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

Пассивные шаблоны работают хорошо в КМС узкой направленности, где спецификация страницы определена четко и практически никогда не меняется (форум, блог). Для фремворков общего назначения удобнее активные шаблоны.
 

Rin

*
fixxxer
да всякий опыт есть. Вопрос в том можешь ли ты реюзать то, что называешь Component. В том смысле, что использовать для _совсем_ других отображений с принципиально иной вью логикой, не меняя код того, что у тебя вместо контроллеров. А только view. Судя по твоему описанию выходит что не очень, и нормально работает только собиралка кубиков аля битрикс
Раз ты задаёшь такие вопросы, значит ты не понимаешь, как работает Model-View-Component и опыта у тебя нет.
Компонент ничего не знает про шаблоны, его дело только готовить данные и возвратить результат, поэтому один и тот же компонент может готовить данные для разных шаблонов.
 

Ирокез

бессмертный пони
Команда форума
Партнер клуба
Блин ну вот чисто интересно словоблудие, Model мне кажется синонимом Component,
Rin
что конкретно у тебя есть Model и Component
 

fixxxer

К.О.
Партнер клуба
Rin

Я нормальные вопросы задаю.

Возвращает данные? Куда?

Ок простой пример, как у тебя работает постраничная навигация?
 

Krishna

Продался Java
Ну просто разнес говнокод по кусочкам помельче. Вариант, конечно, если не хочется делать по нормальному ))

И не сбивай с толку. Я вот тоже могу везде писать MVC и потом говорить что это Milk Vanilla and Chocolate
Жгёшь, сотона!! :-D
 

Rin

*
>что конкретно у тебя есть Model и Component

Model -- база данных и классы для работы с ней
Component -- бизнес-логика

Выше об этом написано
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
прикол именно в том, что Model -- это не "база данных и классы для работы с ней" :)
это классы для обработки данных, а для работы с базой используются драйверы и маппинг

контроллеры в web dev обычно вырождаются во view controllers, потому что кроме определения параметров отрисовки им заниматься нечем
 

Rin

*
В качестве шаблонизатора у меня используется этот движок
Вот пример "скелета" View для схемы Model-View-Component.
PHP:
class App_View
{
	/**
	 * Путь из URL, например '/company/about/'
	 *
	 * @var string
	 */
	private $_path;

	/**
	 * Папка, где хранятся шаблоны
	 *
	 * @var string
	 */
	private $_dir;

	/**
	 * Объект приложения, который доступен из шаблонов как $app
	 *
	 * @var App|null
	 */
	private $_app;

	/**
	 *
	 * @param  string    $path  Путь из URL
	 * @param  string    $dir   Папка к шаблонам
	 * @param  App|null  $app   Объект приложения
	 */
	public function __construct($path, $dir, App $app = null)
	{
		$this->_path = $path;
		$this->_dir  = $dir;
		$this->_app  = $app;
	}

	/**
	 * Метод предназначен для вызова из шаблонов.
	 * Выполняет компонент и возвращает результат его работы.
	 *
	 * @param   string             $component_name     Название компонента.
	 * @param   array|null         $component_options  Ассоц. массив опций компонента.
	 * @param   string|null        $return_array_key   Если результат работы массив,
	 *                                                 то можно возвратить значение с заданным ключом.
	 *                                                 Если ключа не существует, возвратит NULL.
	 * @return  array|scalar|null  Returns FALSE if error occurred
	 */
	public function execute($component_name, array $component_options = null, $return_array_key = null)
	{
	}

	/**
	 * Метод предназначен для вызова из шаблонов.
	 * "Накладывает" данные (ассоц. массив) на шаблон.
	 * При этом переменные в шаблоне имеют локальную область видимости (в рамках шаблона).
	 * Зарезервированные имена в шаблонах:
	 *   $view -- объект App_View
	 *   $app  -- объект App
	 *
	 * @param   string             $template_name     Имя шаблона, расширение указывать не нужно
	 * @param   array|null         $template_options
	 * @return  string|array|bool  Returns FALSE if error occurred
	 */
	public function render($template_name, array $template_options = null)
	{
	}

	/**
	 * Метод предназначен для вызова из шаблонов.
	 * Комбинация self::execute() и self::render() в одном методе.
	 * Выполняет компонент, затем полученные от него данные подставляет в шаблон и возвращает результат работы.
	 * Если компонент возвращает не массив, то шаблон не используется и возвращается результат компонента.
	 *
	 * @param   string                  $component_name     Название компонента.
	 *                                                      Так же м. б. указано название шаблона после разделителя "|"
	 * @param   array|null              $component_options  Опции компонента.
	 * @param   string|null             $template_name
	 * @param   array|null              $template_options
	 * @return  string|array|bool|null  Returns FALSE if error occurred
	 */
	public function run($component_name,       array $component_options = null,
						$template_name = null, array $template_options  = null)
	{
	}

	/**
	 * Метод предназначен для вызова из шаблонов.
	 * Маршрутизатор, выполняет метод self::run() по условию.
	 *
	 * @param   string|bool|int|null    $mixed              Условие для выполнения метода self::run().
	 *                                                      string  Путь из URL или шаблон пути в виде рег. выражения.
	 *                                                              выполняется, если строка совпадает с текущим путём из URL
	 *                                                              выполняется, строка или регулярное выражение (например: '~^/games/[^/]++/~sSX') совпадает с текущим путём из URL
	 *                                                      int     > 0 выполняется, иначе нет
	 *                                                      bool    true -- выполняется, иначе нет
	 *                                                      null    не выполняется
	 * @param   string                  $component_name     Название компонента.
	 *                                                      Так же м. б. указано название шаблона после разделителя "|"
	 *                                                      Если $mixed это рег. выражение, то в названии компонента могут быть метки
	 *                                                      для замены захваченных подмасок на их значения, например: $0, $1, $2 ... $9
	 * @param   array|null              $component_options  Опции компонента.
	 * @param   string|null             $template_name      Название шаблона.
	 *                                                      Если $mixed это рег. выражение, то в названии шаблона могут быть метки
	 *                                                      для замены захваченных подмасок на их значения, например: $0, $1, $2 ... $9
	 * @param   array|null              $template_options   Опции шаблона.
	 * @return  string|array|bool|null  Returns FALSE if error occurred
	 */
	public function route($mixed,
						  $component_name,       array $component_options = null,
						  $template_name = null, array $template_options  = null)
	{
	}

}
Примеры использования:

Меню на всех страницах
<?=$view->run('page_children|page_menu_top', array('pid' => 2, 'depth' => 1))?>

Блок авторизации со ссылкой "Войти", на всех страницах, кроме страницы авторизации
<?=$view->route($url !== '/login/', 'auth_user|auth_user_layer')?>

На странице '/news/' список новостей с постраничным навигатором
<?=$view->route('/news/', 'rec_list|news_list', array('table' => 'news',
'o' => 'news_datetime desc', #поле сортировки
'p' => 0, #с какой записи выводить
'n' => 20, #сколько записей выводить
))?>

Пример кода постраничного навигатора, который хранится в отдельном файле-шаблоне (в этом примере вёрстка кривинькая)
PHP:
<? if (count($pages['slice']) > 1) : ?>
    <table cellpadding="0" cellspacing="0" style="margin: 15px 0 15px 0">
    <form>
    <tr>
        <td>Всего: <b><?=number_format($pages['total'])?></b></td>
        <td style="padding-left:5px">
            Страницы:
            <? if (! empty($pages['prev'])) : ?>
                <a href="<?=$pages['prev']['url']?>">&hellip;</a>
            <? endif ?>
      
            <? $app->setPageAttr('url_start', $pages['slice'][0]['url'], false) ?>
            <? foreach ($pages['slice'] as $i => $p) : ?>
                <? if ($p['is_cur']) : ?>
                    <?
                    if (array_key_exists($i + 1, $pages['slice'])) $app->setPageAttr('url_next', $pages['slice'][$i + 1]['url'], false);
                    if (array_key_exists($i - 1, $pages['slice'])) $app->setPageAttr('url_prev', $pages['slice'][$i - 1]['url'], false);
                    ?>
                    <span style="padding-left:2px; padding-right:2px;"><b><?=$p['n']?></b></span>
                <? else : ?>
                    <span style="padding-left:2px; padding-right:2px;"><a href="<?=$p['url']?>"><?=$p['n']?></a></span>
                <? endif ?>
            <? endforeach ?>
      
            <? if ($pages['next']) : ?>
                <a href="<?=$pages['next']['url']?>">&hellip;</a>
            <? endif ?>
        </td>
        
        <td style="padding-left:10px">Записей на страницу:</td>
        <td>
            <select style="font-size:11px" onChange="location.href = <?=HTML::quote(JSON::encode($_SERVER['REQUEST_URI'], "'"))?>.urlReplaceArg('n', this.value)">
                <? foreach (array(10, 20, 30, 60, 100, 200, 500, 1000) as $n) : ?>
                    <option value="<?=$n?>"<? if ($pages['count'] == $n) :?> selected="selected"<?endif?>><?=$n?></option>
                <? endforeach ?>
            </select>
        </td>
    </tr>
    </form>
    </table>
<? endif ?>

Вставка постраничной навигации
<?/* постраничная навигация вверху страницы */?>
<?=$pages = $view->render('_pages', array('pages' => $pages))?>
... здесь какой-то список записей
<?/* дублируем постраничную навигацию внизу страницы */?>
<?=$pages?>
 

Rin

*
grigori
прикол именно в том, что Model -- это не "база данных и классы для работы с ней"
это классы для обработки данных, а для работы с базой используются драйверы и маппинг
"база данных и классы для работы с ней" -- внутри как раз "классы для обработки данных", как Вы и пишите.
"драйверы и маппинг" -- это уже детали, которых может и не быть. Я, например, ORM не использую.
 

igortik

Новичок
Я для себя брал мысли отсюда Лучшая практика MVC
Жаль, что до сих пор нет единого рекомендованного стандарта, например, для Директорий, именно для стуктуры каталогов в самой системе, чтобы программист мог фактически без мануала понять что где лежит (как в unix, linux). Пытаясь, например, подружить свою систему с ZF приходится идти на поводу их структуры директорий с верхним регистром первой буквы каталога, чтобы Loader работал без проблем и можно было применять понятные неймспейсы с верхним регистром, например, $a = new Module\Index\Model\Index и т.д.

Почти каждый программист усложняет продукт, превращая три буквы MVC в нечто понятное лишь ему самому.
Кто пытается заставить главный исполняемый контроллер научить получать информацию о модулях на странице, когда эта роль явно отведена Активному шаблону и View с элементарным хелпером $this->controller($controller, $module) и т.д и чем плохо выполнение пхп кода в рамках php файла и декрипторов php ясно тоже лишь этому программисту.

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