Comments 29
на сколько я понял — для того, чтобы добавить в шаблон еще один компонент (модуль, объект) — необходимо править код?
Это не очень удобно по двум причинам:
1 — ну собственно при изменении шаблона нужно лезть в код
2 — если вы хотите, чтобы можно было использовать одновременно несколько шаблонов сайта (например, обычный вид и версия для печати, ну или мобильная версия) — в некоторых шаблонах не понадобится одни модули, в других — другие — не понятно, как это реализовать в вашей модели.
Это не очень удобно по двум причинам:
1 — ну собственно при изменении шаблона нужно лезть в код
2 — если вы хотите, чтобы можно было использовать одновременно несколько шаблонов сайта (например, обычный вид и версия для печати, ну или мобильная версия) — в некоторых шаблонах не понадобится одни модули, в других — другие — не понятно, как это реализовать в вашей модели.
0
Если все-таки создать класс для простого отображения переменной, то можно избежать использование лишнего массива и метода… К тому же в такой класс можно добавить escape и другие функции для чистки вывода.
$page->fillings['title'] = new VariableView('greating');
0
У вас в коде по крайней мере одна очень большая проблема:
fillings не типизируются — код не может гарантировать, что в этом массиве будут объекты, реализующие метод draw. Вам нужно сделать fillings защищенным или приватным свойством и реализовать метод add для добавления View с указанием типа агрумента. Не очень хочется давать ссылку на википедию, но всё же посмотрите.
Думаю, вам нужно что-то вроде этого, если я не ошибаюсь, конечно ;):
fillings не типизируются — код не может гарантировать, что в этом массиве будут объекты, реализующие метод draw. Вам нужно сделать fillings защищенным или приватным свойством и реализовать метод add для добавления View с указанием типа агрумента. Не очень хочется давать ссылку на википедию, но всё же посмотрите.
Думаю, вам нужно что-то вроде этого, если я не ошибаюсь, конечно ;):
abstract class AbstractView {
/**
* @var AbstractView[]
*/
protected $views = array();
abstract function draw();
/**
* @param string $key
* @param AbstractView $view
*/
public function addView($key, AbstractView $view) {
$this->views[(string)$key] = $view;
}
/**
* Рендерит отображение
*
* @param string $key
*
* @return string
* @throws InvalidArgumentException
*/
final public function render($key) {
$key = (string)$key;
if (!isset($this->views[$key]))
throw new InvalidArgumentException('Представление по ключу '.$key.' не найдено');
ob_start();
$this->views[$key]->draw();
return ob_get_clean();
}
}
class LayoutView extends AbstractView {
function draw() {
/* ваш код */
}
}
class SubView extends AbstractView {
function draw() {
/* ваш код */
}
}
$view = new LayoutView();
$subView = new SubView();
$view->addView('content', $subView);
echo $view->render('content');
+3
Да, вторая не очень хорошая на мой взгляд вещь:
А что будет, если вы случайно опечатались, вводя имя ключа? Правильно — ничего. Возможно вы или что-то еще будете долго дебажить код в поисках того, почему ваша программа не печатает вьюшку. Игнорирование ошибок — плохая практика.
if(isset($this->fillings[$filling_name])){
$this->fillings[$filling_name]->draw();
}
А что будет, если вы случайно опечатались, вводя имя ключа? Правильно — ничего. Возможно вы или что-то еще будете долго дебажить код в поисках того, почему ваша программа не печатает вьюшку. Игнорирование ошибок — плохая практика.
0
К сожалению комментарий не поправить — пропустил модификаторы доступа к методам draw в наследниках.
0
Лучше выкладывать не код, а ссылку на код на пастбине или другом подобном сайте.
+1
С замечанием относительно типовой небезопасности моего кода согласен. Не думаю, что стоит кидать исключение при отсутствии какого-либо объекта (нет — и не надо). То лично мне и удобно, что можно разметить фрагмент html кода в методе draw(), указав, где- что находится, а потом уже реализовывать постепенно эти днтали. Хотя это дело вкуса на мой взгляд.
Не понял вас:
Может вы имели ввиду:
Не понял вас:
echo $view->render('content');
Может вы имели ввиду:
echo $view->draw();
?0
echo $view->render('content');
это уже непосредственно вставка html — аналог вашего insert0
Мне кажется вы не совсем меня поняли.
Вызов меня поняли: html-код выводится только в методе draw путем инклуда файла .phtml, который по сути является шаблоном, включающем вызовы метода insert('view_name'), который вызывает метод draw() для объекта типа AbstractView, содержащегося в масиве $fillings под ключем 'value name'.
Вызов меня поняли: html-код выводится только в методе draw путем инклуда файла .phtml, который по сути является шаблоном, включающем вызовы метода insert('view_name'), который вызывает метод draw() для объекта типа AbstractView, содержащегося в масиве $fillings под ключем 'value name'.
0
Так, а у самого $view(который экземпляр LayoutView) draw() не вызовется же? или я что то не понял?
0
Идея неплохая, но реализация слабовата. Здесь можно абстрагироваться полностью и ввести стандартное дерево HTML:
- Root
- Head
- Link
- Meta
- Head
- Body
- myheader
- my menu
- mycontent
- myheader
Есть какая-то стандартная реализация элементов Root, Head, Body, которая слабо зависит от какой-то конкретной темы. В узел Head можно легко добавлять необходимые элементы, как и в любой другой. Элементы my* являются уже специфичными, но из них вполне можно выделить часто встречающиеся типы (такие как меню, заголовок, хлебные крошки), функционал которых можно вынести в отдельный класс, а представление — в конкретный, зависящий от каких-то условий.
Самое интересное, что такую систему можно реализовать на основе паттерна Абстрактная фабрика и вообще абстрагироваться от HTML. Тогда можно будет легко перевести сайт с отображения на HTML5 в отображение XML.
0
Немного не в тему. Но я сделал проще используя шаблонизатор blitz унаследовался от него, создал метод call в итоге в любом месте на страничке я могу сделать {{ call('Class','method')}} ну и собственно все. Отдельный «пакет» Widgets реализует необходимый вывод в необходимых местах =) удобно и не надо заморачиваться с layouts. Впрочем у меня есть генератор страниц Page который выводит основной контент по умолчанию. За счет такой гибкости я могу быстро на разных страницах выводить разные виджеты, все что нужно сделать новый шаблон страницы и подключить его на этапе формирования View-а страницы.
Как-то так =)
Как-то так =)
+1
Кстати эта идея у меня крутилась в голове, но в таком формате:
Есть результат выполнения затребованного пользователем действия Controller->action(), он вставляется в определенное место в шаблоне. Но в любой шабло, не важно, к какому классу View, он относится, можно вставлять виджеты, представленные вызовом метода какого либо класса виджетов. Это действительно удобно. Например я всегда хочу видеть справа чат. Вместо того, чтобы постоянно подключать его в layout, я могу вызывать метод класса виджета. Для этого надо описать еще один класс, методы которого, этим вызовом и будут заниматься. И в этом классе регистрировать список всех доступных виджетов. Назовем его WidgetMaster. Тогда в .phtml-шаблонах вставлять для виджетов, например метод WidgetMaster->call('name'). Но допустим, некоторые виджеты должны иметь средства для управления ими… было бы глупо перезагружать страницу из-за виджета. Это можно организовать через Ajax несложно и не нарушая архитектуры приложения. Ничего из этого еще не реализовывал, но могу написать отдельный топик, посвещенный этой теме, когда реализую.
Есть результат выполнения затребованного пользователем действия Controller->action(), он вставляется в определенное место в шаблоне. Но в любой шабло, не важно, к какому классу View, он относится, можно вставлять виджеты, представленные вызовом метода какого либо класса виджетов. Это действительно удобно. Например я всегда хочу видеть справа чат. Вместо того, чтобы постоянно подключать его в layout, я могу вызывать метод класса виджета. Для этого надо описать еще один класс, методы которого, этим вызовом и будут заниматься. И в этом классе регистрировать список всех доступных виджетов. Назовем его WidgetMaster. Тогда в .phtml-шаблонах вставлять для виджетов, например метод WidgetMaster->call('name'). Но допустим, некоторые виджеты должны иметь средства для управления ими… было бы глупо перезагружать страницу из-за виджета. Это можно организовать через Ajax несложно и не нарушая архитектуры приложения. Ничего из этого еще не реализовывал, но могу написать отдельный топик, посвещенный этой теме, когда реализую.
0
Хочу понять вот что. Получается, что у вас в MVC появляется четвертый компонент?
Ну, то есть, теперь вид — не просто шаблон, а класс, который собирает HTML из шаблонов, так?
То есть, стандартным образом воспользоваться таким решением из MVC фреймверков не получится, точнее нужно будет заменить механизм видов на ваш механизм, правильно понимаю?
То есть, если например в CodeIgniter мы пишем что-то в стиле
$this->load->view('blogview', $data);
то тут эта конструкция будет заключена где-то в глубинах вашего объекта вида. Правильно?
Ну, то есть, теперь вид — не просто шаблон, а класс, который собирает HTML из шаблонов, так?
То есть, стандартным образом воспользоваться таким решением из MVC фреймверков не получится, точнее нужно будет заменить механизм видов на ваш механизм, правильно понимаю?
То есть, если например в CodeIgniter мы пишем что-то в стиле
$this->load->view('blogview', $data);
то тут эта конструкция будет заключена где-то в глубинах вашего объекта вида. Правильно?
0
Во многих фреймворках View — это класс. В зенде, например, вью вызывается в dispatch цикле после отработки контроллера. Цикл обработки zend. Это довольно гибкое решение, можно с легкостью менять типы ответа(xml,json) просто заменив один из элементов view.
+1
Да, вы правильно понимаете. Но у меня и не было цели интегрировать мой механизм видов в какой-либо существующий фреймворк. Это механизм видов из моего простенького фреймворка. Прошу не кричать, что самописные фреймворки никто уже не пишет. Я его пишу по филосовским соображениям, дабы глубже понять идеи существующих.
0
А почему не PHP > (XML + XSLT) > HTML?
0
Sign up to leave a comment.
Реализация паттерна Компоновщик (Composite pattern) на php