web-dev-qa-db-ja.com

Codeigniter:部分ビューを構成する最良の方法

Codeigniterで以下のページをどのように構成しますか?

alt text

各セクションに個別のコントローラーを作成することを考えました

  1. 左ナビゲーション
  2. コンテンツナビゲーション
  3. ログイン名
  4. リーダーボード

コンテンツセクションを除外します(これは、左ナビゲーションのリンクと、サブメニューとして使用されるコンテンツナビゲーションに応じて変化します)。他のすべてのセクションはほぼ同じままです

私はやろうと思った:

_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()を介してページを読み込みます

このコードをNews、Users、About Usなどのすべての左側のナビゲーションリンクに配置するのは頭痛の種かもしれません。しかし、すべてのナビゲーションリンクにすべてのセクションがあるわけではないため、セクションを「部分見る"

誰でもこれを行うより良い方法を提案できますか?

37
Gary Green

これが最善のアプローチであることは保証できませんが、次のようなベースコントローラーを作成します。

_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原則を尊重し、ヘッダー、フッター、その他の要素がコードに一度だけ含まれるので、私は私のアプローチが好きです。

23
slikts

@Reinisの回答は、おそらく2.0より前のCIの古いバージョンでは正しくヒットしますが、それ以来多くの変更が加えられているため、この質問に自分がやったことの最新の方法で答えると思いました。

そのほとんどは@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をベースとするサンプルコントローラーを作成します。この場合、次の内容のapplication/controllers /内に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>が基本テンプレートに追加されました。

リソース:

これがこのテクニックに出くわす他の人の助けになることを願っています。

28
alvincrespo

私のテンプレートライブラリは、これらすべてを処理できます。パーシャルを含む単一(または複数)のレイアウトファイルを作成し、メインのコンテンツが配置されるタグを作成します。

簡単な構文:

// 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に追加すると、さらに簡単になります。

6
Phil Sturgeon

このすべてを処理するMY_Controllerを作成します。レイアウト(テンプレート)/ナビゲーションライブラリを使用して、すべてのレイアウト、ナビゲーション、選択したメニュー項目の表示/強調表示、ビューの読み込みなどを生成できます。

各ページセクションにコントローラーを使用している場合、それは正しい方法ではないと思います。そのためにビューとネストされたビューを使用できます。

1
rkj

テンプレートを検討しましたか?少し検索するだけで多くの適切なものが利用可能です-CI wikiを確認してください。

テンプレートはあなたが望んでいることを多かれ少なかれ正確に行います。 1つのマスターテンプレートと「セクション」を定義します。これらは毎回ロードされます

あまりプラグインしたくないので、これで始めることができます- CIのテンプレートライブラリ

1
Ross

フィル・スタージョンが言ったことが好きです。非常に複雑であると考えられていますが、私はmagentoのテンプレート構造が本当に好きでした。

構造化のその方法に触発されて、私は自分のロジックを作りました(それはまったく素晴らしいことではありませんが、それはできる限り簡単です。そしておそらく、私はオーバーライドすることができます->ローダーを表示し、テンプレート名として何らかのオブジェクトを受け入れて、必要に応じて構造をロードするよりも)

first:このアプローチは非常に責任を持って使用する必要があります(テンプレートに必要なコントローラー/メソッドでデータを準備する必要があります!

:テンプレートを適切に準備および構造化する必要があります。

これが私がすることです:

  • すべてのコントローラーには、次のような配列型の属性があります。

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

third/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

forth /app/view/main.phpのファイルは次のようになります。

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

5番目ラッパーは単純な構造化HTMLの一部のphpです(ヘッダー(htmlヘッダー、タイトルなどを読み込んでいます)ヘッダー/ヘッダー(渡された$ data ['view'にヘッダーがある場合に読み込みます) ] ['headers']変数/配列)レイアウト(次のレベルの読み込みファイルを持つ新しいhtml構造化ファイルを単純に含むレイアウトファイルに読み込みます)フッター/フッター(渡された$ data ['view']にフッターがあれば読み込みます) ['footers']変数)スクリプト(タグの直前に分析/フェイスブックスクリプトなどのスクリプトを読み込む)

6th同様に、レイアウトはpublic $ view = Array(....)で指定されたメインバー/サイドバーのコンテンツにもロードされます

何らかの方法が必要な場合、単純にpublic $ 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'])があり、その中にサブノードがあります。 、レイアウト、ヘッダー、フッターなど.

  2. $ data ['view'] ['theend']の定義済みデータを使用して、適切なラッパーをロードします

  3. 再び$ data ['view'] ['layout']のデータをラッパーでさらに使用して、レイアウトのような他のより深い構造をロードします...
  4. レイアウト、同じ$ data ['view'] ['mainbar']、$ data ['view'] ['sidebar']を使用し、メインバーテンプレート、サイドバーテンプレートのようにロードする他の重要な部分をキャッチします...

それはそれについてです...

追伸私は数字を使用していないことをとても残念に思っていますが、stackoverflowシステムは非常に奇妙であるため、3を表示する代わりに1を表示します。

1
user767124