Railsに取り組んでからCodeIgniterもまた使うようになったのですが、Railsにあって便利そうなものをCodeIgniterにも取り入れて、快適に書けるよう進めていっています。今回は、そんなことをしたうちの1つ、レイアウト層の導入について取り上げてみます。
レイアウトって?
Railsをやっている人ならご存知だと思いますが、Railsで各コントローラーから呼び出すビューには、基本的に<body>
の一部しか書かれていません。その外側の<!DOCTYPE>
とか<html>
とかは、別な「レイアウト」ファイルに書いてあって、ビューはその中に表示されることになります。
実際にサイトを作る上で、(JavaScriptとかCSSなどは別として)各ページごとにレイアウトが違うことはまずないですし、各個のビューからは決まりきった部分の描画をまったく省略できるので、すっきり書けるようになります。
描画を乗っ取る_output
それでは、このような機構をCodeIgniterに組み込むには、どうすればいいでしょうか。CodeIgniterには、ビューでの出力が終わった後、それを最終形にする前に呼び出される_output
というメソッドがあるので、ここに仕掛けてみることにします。
まずは、レイアウト制御用のLayout
クラスを用意します。
<?php
class Layout{
private $_ci;
private $_name = 'default';
private $_parameters = array('title' => '', 'h1' => '');
public function __construct(){
$this -> _ci = & get_instance();
}
public function set_template($name){
$this -> _name = $name;
}
public function set_parameter($key, $val){
$this -> _parameters[$key] = $val;
}
public function __set($key, $val) {
$this -> set_parameter($key, $val);
}
public function render($content, $return = FALSE){
$this -> _parameters['_content'] = $content;
return $this -> _ci -> load -> view('layouts/' . $this ->
_name, $this -> _parameters, $return);
}
}
レイアウトのレンダリングにも通常のビューと同じ仕組みを使って、そしてレイアウトからは$_content
で中に出力すべき内容を取得できるようになっています。また、title
やh1
などレイアウトに渡すべき引数がいくつかあるので、マジックメソッドで制御できるようにしてあります。
そして、これを呼ぶMY_Controller
は以下のようになります。
class MY_Controller extends CI_Controller{
public function __construct(){
parent::__construct();
// オートロードで設定してもOK
$this -> load -> library('layout');
}
protected $_use_layout = TRUE;
public function use_layout($value){
$this -> _use_layout = $value;
}
//出力ハンドラ
public function _output($content){
if($this -> _use_layout) {
$content = $this -> layout -> render($content, TRUE);
}
echo $content;
}
}
見ての通り、use_layout
がTRUEならレイアウトを挟んで出力している、それだけです。
検討課題
まだ作りかけなので、考慮すべきことがいくつかあります。
- JavaScript、CSSのハンドリング
- HTML以外を出力する場合、Content-typeを切り替えるだけでレイアウトを無効にする