Pull to refresh

Comments 34

UFO just landed and posted this here
Буковка V в аббревиатуре означает, что какой-либо контроллер загружает какое-либо представление. В случае коханы, кодигниттера и иже с ними представления можно включать в другие представления. Так, например, имея на сайте разделы (контроллеры) «мои жжшечки» и «ни о чем», обладающие одинаковыми, скажем, хидерами и футерами, но разным контентом, мы можем как создать два отдельных view под каждый раздел, так и один view-каркас, и два view-содержимых для, соответственно, бложиков и ниочем'а, и потом включать тело одно их них в карсас. Собственно, мой модуль и создан для того, чтобы упростить и автоматизировать сей процесс, сведя всё к «каркасу».
Да, штатной организации шаблонов в Кохане нет и это задача, с которой сталкивается любой, кто пишет на этом фреймворке. У меня вот такая затравка. Я её где-то нашел, не помню уже где, и слегка переделал под себя.
Да, знаю это решение, но оно показалось мне не достаточно полным и удобным)
Почему именно 3.1? Какие особенности используются?
А можно узнать (не работал с Kohana, я из мира ASP.NET MVC и Rails):
«Для модификации страницы можно использовать следующие конструкции в любом месте функций контроллера:… список...»

А почему такие строго View-related-штуки вообще должны использоваться в контроллере?
Ну как бы, MVC предполагает, что мы обращаемся к контроллеру, который загружает модель, работает с ней, и выдает нам конкретный View. Потому эта система шаблонизации загружает нужные представления, как любой другой контроллер, просто она делает это в нужные места)
Маленькое дополнение, все эти конструкции, в первую очередь, являются не выводящими контент, а накопителями, контент формируется уже после окончания работы экшена)
Ну, вот о том и речь — есть, к примеру, в этом списке, функции, типа «title», а то и куда «хлеще» — «add_style» или «add_script» — это же вещи, про которые контроллер, по идее, вообще не должен знать — ему все равно какие стили будут наложены, чтобы оформить данные, которые он готовит.
Здесь была выбрана реализация шаблонизатора контроллером, а не модулем, для того, чтобы облегчить наследование контроллеров. Когда мы наследует этот главный контроллер, мы получаем полный набор управляющих конструкций, за которыми не нужно следить. Точно так же, как у контроллера есть функции, скажем, after и before, различные add_style и другие добавляют лишь функционал.
А в случае реализации модулем, приходилось бы создавать инстанс модуля, пичкать его управляющими конструкциями, да и вообще, это было бы подключением лишнего класса, что не очень экономно. Хотя, не спорю, эту вещь можно легко переписать и под модуль, но я пока не встречал ни одного такого проекта)
Я не совсем в курсе, что такое модуль именно в кохановской архитектуре, но предполагаю, что слой View можно просто оформить отдельным слоем. И как по мне — это правильно.

«различные add_style и другие добавляют лишь функционал.»
Этот функционал надо бы добавлять как раз к слою, ответственному за View. Например, некий абстрактный ViewPage. У этого самого ViewPage может быть любое количество View-Helper-методов, строго для View-логики.

«А в случае реализации модулем, приходилось бы создавать инстанс модуля, пичкать его управляющими конструкциями, да и вообще, это было бы подключением лишнего класса.»
Нууу, что значит «лишнего класса»? Ведь вся суть MVC в SoC (Separation of Concerns), которая и обеспечивает проектам на этом паттерне такой высокий уровень «maintainability». А иначе, если так подумать — почему бы не запихать все в один класс, вообще всю систему — ведь иначе же «лишние классы, инстансы».
Ну, дописывать функционал самого VIEW, понятное дело, не стоит, ибо системный класс. Расширить его? Как вариант, конечно, но будет некоторая путаница. Единственным вариантом «прослойки» остается отдельный модуль, наполняющий и возвращающий определенный макет. В дальнейшем я планирую сделать две реализации: развить текущую, «контроллерную», и сделать модуль, а пока собираю полезные советы) В любом случае, спасибо за идеи, наталкиваете на мысли!)
Ну я просто исхожу как раз из того, как это сделано в ASP.NET MVC и RoR. В ASP.NET MVC именно что «из коробки» есть классы HtmlHelper, UrlHelper, AjaxHelper, к которым очень просто дописываются новые методы расширения. И (тада!) все эти хелперы являются свойствами объекта View. Полное разделение полномочий по уровням.

А в чем может быть путаница? По-моему, наоборот, все на своих местах :)
Нет, ну логично, я не спорю, в кохане тоже есть хэлперы (хотя уже и не в столь значимом варианте, как в предыдущих версиях). Просто до сих пор это не было связано в какую-либо систему для сайтов с изменяемым контентным содержимым и разделением на регионы) А я вот, под свои нужды, написал то, что было удобно) Хотя, судя по отзывам, идея должна жить, так что я буду ее развивать)
К слову — методы расширения (Extension Methods) — это концепт C#.NET, который активно используется в MVC. Но, как я и предполагал, для PHP можно крайне просто реализовать аналогичную штуку, используя немного рефлексии.

