Codeigniter: лучший способ структурирования частичных представлений

Как бы вы структурировали следующую страницу в Codeigniter?

alt text

Я думал о создании отдельных контроллеров для каждого раздела

  1. Левый навигация
  2. Содержание nav
  3. Логин
  4. Leaderboard

Исключая раздел содержимого (поскольку это изменяется в зависимости от ссылки на левом навигационном и контентном навигаторе, используемом как своеобразное подменю). Все остальные разделы остаются примерно одинаковыми

Я думал об этом:

Class User_Profile extends Controller { function index() { $this->load_controller('Left_Nav'); $this->load_controller('Content_Nav'); $this->load_controller('Login_Name'); $this->load_controller('Leaderboard', 'Board'); $this->Left_Nav->index(array('highlight_selected_page' => 'blah')); $this->load('User'); $content_data = $this->User->get_profile_details(); $this->view->load('content', $content_data); $this->Login_Name->index(); $this->Board->index(); } } 

Очевидно, что этот load_controller не существует, но эта функция была бы полезна. Контроллер для каждого раздела получает данные, требуемые от модели, а затем загружает страницу через $this->view->load()

Это может быть головная боль, чтобы иметь этот код во всех левых навигационных ссылках, таких как «Новости», «Пользователи», «О нас» и т. Д. Но опять же не у каждой навигационной ссылки есть все эти разделы, поэтому мне нужна гибкость в том, что разделы являются «частичными Посмотреть"

Может ли кто-нибудь предложить лучший способ сделать это?

