PHP: 2007年12月アーカイブ

XML Inclusions (XInclude)を使ったテンプレートのレイアウト方法はどうでしょうかというお話。

PHP でテンプレートと言えば生の PHP でぺたっと書くか、Smarty やらといったテンプレートエンジンを利用するのが一般的だと思います。このテンプレート、デザイナさんから見ると嫌な存在ではないでしょうか?テンプレート毎に文法を覚えたり、対応したエディタを用意したり。せっかく覚えるならいろんな言語で通用する技術がいいですよね。XSLT もいいですが、ちょっとひねくれて XInclude を使っちゃいましょう。

ここでは、PHP で XInclude に触れてみたいと思います。まず、デザイナさんに一枚の XHTML を渡します。

Template.xhtml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:xi="http://www.w3.org/2001/XInclude" xml:lang="ja-JPN">
    <head>
        <!-- この部分にヘッダを書いて下さいネ。 -->
        <!-- <link rel="stylesheet" type="text/css" href="" /> -->
        <!-- <script type="text/javascript" src=""></script> -->

        <xi:include href="Page.xhtml" xpointer="xmlns(xh=http://www.w3.org/1999/xhtml) xpointer(/xh:html/xh:head/*)">
            <xi:fallback>
                <!-- この部分は実行時にページ固有のヘッダに置き換えられます。 -->
                <title>デザイン中です</title>
            </xi:fallback>
        </xi:include>
    </head>
    
    <body>
        <xi:include href="Page.xhtml" xpointer="xmlns(xh=http://www.w3.org/1999/xhtml) xpointer(/xh:html/xh:body/*)">
            <xi:fallback>
                <!-- この部分は実行時にページ固有の本本に置き換えられます。 -->
                <!-- 本本はだいたい次の XHTML となります(CSS 確認用に使って下さいネ)。 -->
                <h1>本文</h1>
                <p>どうたらこうたら</p>
                <h2>概要</h2>
                <p>どんどこどんどん</p>
                <h2>以下略</h2>
                <p>...</p>
            </xi:fallback>
        </xi:include>
    </body>
</html>

xxxnyann-seiza.png

定数のような振る舞いをする array やオブジェクトが必要になるケースとはどのような場面でしょうか。 例えば、あるキャラクタの性格を array へ定義しておきそれを参照するケースにて、第三者によって後付設定を付加されたり書き換えられてしまい、 キャラクタが作者の意図しない方向へ進んでしまう可能性がある場合です。

<?php

/**
 * プロフィールを定義します。ここ以外で変更しちゃダメ!
 * 
 * @type array
 */
$profile = array(
        'image' => 'xxxnyann-zukai.png',
        'nickname' => 'モチ',
        'favorite' => 'お団子',
        'hobby' => '散歩',
        'skill' => 'じゃんけん',
        'option' => '井伊直政当世具足',
    );

$profile['favorite'] = 'お魚、お肉'; // な、何するだァー!
$profile['option'] = 'しっぽ'; // な、何するだァー!

?>

<table summary="ひこにゃんのプロフィールです。">
    <caption>ズバリ!これがひこにゃんだ!</caption>
    <thead>
        <tr>
            <th>いめーじ</th>
            <th>ふぃーちゃー</th>
            <th>すぺっく</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td rowspan="5"><img src="<?php echo htmlspecialchars($profile['image']); ?>" width="120" height="160" /></td>
            <td>ひこにゃんマウス</td>
            <td><?php echo htmlspecialchars($profile['favorite']); ?>をおもむろにむさぼるぞ!</td>
        </tr>
        <tr>
            <td>ひこにゃんハンド</td>
            <td><?php echo htmlspecialchars($profile['skill']); ?>でどんな逆境も順境に!</td>
        </tr>
        <tr>
            <td>ひこにゃんレッグ</td>
            <td><?php echo htmlspecialchars($profile['hobby']); ?>で鍛えた足腰で傾斜角60度の坂でもぐいぐいのぼる!</td>
        </tr>
        <tr>
            <td>ひこにゃんオプション</td>
            <td><?php echo htmlspecialchars($profile['option']); ?>がとても魅力的だぞ!</td>
        </tr>
    </tbody>
</table>
profile.png

これを防ぐ手立てとして、要素を変更できない array が欲しくなります。残念ながら PHP には読み取り専用の配列は用意されていないので、自作する必要があります。

xxnyann.png2007年も残すところ一ヶ月を切り、PHP 4 の開発・メンテナンスと、築城400年祭と、商標使用期限の終了が迫っています。既に PHP 5 への移行は済んだと思われますが、この機会にクラスを定義したファイルの読み込み方法について見直してみましょう。

クラスを定義したファイルを1ファイル1クラスで保存している場合、PHP 4 から使用できる手段として、コードの先頭で require_once() を使用して読み込んでいました。使用するクラスの数だけ列挙が必要なため、オブジェクト同士の協調を図るコードを書く場合など、非常に多くの手間が掛かります。
例えば…

<?php
/**
 * クリスマス・イヴ未明からクリスマス終日にかけてひこにゃんが一緒に居てくれます。
 */

// require_once() からクラス定義ファイルを相対パスで読めるようにして。
set_include_path(get_include_path() . PATH_SEPARATOR . '/path/to/my/');

require_once 'My/DateTime.php';
require_once 'My/TimeSpan.php';
require_once 'My/Schedule.php';
require_once 'My/HikonyannPool.php';
require_once 'My/NakanohitoNadoInaiException.php';
require_once 'My/PoolOverflowException.php';
require_once 'My/TrademarkExpiredException.php';


// 私「2007-12-24T00:00:00Z から」
$when = new My_DateTime(2007, 12, 23, 15, 0, 0);
// 私「二日間ほど」
$howlong = new My_TimeSpan(2, 0, 0, 0);
// 私「借りたいの!」
$schedule = new My_Schedule($when, $howlong);

// 私「ダメ?」
try
{
    $hikonyann = HikonyannPool::borrow($schedule); 
    echo $hikonyann->letEnjoy();
    
    /****
            /i     iヽ
  ワーワー     ((/□\))
           ソ_∠ニ二ス  キャーキャー
      ヽ○ノ ∠シ,, ・ェ・ )ゝ
        |○ノ  (   ) ヾ○ノ
        へ|  ○ ∪∪    |
         /> /|ヽ      lヽ
           ∧ 
     ****/
}
// 市「ダメ(中の人などいない的に)」
catch (My_NakanohitoNadoInaiException $e) 
{
    echo 'ひこにゃんもクリスマスを楽しんでいます。';
}
// 市「ダメ(着ぐるみ数が限界的に)」
catch (My_PoolOverflowException $e)
{
    echo 'ひこにゃんは忙しいです。';
}
// 市「ダメ(登録商標的に)」
catch (My_TrademarkExpiredException $e)
{
    echo '尻尾をつけたのが不味かったか!?';
}

?>

この膨大な require_once にうんざりした PHP 5 は、解決手段としてオブジェクトのオートローディングを用意しました。未定義のクラスが使用された時点で、__autoload() がユーザー定義されていれば引数にクラス名を与えて呼び出され、クラスを定義する機会が与えられます。
例えば…

このアーカイブについて

このページには、2007年12月以降に書かれたブログ記事のうちPHPカテゴリに属しているものが含まれています。

前のアーカイブはPHP: 2007年8月です。

次のアーカイブはPHP: 2008年1月です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

Powered by Movable Type 4.12