Подтвердить что ты не робот

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

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

alt text

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

  • Левый навигатор
  • Содержание nav
  • Имя пользователя
  • 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()

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

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

4b9b3361

Ответ 1

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

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, а верхний и нижний колонтитулы и другие элементы включаются только один раз в код.

Ответ 2

@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> был помещен в базовый шаблон.

Ресурсы

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

Ответ 3

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

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

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

Ответ 4

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

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

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

Ответ 5

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

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

Ответ 6

Мне нравится то, что Фил Стерджон упомянул. Хотя он считался очень сложным, мне очень понравилась структура шаблонов, которые имели 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 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 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 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, где у вас есть   head (загрузка заголовков html, название и т.д.)   заголовок/заголовки (загрузка в заголовках, если они есть в переданных $data ['view'] ['headers'] variable/array)   layout (загружает в файл макета, который просто имеет новый 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 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); //
}

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

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

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

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

Вот об этом...

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

Ответ 7

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

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

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

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