高瀬です。
YiiはPHPでWebアプリケーションを開発するためのMVCフレームワーク。以下のWebサイトを参照。
初めに: Yii とは何か | The Definitive Guide to Yii | Yii Framework
Yiiでの開発を始めて半年ほどではあるけれども、使おうと思っても触れることができなかった機能に、「テーマ」と「レイアウト」がある。ここではそれらの使い方を考えてみる。
テーマの作成
「テーマ」はWordPressのテーマのように、Webサイトの見栄えを切り替えるために利用する。以下を参照。その他のトピック: テーマ | The Definitive Guide to Yii | Yii Framework
実際に使ってみよう。試しに、Yiiが自動生成する初期プロジェクトの見栄えを変えるテーマを作成してみる。
[初期プロジェクトのテーマ]
[変更後のテーマ]
変更後のテーマには「uniquevision」という名前を付けることとする。まず最初にすることは、ページのレイアウトを決めているファイルmain.phpを、新しく作るテーマ用にコピーすることだ。
(basePath)/protected/views/layouts/main.php
↓
(basePath)/themes/uniquevision/views/layouts/main.php
テーマはthemesというディレクトリ内に作成する。作成したディレクトリの名前がテーマの名前となる。
では、uniquevisionテーマのカスタマイズをしてみよう。コピーしたmain.phpを編集して、ページの左上に表示されている「My Web Application」の表示を、ユニークビジョンのロゴ画像に変更してみる。
ロゴ画像のファイルはテーマごとのディレクトリ内に配置したいので、以下のパスを作成し、保存。その上で、パスをビューに記述する。
(basePath)/themes/uniquevision/images/ti_logo.gif
(変更前) <div id="header"> <div id="logo"><?php echo CHtml::encode(Yii::app()->name); ?></div> </div><!-- header --> ↓ (変更後) <div id="header"> <div id="logo"><img src="<?= $this->themeBaseUrl; ?>images/ti_logo.gif" /></div> </div><!-- header --> |
テーマのディレクトリに配置した画像ファイルのパスを指すには、Yii::app()->theme という変数を利用することができる。テーマのパスを参照しやすいように、Controllerクラスで以下のように変数を定義した。
class Controller extends CController { : public $themeBaseUrl = ''; public function isThemeUsed() { return !is_null(Yii::app()->theme); } public function init() { parent::init(); if ($this->isThemeUsed()) { $this->themeBaseUrl = Yii::app()->theme->baseUrl . DIRECTORY_SEPARATOR; } Yii::app()->clientScript->registerCoreScript('jquery'); } : |
$this->themeBaseUrl という変数を使用して画像ファイルへのパスを作っている($thisはコントローラのインスタンス)。
さて、画像ファイルのパスの切り替え派できたが、CSSはどうするか。これもテーマごとのディレクトリ内に配置したい。とりあえず元のCSSファイルがあるディレクトリをコピーしてしまおう。
(basePath)/css
↓
(basePath)/themes/uniquevision/css
コピー後のCSSファイルを参照するには、やはり$this->themeBaseUrl を使用する。レイアウト用のmain.php内では、元は Yii::app()->request->baseUrl という変数でパスを生成しているので、これを書き換える。
(変更前) <link rel="stylesheet" type="text/css" href="<?php echo Yii::app()->request->baseUrl; ?>/css/main.css" /> ↓ (変更後) <link rel="stylesheet" type="text/css" href="<?= $this->themeBaseUrl; ?>css/main.css" /> |
main.css を編集しておくと、テーマによりデザインが切り替わることが確認できる。
最後に、新しく作成したテーマ uniquevision を有効にする。有効にするには、config/main.phpにテーマの名前を記述する。
(basePath)/protected/config/main.php
最後に、新しく作成したテーマ uniquevision を有効にする。有効にするには、config/main.phpにテーマの名前を記述する。
(basePath)/protected/config/main.php
return array( 'basePath'=>dirname(__FILE__).DIRECTORY_SEPARATOR.'..', 'name'=>'My Web Application', 'theme'=>'uniquevision', : |
clientScriptの設定によるテーマごとのJavaScriptとCSS
views/layouts/main.php 内に記述されたCSSのファイルパスは前述のようにテーマごとに切り替えることができた。では、clientScriptで指定するJavaScriptやCSSの場合はどうだろうか。例えば、すべてのテーマで共通に「jQuery Alert Dialogs」を使いたいとする。その上で、テーマ個別のJavaScriptも使いたいとする。
config/main.php で、以下のように定義してみた。
(basePath)/protected/config/main.php
return array( : 'components'=>[ : 'clientScript'=>[ 'packages'=> [ 'common' => [ 'baseUrl' => '', 'js' => [ 'js/jquery.alerts.js', 'js/sample.js' ], 'css' => [ 'css/jquery.alerts.css', ], ], 'uniquevision' => [ 'baseUrl' => 'themes/uniquevision/', 'js' => [ 'js/sample_uv.js' ], 'css' => [ ], ], ], ], : |
class Controller extends CController { : public function registerPackage($js = [], $css = []) { $depends = ['common']; if ($this->isThemeUsed()) { $depends []= Yii::app()->theme->name; } Yii::app()->clientScript->packages[Yii::app()->name] = [ 'baseUrl' => '', 'js' => $js, 'css' => $css, 'depends' => $depends ]; Yii::app()->clientScript->registerPackage(Yii::app()->name); } |
このメソッドをアクションから呼び出せば、config/main.phpに記述したJavaScriptとCSSがビューの<head>内に取り込まれる。アクションからの呼び出しは以下のとおり。
class SiteController extends Controller { public function actionIndex() { $this->registerPackage(); $this->render('index'); } |
デフォルトのテーマ用とuniquevisionテーマ用にそれぞれJavaScriptを用意し、jQuery Alert Dialogsでメッセージボックスを表示させるなどすると、どちらのテーマでも動作することを確認することができるだろう。
アクション個別で利用したいJavaScriptやCSSがある場合はどうすればいいだろうか。
上記のControllerクラスに定義したメソッド registerPackage() は、引数で追加のJavaScriptとCSSを指定できるようにしてある。ここに必要なファイルを指定することにする。
public function actionIndex() { $basePath = $this->isThemeUsed() ? 'themes/' . Yii::app()->theme->name . '/' : ''; $js = [ $basePath . 'js/index.js' ]; $css = []; $this->registerPackage($js, $css); $this->render('index'); } |
ここまで、ページのヘッダー/フッター部分やJavaScript、CSSの切り替えをしてきたが、この後はビューの内容をテーマで切り替えてみる。
レイアウトによる段組み
Yiiは初期プロジェクトで2種類の段組みを指定できるようになっている。これはControllerクラスの変数 $layout で指定されている。class Controller extends CController { : public $layout='//layouts/column1'; : public $menu=array(); : |
$layout '//layouts/column2' を指定すると、2列の段組みでページが表示されるようになる。2列の場合、左側の列がメインのコンテンツを表示するエリア、右側の列がサイドバーのエリアになっている。
簡単に2列の段組みにできるのだが、通常、ビューで内容を描画できるのは左側のメインコンテンツ部分だけで、右側のサイドバーには上記Controllerクラスの変数 $menu で指定されるメニュー一覧で固定されてしまっている。任意の内容を表示させたくても、それを引き渡すためのパラメータが用意されていない。さて、どうしたものか。
実験として、初期プロジェクトのテーマでのログイン画面は1列、uniquevision テーマのログイン画面は2列の段組みとしてみよう。uniquevision テーマでは、サイドバー側にログイン用入力フォームを設置する。
ではまず、2列にした場合にサイドバーに描画させる内容をビューに引き渡すパラメータをControllerクラスに用意する。
class Controller extends CController { : public $sidebarParams = null; : |
次に、uniquevision テーマの2列用レイアウトのファイルをコピーする。
(basePath)/protected/views/layouts/column2.php
↓
(basePath)/themes/uniquevision/views/layouts/column2.php
2列の場合、サイドバー側はパーシャルで描画するようにしよう。パーシャルの名前と、それに引き渡すパラメータは $sidebarParams で引き渡す。
(basePath)/themes/uniquevision/views/layouts/column2.php
<?php $this->beginContent('//layouts/main'); ?> <div class="span-19"> <div id="content"> <?php echo $content; ?> </div><!-- content --> </div> <div class="span-5 last"> <div id="sidebar"> <?php $this->renderPartial($this->sidebarParams['partial']); ?> </div><!-- sidebar --> </div> <?php $this->endContent(); ?> |
アクションでは以下のようにする。
class SiteController extends Controller { public function actionLogin() { $model=new LoginForm; : if ($this->isThemeUsed()) { if ('uniquevision' == Yii::app()->theme->name) { $this->layout = '//layouts/column2'; $this->sidebarParams = [ 'partial' => '_login_form', 'model' => $model ]; } } $this->render('login',array('model'=>$model)); } |
テーマが指定されている場合、2列の段組みにして、Controllerクラスの変数 $sidebarParams にパーシャルの名前と、ログイン用入力フォームで使用するモデルをセットしておく。それぞれ、column2.php と、そこから呼び出されるパーシャル(上記の場合は _login_form.php) で参照される。
左側のメインコンテンツはデフォルトのテーマの場合も、uniquevisionテーマの場合も login という名前のビューを描画する。ただし、デフォルトのテーマではメインコンテンツ側(loginビュー)に入力フォームを設置し、uniquevisionテーマではサイドバー側(_login_formパーシャルビュー)に入力フォールを設置。
これで、段組みが1列の場合でも2列の場合でもログイン用入力フォームを動作させることができた。
なお、layouts/column1.php は uniquevision テーマにコピーしていないが、ログイン画面以外の画面が初期プロジェクトと同様に1列の段組みで表示される。つまり、レイアウトやビューのファイルがテーマに定義されていない場合は、デフォルトのテーマ(protected/views以下のファイル)が使用され、差分となるファイルだけをテーマに定義すればよいことが分かる。
おわり
テーマもレイアウトもWebページの見栄えを制御するものだが、うまく使えば見栄えを切り替えるための分岐処理などは書かなくてもよくなりそうだ。しかし、テーマごとに同じ内容のソースファイルを設置してしまうとメンテナンス性がよくないので、どのように利用するかはプロジェクトごとに検討する必要がある。ちょうどこの記事を書いている時に、あるプロジェクトで本番環境、ステージング環境、開発環境で画面の背景色を切り替えたい、という要件があり、一部テーマを利用した。活用できるケースは意外に多いのかもしれない。
0 件のコメント:
コメントを投稿