Комментарии 34
НЛО прилетело и опубликовало эту надпись здесь
Буковка V в аббревиатуре означает, что какой-либо контроллер загружает какое-либо представление. В случае коханы, кодигниттера и иже с ними представления можно включать в другие представления. Так, например, имея на сайте разделы (контроллеры) «мои жжшечки» и «ни о чем», обладающие одинаковыми, скажем, хидерами и футерами, но разным контентом, мы можем как создать два отдельных view под каждый раздел, так и один view-каркас, и два view-содержимых для, соответственно, бложиков и ниочем'а, и потом включать тело одно их них в карсас. Собственно, мой модуль и создан для того, чтобы упростить и автоматизировать сей процесс, сведя всё к «каркасу».
+1
Да, штатной организации шаблонов в Кохане нет и это задача, с которой сталкивается любой, кто пишет на этом фреймворке. У меня вот такая затравка. Я её где-то нашел, не помню уже где, и слегка переделал под себя.
0
Почему именно 3.1? Какие особенности используются?
+1
А можно узнать (не работал с Kohana, я из мира ASP.NET MVC и Rails):
«Для модификации страницы можно использовать следующие конструкции в любом месте функций контроллера:… список...»
А почему такие строго View-related-штуки вообще должны использоваться в контроллере?
«Для модификации страницы можно использовать следующие конструкции в любом месте функций контроллера:… список...»
А почему такие строго View-related-штуки вообще должны использоваться в контроллере?
+3
Ну как бы, MVC предполагает, что мы обращаемся к контроллеру, который загружает модель, работает с ней, и выдает нам конкретный View. Потому эта система шаблонизации загружает нужные представления, как любой другой контроллер, просто она делает это в нужные места)
0
Маленькое дополнение, все эти конструкции, в первую очередь, являются не выводящими контент, а накопителями, контент формируется уже после окончания работы экшена)
0
Ну, вот о том и речь — есть, к примеру, в этом списке, функции, типа «title», а то и куда «хлеще» — «add_style» или «add_script» — это же вещи, про которые контроллер, по идее, вообще не должен знать — ему все равно какие стили будут наложены, чтобы оформить данные, которые он готовит.
+2
Здесь была выбрана реализация шаблонизатора контроллером, а не модулем, для того, чтобы облегчить наследование контроллеров. Когда мы наследует этот главный контроллер, мы получаем полный набор управляющих конструкций, за которыми не нужно следить. Точно так же, как у контроллера есть функции, скажем, after и before, различные add_style и другие добавляют лишь функционал.
А в случае реализации модулем, приходилось бы создавать инстанс модуля, пичкать его управляющими конструкциями, да и вообще, это было бы подключением лишнего класса, что не очень экономно. Хотя, не спорю, эту вещь можно легко переписать и под модуль, но я пока не встречал ни одного такого проекта)
А в случае реализации модулем, приходилось бы создавать инстанс модуля, пичкать его управляющими конструкциями, да и вообще, это было бы подключением лишнего класса, что не очень экономно. Хотя, не спорю, эту вещь можно легко переписать и под модуль, но я пока не встречал ни одного такого проекта)
0
Я не совсем в курсе, что такое модуль именно в кохановской архитектуре, но предполагаю, что слой View можно просто оформить отдельным слоем. И как по мне — это правильно.
«различные add_style и другие добавляют лишь функционал.»
Этот функционал надо бы добавлять как раз к слою, ответственному за View. Например, некий абстрактный ViewPage. У этого самого ViewPage может быть любое количество View-Helper-методов, строго для View-логики.
«А в случае реализации модулем, приходилось бы создавать инстанс модуля, пичкать его управляющими конструкциями, да и вообще, это было бы подключением лишнего класса.»
Нууу, что значит «лишнего класса»? Ведь вся суть MVC в SoC (Separation of Concerns), которая и обеспечивает проектам на этом паттерне такой высокий уровень «maintainability». А иначе, если так подумать — почему бы не запихать все в один класс, вообще всю систему — ведь иначе же «лишние классы, инстансы».
«различные add_style и другие добавляют лишь функционал.»
Этот функционал надо бы добавлять как раз к слою, ответственному за View. Например, некий абстрактный ViewPage. У этого самого ViewPage может быть любое количество View-Helper-методов, строго для View-логики.
«А в случае реализации модулем, приходилось бы создавать инстанс модуля, пичкать его управляющими конструкциями, да и вообще, это было бы подключением лишнего класса.»
Нууу, что значит «лишнего класса»? Ведь вся суть MVC в SoC (Separation of Concerns), которая и обеспечивает проектам на этом паттерне такой высокий уровень «maintainability». А иначе, если так подумать — почему бы не запихать все в один класс, вообще всю систему — ведь иначе же «лишние классы, инстансы».
+1
Ну, дописывать функционал самого VIEW, понятное дело, не стоит, ибо системный класс. Расширить его? Как вариант, конечно, но будет некоторая путаница. Единственным вариантом «прослойки» остается отдельный модуль, наполняющий и возвращающий определенный макет. В дальнейшем я планирую сделать две реализации: развить текущую, «контроллерную», и сделать модуль, а пока собираю полезные советы) В любом случае, спасибо за идеи, наталкиваете на мысли!)
0
Ну я просто исхожу как раз из того, как это сделано в ASP.NET MVC и RoR. В ASP.NET MVC именно что «из коробки» есть классы HtmlHelper, UrlHelper, AjaxHelper, к которым очень просто дописываются новые методы расширения. И (тада!) все эти хелперы являются свойствами объекта View. Полное разделение полномочий по уровням.
А в чем может быть путаница? По-моему, наоборот, все на своих местах :)
А в чем может быть путаница? По-моему, наоборот, все на своих местах :)
+1
Нет, ну логично, я не спорю, в кохане тоже есть хэлперы (хотя уже и не в столь значимом варианте, как в предыдущих версиях). Просто до сих пор это не было связано в какую-либо систему для сайтов с изменяемым контентным содержимым и разделением на регионы) А я вот, под свои нужды, написал то, что было удобно) Хотя, судя по отзывам, идея должна жить, так что я буду ее развивать)
0
К слову — методы расширения (Extension Methods) — это концепт C#.NET, который активно используется в MVC. Но, как я и предполагал, для PHP можно крайне просто реализовать аналогичную штуку, используя немного рефлексии.
И разумеется, менять системные классы не нужно.
И разумеется, менять системные классы не нужно.
+1
Ну то, что вы прислали, это как-то совсем жестко) Во всяком случае, в кохане это можно сделать чуть проще) Хотя и не далеко от вашего решения) Просто я хотел разделить обязанности, оставив view непосредственно для отображения контента, а свой контроллер для его накопления)
0
А как это можно сделать просто? Поскольку в PHP нет встроенного концепта Extension Methods — то без рефлексии никак :) А то, что я прислал — почему жестко то? 10 строк работы с рефлексией и вуаля — используем эти методы.
«Просто я хотел разделить обязанности, оставив view непосредственно для отображения контента, а свой контроллер для его накопления»
Ну я потому и зацепился за это, потому что мне кажется, что у вас контроллер делает больше, чем ему положено. А что значит «накопления»? Подготовка данных — да, однозначно, но (кроме непосредственно отображения) сборка View из кусков — это задача View-уровня.
«Просто я хотел разделить обязанности, оставив view непосредственно для отображения контента, а свой контроллер для его накопления»
Ну я потому и зацепился за это, потому что мне кажется, что у вас контроллер делает больше, чем ему положено. А что значит «накопления»? Подготовка данных — да, однозначно, но (кроме непосредственно отображения) сборка View из кусков — это задача View-уровня.
+1
Я написал чуточку ниже)
habrahabr.ru/blogs/webdev/116237/#comment_3774967
Если бы изначально структура view коханы предполагала такую глубокую работу с шаблоном — это было бы здорово) Но, увы, только сторонними штуками, ну то есть, встроенными в кохану, но по существу, не связанными непосредственно с представлениями)
habrahabr.ru/blogs/webdev/116237/#comment_3774967
Если бы изначально структура view коханы предполагала такую глубокую работу с шаблоном — это было бы здорово) Но, увы, только сторонними штуками, ну то есть, встроенными в кохану, но по существу, не связанными непосредственно с представлениями)
0
Кстати, про наследование контроллеров. Для чего оно вообще может быть нужно. Это какая-то фича HMVC?
Просто на практике MVC мы вообще избегаем базовых контроллеров (лишний layer-supertype как гвоздь в заднице :), а вся AOP-логика задается фильтрами (уверен, в Kohana обязана быть реализация паттерна Intercepting Filter в том или ином виде), данные же, не имеющие отношения к «основному» action-у — получаются через вызовы «RenderAction» во View.
Просто на практике MVC мы вообще избегаем базовых контроллеров (лишний layer-supertype как гвоздь в заднице :), а вся AOP-логика задается фильтрами (уверен, в Kohana обязана быть реализация паттерна Intercepting Filter в том или ином виде), данные же, не имеющие отношения к «основному» action-у — получаются через вызовы «RenderAction» во View.
+1
Ну, быть может, в кохане какая-то своя реализация MVC) В кохане view представляет собой средство загрузки представлений, читай, файлов html (и не только) кода, внедрения в него переменных (присоединением или привязыванием) и рендер с целью возвращения чистого html из объекта. Утрированно, конечно, но в общем)
А контроллер служит для обработки запроса пользователя. Пришел к нам пользователь со ссылкой example.com/buy/milk, мы ему откроем контроллер buy, в котором запустим функцию action_milk, которая должна уже, используя $this->response->body( <что-то>) вернуть внутри «что-то» хоть представление, хоть чистый текст вроде пресловутого «123») Хотя контроллер представляет из себя обычный класс, и наследование в нем сделано, в частности, для расстановки по папкам.
Предположим, у вас есть контроллер «личный кабинет». В нем вам в любом случае надо опознать пользователя по его сессии (или кукам), загрузить общий шаблон страницы, ну и еще что-то. А внутри подпапочки «личный кабинет» есть контроллеры, скажем «фотография», «настройки» и «государственные тайны», которые, наследуясь от «личного кабинета», смогут, во первых, сразу получить доступ к переменной пользователя, заданной в родительском контроллере, а во вторых, уже будут иметь html-окружение, в которое могут вставить свой $content) Фух…
А контроллер служит для обработки запроса пользователя. Пришел к нам пользователь со ссылкой example.com/buy/milk, мы ему откроем контроллер buy, в котором запустим функцию action_milk, которая должна уже, используя $this->response->body( <что-то>) вернуть внутри «что-то» хоть представление, хоть чистый текст вроде пресловутого «123») Хотя контроллер представляет из себя обычный класс, и наследование в нем сделано, в частности, для расстановки по папкам.
Предположим, у вас есть контроллер «личный кабинет». В нем вам в любом случае надо опознать пользователя по его сессии (или кукам), загрузить общий шаблон страницы, ну и еще что-то. А внутри подпапочки «личный кабинет» есть контроллеры, скажем «фотография», «настройки» и «государственные тайны», которые, наследуясь от «личного кабинета», смогут, во первых, сразу получить доступ к переменной пользователя, заданной в родительском контроллере, а во вторых, уже будут иметь html-окружение, в которое могут вставить свой $content) Фух…
0
Ну, я понял, как это работает. Не уверен, правда, это в Kohana так что называет «by design» или это вы так используете.
А нет ли какой-то системы layout'ов?
Мне очень логичной кажется схема в ASP.NET MVC, которая идет прямиком из Rails — если нужно отрендерить HTML, то Action контроллера возвращает ActionResult специального типа (ViewResult), этот результат ищет нужный View в папке, загружает его и выполняет всю View-логику (шаблонизатора), включая расстановку переменных в нужные места.
Вся суть в системе layout'ов — у View назначен собственный layout. В этом layout есть директива шаблонизатора вроде «RenderBody», куда и вставляется тот View, что получился в результате работы Action-а контроллера (таким образом, один и тот же layout может быть использован несколькими View). Но это не все — как layout, так и сам View, могут содержать директивы «RenderAction» (с указанием того, какой именно контроллер и какой Action должен отработать) — вместо этих директив будут «вставлены» результаты работы этих контроллеров. Вот с помощью этих штуковин (RenderBody, RenderAction, ну плюс еще RenderPartial и RenderSection) получается, что можно сделать все, что угодно, переиспользовать как угодно, и не повторяться (aka DRY principle). И безо всякого наследования контроллеров.
А нет ли какой-то системы layout'ов?
Мне очень логичной кажется схема в ASP.NET MVC, которая идет прямиком из Rails — если нужно отрендерить HTML, то Action контроллера возвращает ActionResult специального типа (ViewResult), этот результат ищет нужный View в папке, загружает его и выполняет всю View-логику (шаблонизатора), включая расстановку переменных в нужные места.
Вся суть в системе layout'ов — у View назначен собственный layout. В этом layout есть директива шаблонизатора вроде «RenderBody», куда и вставляется тот View, что получился в результате работы Action-а контроллера (таким образом, один и тот же layout может быть использован несколькими View). Но это не все — как layout, так и сам View, могут содержать директивы «RenderAction» (с указанием того, какой именно контроллер и какой Action должен отработать) — вместо этих директив будут «вставлены» результаты работы этих контроллеров. Вот с помощью этих штуковин (RenderBody, RenderAction, ну плюс еще RenderPartial и RenderSection) получается, что можно сделать все, что угодно, переиспользовать как угодно, и не повторяться (aka DRY principle). И безо всякого наследования контроллеров.
0
Насколько мне известно, в кохане это не так развито, как у вас) Если интересно, вот ссылка на api по view: kohanaframework.org/3.1/guide/api/View
View коханы, по сути, только возвращает html. По существу, он никак не связан с контроллером, ибо вызываться может и в контроллере, и в другом view, и еще черт-те знает, где)
View коханы, по сути, только возвращает html. По существу, он никак не связан с контроллером, ибо вызываться может и в контроллере, и в другом view, и еще черт-те знает, где)
0
Ну, во-первых, 3.1 была выбрана потому, что хотелось ее изучить, сравнить с 3.0.
А во вторых, всё-таки, Kohana должна следовать принципам ООП, что реализовано в 3.1, в частности, в нормальной проверки на тип запроса функциями is_ajax(), is_initial() и других против прямого обращения к переменным 3.0. Мне показалось это… Приятнее)
А во вторых, всё-таки, Kohana должна следовать принципам ООП, что реализовано в 3.1, в частности, в нормальной проверки на тип запроса функциями is_ajax(), is_initial() и других против прямого обращения к переменным 3.0. Мне показалось это… Приятнее)
+1
А почему нет примера маленького контроллера и пары шаблончиков? было бы намного нагляднее, а так трудно что-то понять.
+1
Как раз изучаю кохану, выглядит интересно.
Хорошо бы увидеть на каком-нибудь гитхабе и в виде модуля.
Хорошо бы увидеть на каком-нибудь гитхабе и в виде модуля.
0
Макет (layout) не предполагает жесткое разделение на блоки (header, footer и т.д).
Его нужно использовать только тогда, когда несколько разных макетов, предполагают использование одни и тех же блоков.
Предлога вам строить мета теги через хелпер HTML::attributes() и ссылки через HTML::anchor()
Конструкцию
Можно заменить на
Рекомендую исправить такие недочеты как:
Насколько я понял ваш класс не рассчитан отдавать JSON на AJAX запрос?
Его нужно использовать только тогда, когда несколько разных макетов, предполагают использование одни и тех же блоков.
Предлога вам строить мета теги через хелпер HTML::attributes() и ссылки через HTML::anchor()
Конструкцию
foreach ($this->scripts as $scripts)
{
$html .= $script."\n";
}
Можно заменить на
$html = implode("\n", $this->scripts)."\n";
Рекомендую исправить такие недочеты как:
$this->pager_pair(1,'1')
Насколько я понял ваш класс не рассчитан отдавать JSON на AJAX запрос?
+1
Ну, на счет макета, шаблонизатор не предполагает обязательное использование регионов, по умолчанию в нем важен только $content, так что он может загружать как блочные макеты, так и отдельные.
На счет implode, да, была такая мысль, но, по скольку в процессе написания шаблонизатора идеи возникали не меньше, чем до начала написания, то такая конструкция была сделана с целью предумсмотреть дальнейшую возможную обработку элементов)
На счет пары пейджера, согласен, логичнее было бы сделать вторую переменную необязательной)
А JSON код отдает, вот строчки:
if (! $this->request->is_initial() ) // Если запрос вызывается путем HMVC
elseif ($this->request->is_ajax() ) // Если запрос аяксом
else // Если обычный запрос
На счет implode, да, была такая мысль, но, по скольку в процессе написания шаблонизатора идеи возникали не меньше, чем до начала написания, то такая конструкция была сделана с целью предумсмотреть дальнейшую возможную обработку элементов)
На счет пары пейджера, согласен, логичнее было бы сделать вторую переменную необязательной)
А JSON код отдает, вот строчки:
if (! $this->request->is_initial() ) // Если запрос вызывается путем HMVC
elseif ($this->request->is_ajax() ) // Если запрос аяксом
else // Если обычный запрос
0
Не удобно, что нет layouts, приходится изощряться, а идею полностью поддерживаю.
0
А можно еще раз ссылку на файл — битая? Или уже на гит-хабе что-нибудь есть?
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Универсальная шаблонизация для Kohana 3.1