2010-09-09 12 views
35

Come strutturate la pagina seguente in Codeigniter?Codeigniter: il modo migliore per strutturare le viste parziali

alt text

ho pensato di creare controller separati per ogni sezione

  1. Sinistra nav
  2. Content nav
  3. sessione Nome
  4. Leaderboard

esclusa la sezione del contenuto (in quanto cambia a seconda del collegamento sul navigatore sinistro e del navigatore del contenuto utilizzato come sottomenu kinda). Tutte le altre sezioni rimangono grosso modo la stessa

ho pensato di fare:

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

} 

Ovviamente questo load_controller non esiste, ma questo functionaility sarebbero utili. Il controller per ogni sezione riceve i dati richiesti dal modello e carica la pagina attraverso $this->view->load()

Potrebbe essere un mal di testa avere questo codice in tutti i link di navigazione sinistro come Notizie, Utenti, Chi Siamo, ecc. Ma poi ancora non tutti i collegamenti nav hanno tutte quelle sezioni quindi ho bisogno di quella flessibilità di avere le sezioni come una "vista parziale"

Qualcuno può suggerire un modo migliore per farlo?

risposta

23

non posso garantire che questo è l'approccio migliore, ma creo un controller di base come questo:

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 vista chiamata 'base' è un modello (una vista che include altre viste):

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

ciò realizza è che ogni controllore avvolge la sua uscita nel modello di base, e che hanno una vista valido HTML invece di aprire tag in una visualizzazione e chiusura in un altro. Se mi piacerebbe che un controller specifico usasse un modello diverso o no, potrei semplicemente scavalcare il metodo magico _output().

Un controller vero e proprio sarebbe simile a questa:

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

Poi ho potuto utilizzare le sue proprietà nel mio punto di vista come questo (questo è il 'meta' opinione che popola l'elemento <head>):

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

Mi piace il mio approccio perché rispetta il principio DRY e l'intestazione, il piè di pagina e altri elementi vengono inclusi solo una volta nel codice.

+0

Questa sembra una buona opzione, ma io Non sono propenso all'idea di "viste che incorporano altre visualizzazioni" - come fanno le altre visualizzazioni a ottenere i dati? Presumo che ciò funzionerebbe bene solo quando le viste incluse hanno contenuto statico. –

+0

Le viste sono solo incluse, quindi condividono lo stesso controller ('$ this') e le variabili come modello di base. Guarda come uso '$ this-> title' nella vista 'meta', che è inclusa nel modello base. Potrei anche aver usato '$ content' lì. – slikts

+0

Ho aggiunto un esempio di una vista specifica del controller al controller Home. – slikts

-1

Quello che ho fatto (in Kohana 2) è il modello 1 con tutte le sottosezioni (come il menu a sinistra, l'intestazione superiore) e un singolo controller che popola le variabili che verranno sostituite nel modello.

Quindi, le variabili per ogni sottosezione possono essere generate da funzioni chiamate nel controller stesso. Puoi anche avere queste funzioni in un costruttore di una classe di controller separata, con ogni controller del tuo estendere quello in modo che vengano automaticamente eseguiti e impostati come variabili di classe per un facile accesso.

Per i modelli un po 'più bello si può avere le sottosezioni in file separati, e il grande modello di includerli:

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

hai considerato modelli? Ci sono molti decenti disponibili con un po 'di ricerca - controlla il wiki CI.

i modelli eseguono più o meno esattamente ciò che si desidera. È possibile definire un modello master e "sezioni", e questi vengono caricati per voi ogni volta

non vogliono collegare troppo quindi questo potrebbe iniziare - template libraries in CI

1

mi farebbe un mio_controllore di prendersi cura di tutto questo Puoi top con un layout (template)/libreria di navigazione per generare tutti i layout, navigazione, mostrare/evidenziare la voce di menu selezionata, caricare le visualizzazioni ecc.

Direi che non è il modo giusto per farlo, se stai usando un controller per ogni sezione di pagina. Puoi fare uso di viste e viste nidificate per questo.

6

La mia libreria di modelli può gestire tutto questo. Si crea un singolo (o più) file di layout che contengono i partial e un tag per dove andrà il contenuto del corpo principale.

Sintassi semplice come:

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

Semplici giusto?

Metti un po 'di questo in MY_Controller ed è ancora più facile.

28

@Reinis risposta probabilmente colpire il posto giusto per le versioni precedenti di CI inferiore a 2.0 tuttavia molto cambiato da allora, quindi ho pensato di rispondere a questa domanda con un metodo aggiornato di quello che ho fatto.

maggior parte di esso è simile al metodo @Reinis e anche descritto qui: http://codeigniter.com/wiki/MY_Controller_-_how_to_extend_the_CI_Controller

Tuttavia qui ci sono Ive fatto gli aggiornamenti:

Passaggio 1: Creare un file MY_Controller.php e memorizzarlo in/applicazione/core

Fase 2: nel file MY_Controller.php mettere nelle seguenti contenuti:

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

} 

Passaggio 3: Creare un campione di controllo di basare off di MY_Controller.php, in questo caso ho creerà un controller welcome.php all'interno di application/controller/con il seguente contenuto:

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

} 