И разумеется, менять системные классы не нужно.
Ну то, что вы прислали, это как-то совсем жестко) Во всяком случае, в кохане это можно сделать чуть проще) Хотя и не далеко от вашего решения) Просто я хотел разделить обязанности, оставив view непосредственно для отображения контента, а свой контроллер для его накопления)
А как это можно сделать просто? Поскольку в PHP нет встроенного концепта Extension Methods — то без рефлексии никак :) А то, что я прислал — почему жестко то? 10 строк работы с рефлексией и вуаля — используем эти методы.

«Просто я хотел разделить обязанности, оставив view непосредственно для отображения контента, а свой контроллер для его накопления»

Ну я потому и зацепился за это, потому что мне кажется, что у вас контроллер делает больше, чем ему положено. А что значит «накопления»? Подготовка данных — да, однозначно, но (кроме непосредственно отображения) сборка View из кусков — это задача View-уровня.
Я написал чуточку ниже)
habrahabr.ru/blogs/webdev/116237/#comment_3774967

Если бы изначально структура view коханы предполагала такую глубокую работу с шаблоном — это было бы здорово) Но, увы, только сторонними штуками, ну то есть, встроенными в кохану, но по существу, не связанными непосредственно с представлениями)
Ага, понял, значит это все-таки, «by-design», решение самих создателей Коханы.
Да, скорее всего) Хотя, вроде как, ветку 3.1 вообще чуть ли не один человек тянет сейчас, так что не удивительно, что ему за всем не уследить!)
Кстати, про наследование контроллеров. Для чего оно вообще может быть нужно. Это какая-то фича HMVC?

Просто на практике MVC мы вообще избегаем базовых контроллеров (лишний layer-supertype как гвоздь в заднице :), а вся AOP-логика задается фильтрами (уверен, в Kohana обязана быть реализация паттерна Intercepting Filter в том или ином виде), данные же, не имеющие отношения к «основному» action-у — получаются через вызовы «RenderAction» во View.
Ну, быть может, в кохане какая-то своя реализация MVC) В кохане view представляет собой средство загрузки представлений, читай, файлов html (и не только) кода, внедрения в него переменных (присоединением или привязыванием) и рендер с целью возвращения чистого html из объекта. Утрированно, конечно, но в общем)

А контроллер служит для обработки запроса пользователя. Пришел к нам пользователь со ссылкой example.com/buy/milk, мы ему откроем контроллер buy, в котором запустим функцию action_milk, которая должна уже, используя $this->response->body( <что-то>) вернуть внутри «что-то» хоть представление, хоть чистый текст вроде пресловутого «123») Хотя контроллер представляет из себя обычный класс, и наследование в нем сделано, в частности, для расстановки по папкам.
Предположим, у вас есть контроллер «личный кабинет». В нем вам в любом случае надо опознать пользователя по его сессии (или кукам), загрузить общий шаблон страницы, ну и еще что-то. А внутри подпапочки «личный кабинет» есть контроллеры, скажем «фотография», «настройки» и «государственные тайны», которые, наследуясь от «личного кабинета», смогут, во первых, сразу получить доступ к переменной пользователя, заданной в родительском контроллере, а во вторых, уже будут иметь html-окружение, в которое могут вставить свой $content) Фух…
Ну, я понял, как это работает. Не уверен, правда, это в 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). И безо всякого наследования контроллеров.
Насколько мне известно, в кохане это не так развито, как у вас) Если интересно, вот ссылка на api по view: kohanaframework.org/3.1/guide/api/View

View коханы, по сути, только возвращает html. По существу, он никак не связан с контроллером, ибо вызываться может и в контроллере, и в другом view, и еще черт-те знает, где)
Ну, во-первых, 3.1 была выбрана потому, что хотелось ее изучить, сравнить с 3.0.
А во вторых, всё-таки, Kohana должна следовать принципам ООП, что реализовано в 3.1, в частности, в нормальной проверки на тип запроса функциями is_ajax(), is_initial() и других против прямого обращения к переменным 3.0. Мне показалось это… Приятнее)
А почему нет примера маленького контроллера и пары шаблончиков? было бы намного нагляднее, а так трудно что-то понять.
Почему же нету?) В папке классов лежит контроллер example с применением основный функций)
Как раз изучаю кохану, выглядит интересно.
Хорошо бы увидеть на каком-нибудь гитхабе и в виде модуля.
Макет (layout) не предполагает жесткое разделение на блоки (header, footer и т.д).
Его нужно использовать только тогда, когда несколько разных макетов, предполагают использование одни и тех же блоков.
Предлога вам строить мета теги через хелпер 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 запрос?
Ну, на счет макета, шаблонизатор не предполагает обязательное использование регионов, по умолчанию в нем важен только $content, так что он может загружать как блочные макеты, так и отдельные.
На счет implode, да, была такая мысль, но, по скольку в процессе написания шаблонизатора идеи возникали не меньше, чем до начала написания, то такая конструкция была сделана с целью предумсмотреть дальнейшую возможную обработку элементов)
На счет пары пейджера, согласен, логичнее было бы сделать вторую переменную необязательной)

А JSON код отдает, вот строчки:
if (! $this->request->is_initial() ) // Если запрос вызывается путем HMVC
elseif ($this->request->is_ajax() ) // Если запрос аяксом
else // Если обычный запрос
Не удобно, что нет layouts, приходится изощряться, а идею полностью поддерживаю.
А можно еще раз ссылку на файл — битая? Или уже на гит-хабе что-нибудь есть?
Sign up to leave a comment.

Articles

Change theme settings