Codeigniter: лучший способ структурировать частичные представления - PullRequest
37 голосов
/ 09 сентября 2010

Как бы вы структурировали приведенную ниже страницу в 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()

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

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

Ответы [ 7 ]

28 голосов
/ 23 ноября 2011

@ Ответ Рейниса, вероятно, попал в точку правильно для более ранних версий 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: Создайте другое представление в /приложение/ views и назовите этот view 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> было введено в базовый шаблон.

Ресурсы:

Надеюсь, это поможет всем, кто сталкивается с этой техникой.

23 голосов
/ 09 сентября 2010

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

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);
    }

}

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

<?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');
    }
}

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

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

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

6 голосов
/ 13 сентября 2010

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

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

// 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, и это еще проще.

1 голос
/ 11 марта 2012

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

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

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

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

Это то, что я делаю:

  • в каждом контроллере у меня есть атрибут типа 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); //
    }
    

третий В папке / 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'] / переменная (загрузка в файл макета, который просто имеет новую структурированную html)файл со следующим уровнем загрузки файлов) скрипты нижнего колонтитула / нижнего колонтитула (загрузка в нижний колонтитул, если есть какие-либо переданные переменные $ data ['view'] ['footers']) (загрузка таких надписей, как скрипты аналитики / facebook непосредственно перед тегом)

шестой Таким же образом, макет также будет загружать содержимое основной / боковой панели, указанное в общедоступном $ 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-> view ('main', $ data);<- Загружает /app/view/main.php и передает $ data $ data имеет узел 'view' ($ data ['view']) и в нем есть подузлы, которые определяют другие важные вещи, такие как: каков конецкакой макет, какие верхние колонтитулы, какие нижние колонтитулы и т. д. ... </p>

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

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

Вот и все ....

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

1 голос
/ 09 сентября 2010

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

1 голос
/ 09 сентября 2010

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

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

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

0 голосов
/ 09 сентября 2010

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

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

<?php include 'leftMenu.php'; ?>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...