Помогите разобраться. Стандарными средствами шаблоны ищутся в 2-х местах: 1) app/Resource/MyBundle/view/ 2) src/MyBundle/Resources/view/ Если не указать имя бандла, тогда подгружаться шаблон будет из: app/Resources/view/. Вопросы следующие: 1) Возможно ли динамически, например в зависимости от домена, переопределить основной путь к шаблонам? например в app/site.com/Resources/view/ 2) Возможно ли добавить еще один путь для поиска шаблонов, притом по приоритету выше, чем основной в app/*, например для того чтобы реализовать темы оформления, например app/site.com/Resources/theme/default/view/ 3) Возможно ли научить метод $this->render(); понимать еще и другие форматы указания шаблона? т.е. помимо формата 'MyBundle:ControllerName:tpl.html.twig' и 'MyBundle::tpl.html.twig', можно было еще указать что-то вроде 'Acme/Menu::tpl.html.twig' и в этом случае Acme/Menu будет ссылаться на путь, например такой: app/site.com/Resources/theme/default/modules/Acme/Menu/view/, разумеется если в этом пути шаблона не будет, то он будет подгружен из папки самого «модуля», например src/Acme/Modules/Menu/Resources/view/ т.е. получится следующий приоритет поиска шаблонов, заданных таким образом '::tpl.html.twig': 1) app/site.com/Resources/theme/default/view/ 2) app/site.com/Resources/view/ разумеется подобный формат ':some/path:tpl.html.twig' будет ссылаться на: 1) app/site.com/Resources/theme/default/view/some/path/ 2) app/site.com/Resources/view/some/path/ а шаблоны заданные в виде 'Acme/Menu::tpl.html.twig', будут искаться в следующих местах: 1) app/site.com/Resources/theme/default/modules/Acme/Menu/view/ 2) app/site.com/Resources/modules/Acme/Menu/view/ 3) src/Acme/Modules/Menu/Resources/view/ Пщупал, LiipThemeBundle - работает, но нужно его научить еще нескольким вещам: 1) в связи с тем что site_id можно получить только динамически $container->get('engine.site')->getId(), попробовал залесть в конструктор класса Liip\ThemeBundle\Locator\FileLocator и там подкорректировать $this->path, чтобы в итоге получался путь для разных сайтов вида /app/Resources/sites/{site_id}, разумеется при первом запуске, при построении кеша контейнера вываливается ошибка: «Whoops, looks like something went wrong. InactiveScopeException: You cannot create a service ("request") of an inactive scope ("request").» но при последующих запусках в принципе работает но это конечно не «symfony way»... отсюда вопрос, в каком месте можно динамически сформировать путь для поиска шаблонов? 2) в LiipThemeBundle список всех возможных тем необходимо указывать в конфиге, как можно формировать этот список динамически? список всех доступных тем также доступны через сервис $container->get('engine.site')->getThemes();
решение найдено! Суть заключалась в следующем: Liip создаёт параметр liip_theme.file_locator.class в котором задаётся имя класса, с файл-локатором, так вот в ДИ нашего бандла в экстеншене надо просто подменить этот параметр на имя нашего класса, притом его описание предельно простое Код (PHP): <?php namespace SmartCore\Bundle\EngineBundle\Locator; use Liip\ThemeBundle\Locator\FileLocator as BaseFileLocator; class MultisitesFileLocator extends BaseFileLocator { public function locateAppResource($name, $dir = null, $first = true) { if ($this->kernel->getContainer()->getParameter('smart_core_engine.dir_sites') !== '') { $dir = $this->kernel->getContainer()->getParameter('kernel.root_dir') . '/' . $this->kernel->getContainer()->getParameter('smart_core_engine.dir_sites') . $this->kernel->getContainer()->get('engine.site')->getId() . '/Resources'; } return parent::locateAppResource($name, $dir, $first); } } получилось правда ограничение, без Liip мультсайтовость неработает... но это не страшно Также был решен вопрос с динамическим списком доступных тем в Liip в классе ActiveTheme есть метод setThemes(), который можно юзать динамически
Апельсин, нет йии категорически не интересует подождём когда Yii2 выйдет, если там уберут статику, префикс С, и компоненты будут мало связные и соответствовать PSR-0, то можно будет юзать, если там дейсвительно что-то уникально ценное будет на счет дикости кода, это я просто поленился чуть чуть вот так красивее будет в этом случае: Код (PHP): <?php namespace SmartCore\Bundle\EngineBundle\Locator; use Liip\ThemeBundle\Locator\FileLocator as BaseFileLocator; class MultisitesFileLocator extends BaseFileLocator { public function locateAppResource($name, $dir = null, $first = true) { $container = $this->kernel->getContainer(); if ($container->getParameter('smart_core_engine.dir_sites') !== '') { $dir = $container->getParameter('kernel.root_dir') . '/' . $container->getParameter('smart_core_engine.dir_sites') . $container->get('engine.site')->getId() . '/Resources'; } return parent::locateAppResource($name, $dir, $first); } }
бида! Для таких недокодеров как я это прям китайская грамота. Но я уверен, что тут на вопрос "а что же он делает" можно ответить парой слов?
igordata, самокритика это хорошо ) ну а так если по русьске сказать, то "если у нас задан параметр smart_core_engine.dir_sites, тогда мы подменяем переменную $dir на другой путь" всё для людей незнакомых с современными трендами и паттернами программирования и проектирования может оказаться непонятным понятие "Контейнер", здесь можно погуглить по словам IoC, Dependency Injection, Service Container... также если смотреть именно в сторону симфони2, тогда вот тут дока есть http://symfony-gu.ru/documentation/ru/html/book/service_container.html , также из очень лёгких реализаций контейенра, можно глянуть на проект Pimple (https://github.com/fabpot/Pimple).
блин, вот честно - жуть какая, что-то как-то не очевидно это происходит или после коханы так страшно смотрится
угу, пока не разберешся может показаться некоторая неочевидность а вообще да, симфони2 с наскоку не осваевается ( тут никуда не деться... кохану смотрел, но ничего интересного для себя не нашел, а её стандарты кодирования мне ломали глаза %)
А Yii framework? Symfony не использовал, но по слухам он не очень удобный плюс громоздкий... А почему ты выбрал именно его???
smitt, всё смотрел и yii разумеется тоже, притом намного раньше чем сф2 но проникся симфони я только после уроков от Фабиена (http://fabien.potencier.org/article/50/create-your-own-fram ... nts-part-1 тут цикл из 12 статей), они позволяют на самом низком уровне понять как работают компоненты. сам же симфони, который позиционируется как фреймворк, это собственно всего навсего один бандл ("пакет" или "модуль" если говорить более по русски ) https://github.com/symfony/symfony/tree/master/src/Symfony/ ... workBundle, который разумеется юзает эти самые компоненты, которые описал Фабиен. слухов про неудобность я сам ниразу не слышал... громоздкость у него скажем так - "умеренная" ) встроенные средства разнопланового кеширования позволяют добиться очень приличных показателей производительности! или вы не производительсть имеете ввиду под громоздкостью? выбрал, потому что после изучения, понял, что это именно то, что мне нужно! современный, очень активно развивается, красивая работа с БД, притом ОРМ можно не юзать, а можно юзать контейнер сервисов вообще гениальная штука! до сих пор радуюсь )) идея с бандлами тоже шедевр! с ними реально можно делать всё что хочешь, притом средствами фреймворка в бандл можно ввинтить инструменты командной строки, обработчики на всякие события, перегрузить другой бандл и т.д. и т.п... в общем у меня сейчас можно сказать только щенячий восторг остался ) но хочу сказать, что убежать кого-то переходить на сф2 не буду т.к. легко нарваться на холивар ( но если найдутся ребята и начнут задавать вопросы - с радостью буду отвечать на сколько это будет в моих силах т.к. очень заинтересован в максимально глубоком понимании этого проекта
Было желание сменить кохану на что-то другое, но с выходом версии 3.2 это желание пропало, HMVC таки куда как удобно и красиво там используется. ) За Фабиена спсибо, посмотрю обязательно для общего развития.
Ke1eth, кстати скажите как там HMVC реализовано? в симфони например вот так: Код (PHP): $Response = $this->forward('MyBundle:Hello:index', array('param1' => 123));
из вьюшки: Код (PHP): echo Request::factory('controller/action')->execute()->body(); помимо, передачи параметров через роут, можно докидать еще постом параметров Код (PHP): echo Request::factory('controller/action/id')->post('key', 'value')->execute()->body();
ага, ясно примерно... а метод body() отвечает за рендеринг? кстати да, забыл сказать, что к экшену можно обратиться прямо из шаблончика: Код (Text): {% render 'MyBundle:Hello:index' with {'text': 'Hello World'} %} а еще можно из любого контроллера отрендерить шаблончик любого бандла: Код (PHP): echo $this->renderView("MyBundle::tpl.html.twig", array('text' => 123)); // а также можно юзать путь до шаблонов: echo $this->renderView("MyBundle:sub/path/to:tpl.html.twig", array('text' => 123));
еще хочу заметить, что в первом примере $Response это полноценный объет НТТР ответа, и если нам в котроллере надо только контент (без заголовков), тогда получить его можно так: Код (PHP): echo $Response->getContent();