web-dev-qa-db-fra.com

Codeigniter: le meilleur moyen de structurer des vues partielles

Comment structureriez-vous la page ci-dessous dans Codeigniter?

alt text

J'ai pensé créer des contrôleurs séparés pour chaque section

  1. Nav gauche
  2. Navigation de contenu
  3. Identifiant
  4. Classement

Exclure la section de contenu (car cela change en fonction du lien sur la navigation de gauche et de la navigation de contenu utilisée comme un sous-menu un peu). Toutes les autres sections restent à peu près les mêmes

J'ai pensé à faire:

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

}

Évidemment, ce load_controller n’existe pas mais cette fonctionnalité serait utile. Le contrôleur de chaque section obtient les données requises du modèle, puis charge la page via $this->view->load().

Cela pourrait être un casse-tête d'avoir ce code dans tous les liens de navigation de gauche tels que Nouvelles, Utilisateurs, À propos de nous, etc. Mais là encore, tous les liens de navigation n'ont pas toutes ces sections. vue"

Quelqu'un peut-il suggérer un meilleur moyen de le faire?

37
Gary Green

Je ne peux pas garantir que c'est la meilleure approche, mais je crée un contrôleur de base comme celui-ci:

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

}

La vue appelée 'base' est un modèle (une vue qui inclut d'autres vues):

<?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>

Cela permet aux contrôleurs d'encapsuler leur sortie dans le modèle de base et que les vues disposent d'un code HTML valide au lieu d'ouvrir les balises dans une vue et de les fermer dans une autre. Si je souhaite qu'un contrôleur spécifique utilise un modèle différent ou aucun modèle, je pourrais simplement remplacer la méthode magique _output().

Un contrôleur réel ressemblerait à ceci:

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

Ensuite, je pourrais utiliser ses propriétés dans mes vues comme ceci (c'est la vue 'méta' qui remplit l'élément <head>):

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

J'aime mon approche car elle respecte le principe DRY et que l'en-tête, le pied de page et d'autres éléments ne sont inclus qu'une seule fois dans le code.

23
slikts

La réponse de @Reinis a probablement été choisie correctement pour les anciennes versions de CI inférieures à 2.0, mais beaucoup de choses ont changé depuis. J'ai donc pensé répondre à cette question avec une méthode à jour de ce que j'ai fait.

La plupart sont similaires à la méthode @Reinis et sont également décrits ici: http://codeigniter.com/wiki/MY_Controller_-_how_to_extend_the_CI_Controller

Cependant voici les mises à jour que j'ai faites:

Étape 1: Créez un fichier MY_Controller.php et stockez-le dans/application/core.

Étape 2: Dans votre fichier MY_Controller.php, insérez le contenu suivant:

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

}

Étape 3: Créez un exemple de contrôleur pour vous baser sur MY_Controller.php. Dans ce cas, je vais créer un contrôleur welcome.php dans application/controllers/avec le contenu suivant:

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

}

Une fois que vous avez défini ces contrôleurs, procédez comme suit:

Étape 4: Créez une vue de base dans/application/views et nommez le fichier base.php. Le contenu du fichier doit être similaire à celui-ci:

<!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>

Étape 5: Créez une autre vue dans/application/views et nommez cette vue welcome_message.php, le contenu de ce fichier sera:

<h1>Welcome</h1>

Une fois que tout cela est terminé, vous devriez voir le résultat suivant:

<!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>

Comme vous pouvez le constater, <h1>Welcome</h1> a été placé dans le modèle de base. 

Ressources:

J'espère que cela aidera tous ceux qui découvrent cette technique.

28
alvincrespo

Ma bibliothèque de modèles peut gérer tout cela. Vous créez un (plusieurs) fichier (s) de mise en page contenant les partiels et une balise indiquant l'emplacement du corps principal.

Syntaxe aussi simple que:

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

Simples non?

Mettez une partie de cela dans MY_Controller et c'est encore plus facile.

6
Phil Sturgeon