Una volta che avete questi controller set, effettuare le seguenti operazioni:

Passaggio 4: creare una vista di base all'interno di/application/views e denominare il file base.php, il contenuto del file dovrebbe essere simile a questo:

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

Passo 5: Creare un'altra vista in/application/punti di vista e questo nome welcome_message.php vista, il contenuto di questo file sarà:

<h1>Welcome</h1> 

volta, tutto questo è completo, si dovrebbe vedere il seguente output:

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

Come si può vedere <h1>Welcome</h1> è stato messo nel modello base.

Risorse:

Spero che questo aiuti chiunque altro imbattersi in questa tecnica.

+2

Se si esegue questa operazione da un'installazione pulita, è necessario anche abilitare l'helper "url" in application/config/autoload.php (affinché 'base_url()' funzioni). –

+0

Capisco che in sostanza si costruisca la visualizzazione del contenuto iniziale, quindi prima dell'output, si costruisca la vista di base e si aggiunga il contenuto pre-costruito alla vista di base. Non capisco il passaggio per riferimento? e ho impostato questo allo stesso modo e solo passare un paio di bit nell'array di dati alla base (come page_title, page_keywords, ecc.), ma mi dà uno schermo vuoto ... quindi non sembra carica la vista di base, ma nessun errore ... La visualizzazione dei dati $ mostra tutte le informazioni giuste anche se il contenuto è stato creato e non c'è un errore ortografico da nessuna parte. Qualche idea? – mtpultz

1

Mi piace quello che ha menzionato Phil Sturgeon. Sebbene sia considerato molto complicato, mi è piaciuta molto la struttura dei template di Magento.

Ispirato con questo modo di strutturare ho fatto la mia logica, (che non è affatto grande ma è semplice come può essere, e forse forse potrei sovrascrivere -> visualizzare il caricatore e renderlo accetta un qualche tipo di oggetto come un nome di modello e di caricare la struttura come richiesto)

primo: Questo approccio deve essere utilizzato in modo molto responsabile (si mus preparare i dati nel controllore/metodo che i modelli richiedono

secondo:! bisogni dei modelli essere preparato e strutturato correttamente

Questo è quello che faccio:

  • in ogni controller ho attributo di tipo Array, qualcosa di simile:

    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' => '', 
    ); 
    
  • In ogni metodo per il quale voglio usare la struttura precedente e se voglio cambiare un po 'scrivo in questo modo:

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

terza cartella A/application/vista ho struttura come

/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 

indietro file in /app/view/main.php sembra qualcosa di simile:

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

quinto wrapper è semplice php in HTML strutturato dove hai la testa (caricamento di intestazioni HTML, titolo ecc ...) intestazioni/intestazioni (caricamento delle intestazioni se ci sono dati in $ passati ['vista'] ['intestazioni'] variabile/matrice) Layout (carica nel file di layout che ha semplicemente un nuovo file strutturato html con il prossimo livello di caricamento file) piè di pagina/piè di pagina (caricamento in corso a piè di pagina se ci sono in passati $ dati [ 'vista'] [ 'piè di pagina'] variabile) script (inscripts carico come analytics/script facebook poco prima tag)

sesto Allo stesso modo, il layout verrebbe caricato anche nel contenuto della barra principale/sidebar specificato in pubblico $ view = Array (....)

Se ho bisogno di un metodo, ho semplicemente sostituito una parte di public $ view = Array (...) attributo, e sovrascrivo solo una parte diversa.

si fa qualcosa di simile:

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

FINALMENTE carico va in questo modo:

  1. $ this-> load-> view ('main', $ dati); < - Carica /app/view/main.php e passa $ dati $ data ha nodo 'view' ($ data ['view']) e in esso ha sub-nodi che determinano altre cose importanti come: qual è il fine, ciò che il layout, che cosa le intestazioni, piè di pagina che cosa ecc ...

  2. utilizzando i dati definiti nei dati $ [ 'vista'] [ 'theend'] carica corretta involucro

  3. Anche in questo caso utilizzando i dati nei dati $ [ 'view'] ['layout'] ulteriormente nel wrapper carica altre strutture più profonde come il layout ...
  4. layout, utilizza lo stesso $ data ['view'] ['mainbar'], $ data ['view'] ['barra laterale'] e cattura altre parti importanti da caricare come i modelli della barra principale, i modelli della barra laterale ...

Che è su di esso ...

P.S. Sono così dispiaciuto per non aver usato i numeri, ma il sistema di stackoverflow è così strano che invece di mostrare 3. mi mostra 1 .. come vedi ho avuto alcune liste annidate ...

Problemi correlati