Я не могу ручаться, что это лучший подход, но я создаю базовый контроллер следующим образом:

 class MY_Controller extends CI_Controller { public $title = ''; // The template will use this to include default.css by default public $styles = array('default'); function _output($content) { // Load the base template with output content available as $content $data['content'] = &$content; $this->load->view('base', $data); } } 

Представление, называемое «базой», является шаблоном (представление, которое включает в себя другие виды):

 <?php echo doctype(); ?> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <?php $this->load->view('meta'); ?> </head> <body> <div id="wrapper"> <?php $this->load->view('header'); ?> <div id="content"> <?php echo $content; ?> </div> <?php $this->load->view('footer'); ?> </div> </body> </html> 

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

Фактический контроллер будет выглядеть так:

 class Home extends MY_Controller { // Override the title public $title = 'Home'; function __construct() { // Append a stylesheet (home.css) to the defaults $this->styles[] = 'home'; } function index() { // The output of this view will be wrapped in the base template $this->load->view('home'); } } 

Тогда я мог бы использовать его свойства в своих представлениях, подобных этому (это представление «мета», которое заполняет элемент <head> ):

 echo "<title>{$this->title}</title>"; foreach ($this->styles as $url) echo link_tag("styles/$url.css"); 

Мне нравится мой подход, потому что он уважает принцип DRY, а верхний и нижний колонтитулы и другие элементы включаются только один раз в код.

Ответ @Reinis, вероятно, правильно попал на место для более ранних версий CI менее 2.0, но с тех пор он сильно изменился, поэтому я решил ответить на этот вопрос с помощью современного метода того, что я сделал.

Большинство из них аналогично методу @Reinis, а также описано здесь: http://codeigniter.com/wiki/MY_Controller_-_how_to_extend_the_CI_Controller

Однако здесь сделаны обновления:

Шаг 1. Создайте файл MY_Controller.php и сохраните его в / application / core

Шаг 2. В вашем файле MY_Controller.php добавьте следующее содержимое:

 <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); class MY_Controller extends CI_Controller { function __construct() { parent::__construct(); } function _output($content) { // Load the base template with output content available as $content $data['content'] = &$content; echo($this->load->view('base', $data, true)); } } 

Шаг 3: Создайте образец контроллера, чтобы сфокусироваться на MY_Controller.php, в этом случае я создам контроллер welcome.php внутри приложения / контроллеров / со следующим содержимым:

 <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); class Welcome extends MY_Controller { function __construct() { parent::__construct(); } public function index() { $this->load->view('welcome_message'); } } 

После установки этих контроллеров выполните следующие действия:

Шаг 4. Создайте базовый вид внутри / application / views и назовите файл base.php, содержимое файла должно быть похоже на это:

 <!DOCTYPE html> <!--[if IE 7 ]><html lang="en" class="ie7"><![endif]--> <!--[if IE 8 ]><html lang="en" class="ie8"><![endif]--> <!--[if gt IE 8]><!--><html lang="en"><!--<![endif]--> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> <title></title> <link rel="stylesheet" href="<?php echo base_url(); ?>stylesheets/reset.css" media="screen" /> </head> <body> <div id="section_main"> <div id="content"> <?php echo $content; ?> </div> </div> <?php $this->load->view('shared/scripts.php'); ?> </div> </body> </html> 

Шаг 5: Создайте еще один вид в / application / views и назовите это представление welcome_message.php, содержимое этого файла будет:

 <h1>Welcome</h1> 

Как только все это будет завершено, вы увидите следующий результат:

 <!DOCTYPE html> <!--[if IE 7 ]><html lang="en" class="ie7"><![endif]--> <!--[if IE 8 ]><html lang="en" class="ie8"><![endif]--> <!--[if gt IE 8]><!--><html lang="en"><!--<![endif]--> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> <title></title> <link rel="stylesheet" href="http://somedomain.local/stylesheets/reset.css" media="screen" /> </head> <body> <!-- BEGIN: section_main --> <div id="section_main"> <div id="content"> <h1>Welcome</h1> </div> </div> <!-- END: section_main --> <script src="/path/to/js.js"></script> </div> </body> </html> 

Как вы видите, <h1>Welcome</h1> было помещено в базовый шаблон.

Ресурсы:

Надеюсь, это поможет кому-то еще прибегнуть к этой технике.

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

Синтаксис прост как:

 // Set the layout: defaults to "layout" in application/views/layout.php $this->template->set_layout('whatever') // Load application/views/partials/viewname as a partial $this->template->set_partial('partialname', 'partials/viewname'); // Call the main view: application/views/bodyviewname $this->template->build('bodyviewname', $data); от // Set the layout: defaults to "layout" in application/views/layout.php $this->template->set_layout('whatever') // Load application/views/partials/viewname as a partial $this->template->set_partial('partialname', 'partials/viewname'); // Call the main view: application/views/bodyviewname $this->template->build('bodyviewname', $data); 

Симплирует правильно?

Поместите часть этого в MY_Controller и еще проще.

вы считали шаблоны? Есть много достойных, доступных с небольшим поиском – проверьте CI wiki.

шаблоны делают более или менее то, что вам нужно. Вы определяете один главный шаблон и «разделы», и они загружаются для вас каждый раз

не хотите подключаться слишком сильно, чтобы вы могли начать работу – библиотеки шаблонов в CI

Я бы сделал MY_Controller, чтобы позаботиться обо всем этом. Вы можете разместить его с помощью макета (шаблона) / навигационной библиотеки для создания всех макетов, навигации, отображения / выделения выделенного пункта меню, загрузки представлений и т. Д.

Я бы сказал, что это неправильный способ сделать это, если вы используете контроллер для каждого раздела. Вы можете использовать представления и вложенные представления для этого.

Мне нравится то, что Фил Стерджон упомянул. Хотя это считается очень сложной, мне очень понравилась структура шаблонов, которая имеет magento.

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

во-первых : этот подход должен использоваться очень ответственно (вы собираете данные в контроллере / методе, который требуется вашим шаблонам!

second : Шаблон должен быть подготовлен и структурирован должным образом.

Вот что я делаю:

  • в каждом контроллере у меня есть атрибут типа Array, что-то вроде этого:

     class Main extends CI_Controller { public $view = Array( 'theend' => 'frontend', 'layout' => '1column', 'mainbar' => array('content','next template file loaded under'), 'sidebar' => array('generic','next template file loaded under'), 'content' => '', ); 
  • В каждом методе, для которого я хочу использовать предыдущую структуру, и если я хочу немного изменить его, напишу его так:

     public function index() { $data['view'] = $this->view; // i take/load global class's attribute $data['view']['mainbar'] = Array('archive','related_posts'); // i change mainbar part of it // i add/load data that i need in all those templates that are needed $data['view'] also my using same Array $data['my_required_data_that_i_use_in_template_files'] = 1; $this->load->view('main',$data); // } 

Третья папка In / application / view у меня есть структура вроде

 /view/main.php <-- which basically just determines which side's wrapper of web to load (frontend or backend or some other) /view/frontend/wrapper.php /view/backend/wrapper.php /view/mobile/wrapper.php <-- this wrappers are again another level of structuring for ex: /view/backend/layouts/ <-- inside i have templates different layouts like 1column.php 2columns-left (have left side is narrow one),2columns-right,3columns... etc... /view/backend/mainbar/ <-- inside i have templates for mainbar in pages /view/backend/mainbar/.../ <-- in the same way it's possible to add folders for easily grouping templates for example for posts so you add for example /view/backend/mainbar/posts/ <-- all templates for creating, editing etc posts... /view/backend/sidebar/ <-- inside i have templates for sidebar in pages /view/backend/...other special cases.... like dashboard.php 

Четвертый файл в /app/view/main.php выглядит примерно так:

 if ($view['theend'] == "frontend") { $this->load->view('/frontend/wrapper'); } elseif ($view['theend'] == "backend") { $this->load->view('/backend/wrapper'); } 

пятая оболочка проста в php в структурированном HTML, где у вас есть заголовок (загрузка заголовков html, заголовок и т. д.) заголовок / заголовки (загрузка в заголовках, если в переданной переменной $ data ['view'] ['headers'] / array) (загружает в файл макета, который просто имеет новый html-структурированный файл со следующим уровнем загрузки файлов) нижние колонтитулы (загрузка нижних колонтитулов, если в переданной переменной $ data ['view'] ['footers'] есть какая-либо информация) скриптов (загрузка скриптов, таких как analytics / facebook, скрипты перед тегом)

шестой. Таким же образом, макет также будет загружаться в контент mainbar / sidebar, указанный в public $ view = Array (….)

Если мне нужен какой-то метод, я просто переопределяю часть публичного атрибута $ view = Array (…), и я переопределяю только часть, которая отличается.

это делается примерно так:

 public function index() { $data['view'] = $this->view; // i take/load global class's attribute $data['view']['mainbar'] = Array('archive','related_posts'); // i change mainbar part of it // i add/load data that i need in all those templates that are needed $data['view'] also my using same Array $data['my_required_data_that_i_use_in_template_files'] = 1; $this->load->view('main',$data); // } 

НАКОНЕЧНЯ Загрузка выглядит следующим образом:

  1. $ This-> load-> Вид ( 'главный', $ данных); <- Loads /app/view/main.php и передает $ data $ data имеет узел 'view' ($ data ['view']), и в нем у него есть узлы, которые определяют другие важные вещи, такие как: какой конец , какой макет, какие заголовки, какие нижние колонтитулы и т. д. …

  2. Используя определенные данные в $ data ['view'] ['theend'], он загружает соответствующую оболочку

  3. Снова используя данные в $ data ['view'] ['layout'] далее в обертке, он загружает другие, более глубокие структуры, такие как макет …
  4. layout, использует те же $ data ['view'] ['mainbar'], $ data ['view'] ['sidebar'] и улавливает другие важные части для загрузки, как шаблоны панели, шаблоны боковых панелей …

Это о нем …

ps Мне очень жаль, что не использовал числа, но система stackoverflow настолько странная, что вместо показа 3. она показывает мне 1 .. как вы видите, у меня были некоторые вложенные списки …

То, что я сделал (в Kohana 2), имеет 1 шаблон со всеми подразделами (например, левое меню, верхний заголовок) и один контроллер, который заполняет переменные, которые будут заменены в шаблоне.

Затем переменные для каждого подсектора могут быть сгенерированы функциями, называемыми самим контроллером. Вы также можете использовать эти функции в отдельном конструкторе класса контроллера, причем каждый ваш контроллер расширяет его, чтобы они автоматически запускались и устанавливались как переменные класса для легкого доступа.

Для немного более приятных шаблонов вы можете иметь подразделы в отдельных файлах, а большой шаблон включает их:

 <?php include 'leftMenu.php'; ?>