Je ferais un MY_Controller pour s'occuper de tout ça. Vous pouvez y ajouter une présentation (modèle)/bibliothèque de navigation pour générer toutes les présentations, la navigation, l'affichage/la mise en surbrillance de l'élément de menu sélectionné, le chargement des vues, etc.

Je dirais que ce n'est pas la bonne façon de procéder, si vous utilisez un contrôleur pour chaque section de page. Vous pouvez utiliser des vues et des vues imbriquées pour cela.

1
rkj

avez-vous envisagé des modèles? Il y a beaucoup de bons choix disponibles avec une petite recherche - consultez le wiki de CI.

les modèles font plus ou moins exactement ce que vous recherchez. Vous définissez un modèle principal et des "sections", qui sont chargées pour vous à chaque fois.

ne voulez pas trop en brancher, cela pourrait vous aider à démarrer - bibliothèques de modèles dans CI

1
Ross

J'aime ce que Phil Sturgeon a mentionné. Bien que cela soit considéré comme très compliqué, j’ai vraiment aimé la structure des modèles de magento.

Inspiré par cette façon de structurer, j’ai créé ma logique (ce qui n’est pas génial, mais aussi simple que cela puisse être, et peut-être pourrais-je remplacer -> view loader et lui faire accepter une sorte d’objet comme nom de modèle et charger la structure selon les besoins)

first : Cette approche doit être utilisée de manière très responsable (vous devez préparer les données dans le contrôleur/la méthode requise par vos modèles!).

second : Le modèle doit être préparé et structuré correctement.

C'est ce que je fais:

  • dans chaque contrôleur, j'ai l'attribut de type Array, quelque chose comme ceci:

    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' => '',
    );
    
  • Dans chaque méthode pour laquelle je veux utiliser la structure précédente, et si je veux la changer un peu, je l'écris comme ceci:

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

troisième dans/application/view folder j'ai une structure comme

/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

ahead Le fichier /app/view/main.php ressemble à ceci:

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

cinquième wrapper est simple php en HTML structuré où vous avez head (chargement des en-têtes HTML, du titre, etc.) en-tête/en-têtes (chargement dans les en-têtes s'il y en a dans la variable $ data ['view'] ['en-têtes'] transmise/tableau) layout (charge dans un fichier de disposition qui a simplement un nouveau fichier structuré html avec le prochain niveau de chargement des fichiers) footer/footers (chargement dans les bas de page s'il y en a dans la variable $ data ['view'] ['footers'] passée) scripts (chargement d'inscriptions comme les scripts d'analyse/facebook juste avant la balise)

sixième Ainsi, de la même manière, layout serait également chargé dans le contenu principal/sidebar spécifié dans public $ view = Array (....)

Si j'ai besoin d'une méthode, je remplace simplement une partie de l'attribut public $ view = Array (...), et je remplace seulement une partie qui est différente.

ça fait quelque chose comme ça:

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

FINALEMENT Load va comme ceci:

  1. $ this-> load-> view ('main', $ data); <- Charge /app/view/main.php et passe $ data $ Data a le noeud 'view' ($ data ['view']) et contient des sous-noeuds qui déterminent d'autres éléments importants tels que: est la fin, quelle disposition, quels en-têtes, quels pieds de page etc ...

  2. En utilisant des données définies dans $ data ['view'] ['theend'], il charge le bon wrapper

  3. Encore une fois, en utilisant les données dans $ data ['view'] ['layout'] plus loin dans wrapper, il charge d'autres structures plus profondes, telles que layout ...
  4. layout, utilise les mêmes $ data ['view'] ['mainbar'], $ data ['view'] ['sidebar'] et attrape d’autres pièces importantes à charger telles que les templates de la barre principale, les templates de la barre latérale ...

C'est à peu près tout ...

p.s. Je suis vraiment désolé de ne pas utiliser de chiffres, mais le système stackoverflow est tellement étrange qu'au lieu de montrer 3. il me montre 1 .. comme vous voyez, j'avais des listes imbriquées ...

1
user767124