<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Apelog &#187; code</title>
	<atom:link href="http://blog.apecell.com/tag/code/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.apecell.com</link>
	<description>Apecell's blog by Design</description>
	<lastBuildDate>Tue, 22 Jun 2010 07:08:30 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>TemplateLiteは割り当てたオブジェクトにアクセスできない</title>
		<link>http://blog.apecell.com/2008/01/01/id/29</link>
		<comments>http://blog.apecell.com/2008/01/01/id/29#comments</comments>
		<pubDate>Mon, 31 Dec 2007 18:00:00 +0000</pubDate>
		<dc:creator>design</dc:creator>
				<category><![CDATA[Develop]]></category>
		<category><![CDATA[Program]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[template]]></category>

		<guid isPermaLink="false">http://blog.apecell.com/1970/01/01/29</guid>
		<description><![CDATA[Smarty互換でSmartyより軽量なTemplateLiteを使うに書いた後適度に使っていたところ、Smartyと決定的な差異を発見。

TemplateLiteはオブジェクトにアクセスできない。はじめからオブジェクトをアサインしないような作りにしておけば問題無いものの、既にSmartyでオブジェクトをアサインして使っている場合、テンプレートエンジンをそのまま差し替えるわけにはいかないので注意。
例えば、Zend_Validateのエラー結果を纏めて以下のようなクラスに渡したオブジェクトをアサインしているとする。

&#60;?php
/**
 * @package Sample
 */
class Sample_Validate_Result {
    /**
     * @var array
     */
    private $_errors;

    /**
     * @param array $errors
     */
    public function __construct(array $errors) {
   [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.apecell.com/archives/318974.html" target="_blank">Smarty互換でSmartyより軽量なTemplateLiteを使う</a><br />に書いた後適度に使っていたところ、Smartyと決定的な差異を発見。</p>
</p>
<p>TemplateLiteはオブジェクトにアクセスできない。はじめからオブジェクトをアサインしないような作りにしておけば問題無いものの、既にSmartyでオブジェクトをアサインして使っている場合、テンプレートエンジンをそのまま差し替えるわけにはいかないので注意。</p>
<p>例えば、Zend_Validateのエラー結果を纏めて以下のようなクラスに渡したオブジェクトをアサインしているとする。</p>
<pre name="code" class="php">
&lt;?php
/**
 * @package Sample
 */
class Sample_Validate_Result {
    /**
     * @var array
     */
    private $_errors;

    /**
     * @param array $errors
     */
    public function __construct(array $errors) {
        $this-&gt;_errors = $errors;
    }

    /**
     * エラーの有無を返す
     *
     * @param string $name
     * @return mixed
     */
    public function __get($name) {
        if (array_search($name, $this-&gt;_errors) !== false) {
            return true;
        } elseif (!array_key_exists($name, $this-&gt;_errors)) {
            return false;
        } else {
            return new Sample_Validate_Result($this-&gt;_errors[$name]);
        }
    }
}
</pre>
<p>その状態でテンプレートからアサインしたオブジェクトのメンバ変数にアクセスしようとTemplateLiteの場合、evalに失敗してエラー。</p>
<pre name="code" class="php">
&lt;?php
// Validatorから帰ってくるエラー例
$errorArray = array(
    'nickname'    =&gt; array('isEmpty'),
    'mailaddress' =&gt; array('tooLong', 'invalid')
);

// コントローラー内でエラーオブジェクトをアサイン
$this-&gt;view-&gt;errors = new Sample_Validate_Result($errorsArray);

// Smartyならこれができる
{ if $errors-&gt;nickname-&gt;isEmpty }
</pre>
<p>完全互換だと思っていて差し替えが後になってしまうと、影響範囲も広がってしまうので記憶の片隅にでも。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.apecell.com/2008/01/01/id/29/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHPエラー発生時に例外を投げる</title>
		<link>http://blog.apecell.com/2007/11/11/id/22</link>
		<comments>http://blog.apecell.com/2007/11/11/id/22#comments</comments>
		<pubDate>Sat, 10 Nov 2007 16:47:45 +0000</pubDate>
		<dc:creator>design</dc:creator>
				<category><![CDATA[Develop]]></category>
		<category><![CDATA[Program]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.apecell.com/2007/11/11/22</guid>
		<description><![CDATA[処理が継続されるエラー発生時に例外を投げるというもの。エラー処理を例外で統一させる事が出来る。


class IOException extends Exception {}

function errorHandler($errno, $errstr, $errfile, $errline) {
    if (false !== substr('failed to open stream', $errstr)) {
        throw new IOException($errstr, $errno);
    }
    throw new Exception($errstr, $errno);
}

set_error_handler('errorHandler');

try {
    file_put_contents('cosmos:\\1.txt', 'asdf');
} catch (IOException $e) {
  [...]]]></description>
			<content:encoded><![CDATA[<p>処理が継続されるエラー発生時に例外を投げるというもの。エラー処理を例外で統一させる事が出来る。</p>
<blockquote title="PHP coding tip: Convert notices and warnings into Exceptions" cite="http://www.alexatnet.com/node/23">
<pre name="code" class="php">
class IOException extends Exception {}

function errorHandler($errno, $errstr, $errfile, $errline) {
    if (false !== substr('failed to open stream', $errstr)) {
        throw new IOException($errstr, $errno);
    }
    throw new Exception($errstr, $errno);
}

set_error_handler('errorHandler');

try {
    file_put_contents('cosmos:\\1.txt', 'asdf');
} catch (IOException $e) {
    echo 'IO exception: ' . $e-&gt;getMessage();
} catch (Exception $e) {
    echo 'Unknown exception: ' . $e-&gt;getMessage();
}
</pre>
<p><cite><a href="http://www.alexatnet.com/node/23">PHP coding tip: Convert notices and warnings into Exceptions</a></cite></p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://blog.apecell.com/2007/11/11/id/22/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHPでOpenIDによるログイン処理</title>
		<link>http://blog.apecell.com/2007/10/28/id/20</link>
		<comments>http://blog.apecell.com/2007/10/28/id/20#comments</comments>
		<pubDate>Sat, 27 Oct 2007 15:00:00 +0000</pubDate>
		<dc:creator>design</dc:creator>
				<category><![CDATA[Develop]]></category>
		<category><![CDATA[Program]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[openid]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[zendframework]]></category>

		<guid isPermaLink="false">http://blog.apecell.com/1970/01/01/20</guid>
		<description><![CDATA[PHPでのOpenIDを利用したログイン認証の実装について。
OpenIDの概要は調べるかWebの分散ID認証システムについてにて。とりあえず実装してみて、という感じなので間違っていたら指摘お願いします。
OpenID EnabledのPHP用ライブラリを利用する。
他にもVidentity.orgやPHP ClassesにOpenIDのライブラリはあるが更新が止まっていたり簡易的なものだったりするのでOpenID Enabledのものを使用。
実行環境

WindowsXP SP2
PHP 5.2.3
PHP OpenID Library 2.0.0-rc2

PHP OpenID Library 1.x.x系統と若干実装が違うので互換性は無い。
サンプルを動かしてみる
ライブラリを解凍するとexamplesディレクトリがある、コンシューマ側なのでexamples/consumerを実行してみる。
OpenID関連で生成されるファイル格納ディレクトリが作れないとエラーが出た。デフォルトで「/tmp/_php_consumer_test」に作るようになっているので「/tmp」を作ってやる（Windowsで「/tmp」は、Dドライブで実行しているなら「D:\tmp」）。
次にOpenIDで使用する暗号生成部でエラーになった。追ってみるとデフォルトで「/dev/urandom」を使用するようになっている。「/dev/urandom」はカーネル乱数ジェネレータでWindowsには無い。
定数Auth_OpenID_RAND_SOURCEがNULLの場合、PHP内で乱数を生成するのでWindowsの場合は先に以下のようにNULLで定数定義する。

&#60;?php
// Windowsの場合カーネル乱数ジェネレータを使用しない
if (!strncmp(PHP_OS, 'WIN', 3)) {
    define('Auth_OpenID_RAND_SOURCE', NULL);
}

この2点の変更で動作確認は出来た。確認にはOpenID.ne.jpを使用。
OpenIDでの認証をアプリケーションに組み込むために
組み込む為には入力されたIDとアプリケーションのデータ（会員ID）を結び付ける必要がある。
先に会員登録としてOpenIDを入力させて登録させる形式より、先に認証をおこない認可された場合ログインフラグを立ててアプリケーションデータと比較し、無ければ入力したIDと取得したデータ（ニックネームやメールアドレス）を登録する方がOpenIDで管理している情報を利用できるのでスマート。
取得したデータ以外に必要な情報があれば、認証時に登録画面に遷移。OpenID1.0で登録できる情報はE-mail、ニックネーム、氏名、性別、国籍、郵便番号、言語、生年月日。OpenID2.0ではプロトコルにXRIが使えてもう少し詳細な情報がやりとりできるらしい。
ユーザーから入力されたIDと結果として取得できるIDは違う場合があるので認証リダイレクト前に一度セッションに格納してから認可後にセッションから取得した値をアプリケーション側に登録する必要がある。
Zend Frameworkで使用
軽くラッピングしてZend Frameworkで使ってみた。
とりあえずザッと書いて動かしてみたものを以下に。
Zend_Controller_Actionを継承してpreDispatch()に認証処理を実装、実際のControllerはこのクラスを継承する。デフォルトで認証をおこなうようになっているので、認証が必要ない場合は$this-&#62;checkLogin = false;でオーバーライド。

&#60;?php
class Sample_Controller_Action_Base extends Zend_Controller_Action {
    /**
     * @var bool ログインチェックフラグ
     */
    protected $checkLogin = true;

  [...]]]></description>
			<content:encoded><![CDATA[<p>PHPでのOpenIDを利用したログイン認証の実装について。</p>
<p>OpenIDの概要は調べるか<a href="http://blog.apecell.com/archives/310800.html" target="_blank">Webの分散ID認証システムについて</a>にて。とりあえず実装してみて、という感じなので間違っていたら指摘お願いします。</p>
<p><a href="http://www.openidenabled.com/php-openid/" target="_blank">OpenID Enabled</a>のPHP用ライブラリを利用する。</p>
<p>他にも<a href="http://videntity.org/openid/" target="_blank">Videntity.org</a>や<a href="http://www.phpclasses.org/" target="_blank">PHP Classes</a>にOpenIDのライブラリはあるが更新が止まっていたり簡易的なものだったりするのでOpenID Enabledのものを使用。</p>
<h4>実行環境</h4>
<ul>
<li>WindowsXP SP2</li>
<li>PHP 5.2.3</li>
<li>PHP OpenID Library 2.0.0-rc2</li>
</ul>
<p>PHP OpenID Library 1.x.x系統と若干実装が違うので互換性は無い。</p>
<h4>サンプルを動かしてみる</h4>
<p>ライブラリを解凍するとexamplesディレクトリがある、コンシューマ側なのでexamples/consumerを実行してみる。</p>
<p>OpenID関連で生成されるファイル格納ディレクトリが作れないとエラーが出た。デフォルトで「/tmp/_php_consumer_test」に作るようになっているので「/tmp」を作ってやる（Windowsで「/tmp」は、Dドライブで実行しているなら「D:\tmp」）。</p>
<p>次にOpenIDで使用する暗号生成部でエラーになった。追ってみるとデフォルトで「/dev/urandom」を使用するようになっている。「/dev/urandom」はカーネル乱数ジェネレータでWindowsには無い。</p>
<p>定数Auth_OpenID_RAND_SOURCEがNULLの場合、PHP内で乱数を生成するのでWindowsの場合は先に以下のようにNULLで定数定義する。</p>
<pre name="code" class="php">
&lt;?php
// Windowsの場合カーネル乱数ジェネレータを使用しない
if (!strncmp(PHP_OS, 'WIN', 3)) {
    define('Auth_OpenID_RAND_SOURCE', NULL);
}
</pre>
<p>この2点の変更で動作確認は出来た。確認には<a href="http://www.openid.ne.jp/">OpenID.ne.jp</a>を使用。</p>
<h4>OpenIDでの認証をアプリケーションに組み込むために</h4>
<p>組み込む為には入力されたIDとアプリケーションのデータ（会員ID）を結び付ける必要がある。</p>
<p>先に会員登録としてOpenIDを入力させて登録させる形式より、先に認証をおこない認可された場合ログインフラグを立ててアプリケーションデータと比較し、無ければ入力したIDと取得したデータ（ニックネームやメールアドレス）を登録する方がOpenIDで管理している情報を利用できるのでスマート。</p>
<p>取得したデータ以外に必要な情報があれば、認証時に登録画面に遷移。OpenID1.0で登録できる情報はE-mail、ニックネーム、氏名、性別、国籍、郵便番号、言語、生年月日。OpenID2.0ではプロトコルにXRIが使えてもう少し詳細な情報がやりとりできるらしい。</p>
<p>ユーザーから入力されたIDと結果として取得できるIDは違う場合があるので認証リダイレクト前に一度セッションに格納してから認可後にセッションから取得した値をアプリケーション側に登録する必要がある。</p>
<h4>Zend Frameworkで使用</h4>
<p>軽くラッピングしてZend Frameworkで使ってみた。</p>
<p>とりあえずザッと書いて動かしてみたものを以下に。</p>
<p>Zend_Controller_Actionを継承してpreDispatch()に認証処理を実装、実際のControllerはこのクラスを継承する。デフォルトで認証をおこなうようになっているので、認証が必要ない場合は$this-&#62;checkLogin = false;でオーバーライド。</p>
<pre name="code" class="php">
&lt;?php
class Sample_Controller_Action_Base extends Zend_Controller_Action {
    /**
     * @var bool ログインチェックフラグ
     */
    protected $checkLogin = true;

    /**
     * @var Zend_Session
     */
    public $session;

    /**
     * 初期化
     */
    public function init() {
        $this-&gt;session = new Zend_Session_Namespace();
    }

    /**
     * preDispatch
     */
    public function preDispatch() {
        // ログイン認証
        if ($this-&gt;checkLogin &amp;&amp; !$this-&gt;session-&gt;login) {
            $auth = new Sample_Auth_OpenID();

            if (!empty($_REQUEST['openid_url'])) {
                $this-&gt;session-&gt;openid_url = $_REQUEST['openid_url'];
                $process_path = '/home'; // 適当に遷移に合わせて

                $auth-&gt;authenticate($_REQUEST['openid_url'], $process_path);
            }

            // 認可結果判別
            if ($auth-&gt;checkResult()) {
                // 認可時
                $this-&gt;session-&gt;login = true;

                echo $this-&gt;session-&gt;openid_url;
                print_r($auth-&gt;getContents());
            } else {
                // 拒否/失敗
                $this-&gt;session-&gt;destroy();
                echo 'Auth failed...';
            }
        }
    }
}
</pre>
<p>で、以下がOpenIDの認証用クラス。といってもexample纏めた程度。</p>
<pre name="code" class="php">
&lt;?php
class Sample_Auth_OpenID {
    /**
     * @var Auth_OpenID_Consumer
     */
    protected $_consumer = NULL;

    /**
     * OpenID関連で生成されるファイル格納ディレクトリパス
     * @var string
     */
    public $_store_path = &quot;/tmp/_php_consumer&quot;;

    /**
     * 承認フラグ
     * @var bool
     */
    protected $_valid = false;

    /**
     * 認証レスポンス
     * @var object
     */
    protected $_response = NULL;

    /**
     * 取得内容
     * @var array
     */
    protected $_contents = array();

    /**
     * コンストラクタ
     */
    public function __construct() {
        // Windowsの場合カーネル乱数ジェネレータを使用しない
        if (!strncmp(PHP_OS, 'WIN', 3)) {
            define('Auth_OpenID_RAND_SOURCE', NULL);
        }

        if (!file_exists($this-&gt;_store_path) &amp;&amp; !mkdir($this-&gt;_store_path)) {
            die(&quot;Could not create the FileStore directory&quot;);
        }

        $this-&gt;_consumer = new Auth_OpenID_Consumer(new Auth_OpenID_FileStore($this-&gt;_store_path));

        require_once &quot;Auth/OpenID/SReg.php&quot;;
    }
    /**
     * OpenIDによる認証
     *
     * @param string $checkid
     * @param string $process_path
     * @return bool 認証失敗時
     */
    public function authenticate($checkid, $process_path) {
        // 接続スキーマ
        $scheme = 'http';
        $scheme = (isset($_SERVER['HTTPS']) and $_SERVER['HTTPS'] == 'on') ? 'https' : 'http';

        // 承認URL
        $trust_root = sprintf(&quot;$scheme://%s:%s%s&quot;,
        $_SERVER['SERVER_NAME'], $_SERVER['SERVER_PORT'],
        dirname($_SERVER['PHP_SELF']));

        // 承認後リダイレクト先URL
        $process_url = $trust_root . $process_path;

        // 認証開始
        $auth_request = $this-&gt;_consumer-&gt;begin($checkid);

        // 入力されたOpenIDが使用出来ず失敗
        if (!$auth_request) {
            return false;
        }

        // 認証時に取得するデータ
        $sreg_request = Auth_OpenID_SRegRequest::build(
                                     // Required
                                     array('nickname'),
                                     // Optional
                                     array('fullname', 'email'));

        if ($sreg_request) {
            $auth_request-&gt;addExtension($sreg_request);
        }

        // 承認の為リダイレクト
        if ($auth_request-&gt;shouldSendRedirect()) {
            $redirect_url = $auth_request-&gt;redirectURL($trust_root, $process_url);

            // If the redirect URL can't be built, display an error
            // message.
            if (Auth_OpenID::isFailure($redirect_url)) {
                displayError(&quot;Could not redirect to server: &quot; . $redirect_url-&gt;message);
            } else {
                // Send redirect.
                header(&quot;Location: &quot;.$redirect_url);
                exit;
            }
        }
    }

    /**
     * 認証結果判別
     *
     * @return bool 認証可否
     */
    public function checkResult() {
        $this-&gt;_response = $this-&gt;_consumer-&gt;complete();

        // 認可時のみ値セット
        if ($this-&gt;_response-&gt;status == Auth_OpenID_SUCCESS) {
            $this-&gt;_valid = true;
            $this-&gt;_contents = Auth_OpenID_SRegResponse::fromSuccessResponse($this-&gt;_response)-&gt;contents();

            $id = ($this-&gt;_response-&gt;endpoint-&gt;canonicalID) ? $this-&gt;_response-&gt;endpoint-&gt;canonicalID : $this-&gt;_response-&gt;identity_url;
        }

        return $this-&gt;isValid();
    }

    /**
     * @var bool 認可結果
     */
    public function isValid() {
        return $this-&gt;_valid;
    }

    /**
     * @return array 取得情報
     */
    public function getContents() {
        return $this-&gt;_contents;
    }
}
</pre>
<p>認証APIやプロトコル仕様が乱立してるけど何が主流になるやら。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.apecell.com/2007/10/28/id/20/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Smarty互換でSmartyより軽量なTemplateLiteを使う</title>
		<link>http://blog.apecell.com/2007/10/19/id/18</link>
		<comments>http://blog.apecell.com/2007/10/19/id/18#comments</comments>
		<pubDate>Thu, 18 Oct 2007 15:00:00 +0000</pubDate>
		<dc:creator>design</dc:creator>
				<category><![CDATA[Develop]]></category>
		<category><![CDATA[Program]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[template]]></category>
		<category><![CDATA[zendframework]]></category>

		<guid isPermaLink="false">http://blog.apecell.com/1970/01/01/18</guid>
		<description><![CDATA[SmartyはPHPのテンプレートエンジンでは最も有名で利用者も多いが重い。
TemplateLiteはLGPLライセンスのSmarty互換テンプレートエンジンでSmartyより早いとのこと。PHP5.1.1でSmartyとのベンチマーク比較を見る限りテンプレートで色々やってると結構差が出そう。
公式に書かれている、「TemplateLiteを使うべき7つの理由（意訳）」

Smartyよりコンパイルが早い
Smartyより表示が速い
Smartyと比較してメモリ使用量が少ない
Smartyの機能のほとんどをサポート
Smartyの代替となる
各リリースに合わせて機能追加される
活発な開発プロジェクト

6.の「各リリース」というのはSmartyに合わせてという事かな。気になるなら原文参照。
使い方もSmartyと同じなのでSmartyの重さが気になっているなら丁度良い代替になりそう。ZendFrameworkのViewとして使う場合も、Smartyの部分をTemplateLiteに置き換えればそのまま動作する。
単純なページだとそこまで差が出ないので、純粋にincludeのコストが気になる場合はSimplateなどの PHP Extention なテンプレートエンジンを使った方が良い。
以下ZendFrameworkのViewRenderer用クラス。ZendFrameworkの別テンプレートエンジン使用方法はZend FrameworkのViewをSmartyに変更するにはを参照。

&#60;?php
require_once 'Zend/View/Interface.php';
require_once 'class.template.php';

class Sample_View_TemplateLite implements Zend_View_Interface
{
    /**
     * TemplateLite object
     * @var Template_Lite
     */
    protected $_templateLite;

    /**
     * コンストラクタ
     *
   [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://smarty.php.net/" target="_blank">Smarty</a>はPHPのテンプレートエンジンでは最も有名で利用者も多いが重い。</p>
<p><a href="http://templatelite.sourceforge.net/" target="_blank">TemplateLite</a>はLGPLライセンスのSmarty互換テンプレートエンジンでSmartyより早いとのこと。PHP5.1.1で<a href="http://templatelite.sourceforge.net/images/templatelite_speed.gif" target="_blank">Smartyとのベンチマーク比較</a>を見る限りテンプレートで色々やってると結構差が出そう。</p>
<p>公式に書かれている、「TemplateLiteを使うべき7つの理由（意訳）」</p>
<ol>
<li>Smartyよりコンパイルが早い</li>
<li>Smartyより表示が速い</li>
<li>Smartyと比較してメモリ使用量が少ない</li>
<li>Smartyの機能のほとんどをサポート</li>
<li>Smartyの代替となる</li>
<li>各リリースに合わせて機能追加される</li>
<li>活発な開発プロジェクト</li>
</ol>
<p>6.の「各リリース」というのはSmartyに合わせてという事かな。気になるなら原文参照。</p>
<p>使い方もSmartyと同じなのでSmartyの重さが気になっているなら丁度良い代替になりそう。ZendFrameworkのViewとして使う場合も、Smartyの部分をTemplateLiteに置き換えればそのまま動作する。</p>
<p>単純なページだとそこまで差が出ないので、<em>純粋にincludeのコストが気になる場合</em>はSimplateなどの PHP Extention なテンプレートエンジンを使った方が良い。</p>
<p>以下ZendFrameworkのViewRenderer用クラス。ZendFrameworkの別テンプレートエンジン使用方法は<a href="http://blog.apecell.com/archives/264496.html" target="_blank">Zend FrameworkのViewをSmartyに変更するには</a>を参照。</p>
<pre name="code" class="php">
&lt;?php
require_once 'Zend/View/Interface.php';
require_once 'class.template.php';

class Sample_View_TemplateLite implements Zend_View_Interface
{
    /**
     * TemplateLite object
     * @var Template_Lite
     */
    protected $_templateLite;

    /**
     * コンストラクタ
     *
     * @param string $tmplPath
     * @param array $extraParams
     * @return void
     */
    public function __construct($tmplPath = null, $extraParams = array())
    {
        $this-&gt;_templateLite = new Template_Lite;

        if (null !== $tmplPath) {
            $this-&gt;setScriptPath($tmplPath);
        }

        foreach ($extraParams as $key =&gt; $value) {
            $this-&gt;_templateLite-&gt;$key = $value;
        }
    }

    /**
     * テンプレートエンジンオブジェクトを返します
     *
     * @return Template_Lite
     */
    public function getEngine()
    {
        return $this-&gt;_templateLite;
    }

    /**
     * テンプレートへのパスを設定します
     *
     * @param string $path パスとして設定するディレクトリ
     * @return void
     */
    public function setScriptPath($path)
    {
        if (is_readable($path)) {
            $this-&gt;_templateLite-&gt;template_dir = $path;
            return;
        }

        throw new Exception('無効なパスが指定されました');
    }

    /**
     * 現在のテンプレートディレクトリを取得します
     *
     * @return string
     */
    public function getScriptPaths()
    {
        return $this-&gt;_templateLite-&gt;template_dir;
    }

    /**
     * setScriptPath へのエイリアス
     *
     * @param string $path
     * @param string $prefix Unused
     * @return void
     */
    public function setBasePath($path, $prefix = 'Zend_View')
    {
        return $this-&gt;setScriptPath($path);
    }

    /**
     * setScriptPath へのエイリアス
     *
     * @param string $path
     * @param string $prefix Unused
     * @return void
     */
    public function addBasePath($path, $prefix = 'Zend_View')
    {
        return $this-&gt;setScriptPath($path);
    }

    /**
     * 変数をテンプレートに代入します
     *
     * @param string $key 変数名
     * @param mixed $val 変数の値
     * @return void
     */
    public function __set($key, $val)
    {
        $this-&gt;_templateLite-&gt;assign($key, $val);
    }

    /**
     * 代入された変数を取得します
     *
     * @param string $key 変数名
     * @return mixed 変数の値
     */
    public function __get($key)
    {
        return $this-&gt;_templateLite-&gt;get_template_vars($key);
    }

    /**
     * empty() や isset() のテストが動作するようにします
     *
     * @param string $key
     * @return boolean
     */
    public function __isset($key)
    {
        return (null !== $this-&gt;_templateLite-&gt;get_template_vars($key));
    }

    /**
     * オブジェクトのプロパティに対して unset() が動作するようにします
     *
     * @param string $key
     * @return void
     */
    public function __unset($key)
    {
        $this-&gt;_templateLite-&gt;clear_assign($key);
    }

    /**
     * 変数をテンプレートに代入します
     *
     * 指定したキーを指定した値に設定します。あるいは、
     * キー =&gt; 値 形式の配列で一括設定します
     *
     * @see __set()
     * @param string|array $spec 使用する代入方式 (キー、あるいは キー =&gt; 値 の配列)
     * @param mixed $value (オプション) 名前を指定して代入する場合は、ここで値を指定します
     * @return void
     */
    public function assign($spec, $value = null)
    {
        if (is_array($spec)) {
            $this-&gt;_templateLite-&gt;assign($spec);
            return;
        }

        $this-&gt;_templateLite-&gt;assign($spec, $value);
    }

    /**
     * 代入済みのすべての変数を削除します
     *
     * Zend_View に {@link assign()} やプロパティ
     * ({@link __get()}/{@link __set()}) で代入された変数をすべて削除します
     *
     * @return void
     */
    public function clearVars()
    {
        $this-&gt;_templateLite-&gt;clear_all_assign();
    }

    /**
     * テンプレートを処理し、結果を出力します
     *
     * @param string $name 処理するテンプレート
     * @return string 出力結果
     */
    public function render($name)
    {
        return $this-&gt;_templateLite-&gt;fetch($name);
    }
}
</pre>
<p>そのまんまですが。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.apecell.com/2007/10/19/id/18/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zend FrameworkのViewをSmartyに変更するには</title>
		<link>http://blog.apecell.com/2007/09/26/id/10</link>
		<comments>http://blog.apecell.com/2007/09/26/id/10#comments</comments>
		<pubDate>Tue, 25 Sep 2007 15:00:00 +0000</pubDate>
		<dc:creator>design</dc:creator>
				<category><![CDATA[Develop]]></category>
		<category><![CDATA[Howto]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[template]]></category>
		<category><![CDATA[zendframework]]></category>

		<guid isPermaLink="false">http://blog.apecell.com/1970/01/01/10</guid>
		<description><![CDATA[
標準のZend Viewより使い慣れたSmartyを使いたかったので差し替えてみることに。
Zend Framework: Document &#8211; 35.3.2. 別のテンプレートシステムの使用の項目だけだとSmartyは呼び出せても実際どうやってControllerに組み込むの？となってしまう。
とりあえずControllerのViewを差し替えてみるかと思いZend_Controller_Actionを継承してinit()でSmartyを差し替えた。

&#60;?php
class Sample_Controller_Action extends Zend_Controller_Action {
    /**
     * @var Zend_Config
     */
    protected $_config;

    public function init() {
        // コンフィグの読み込み
        [...]]]></description>
			<content:encoded><![CDATA[<div class="section">
<p>標準のZend Viewより使い慣れたSmartyを使いたかったので差し替えてみることに。</p>
<p><a href="http://framework.zend.com/manual/ja/zend.view.scripts.html#zend.view.scripts.templates" target="_blank">Zend Framework: Document &#8211; 35.3.2. 別のテンプレートシステムの使用</a>の項目だけだとSmartyは呼び出せても実際どうやってControllerに組み込むの？となってしまう。</p>
<p>とりあえずControllerのViewを差し替えてみるかと思いZend_Controller_Actionを継承してinit()でSmartyを差し替えた。</p>
<pre name="code" class="php">
&lt;?php
class Sample_Controller_Action extends Zend_Controller_Action {
    /**
     * @var Zend_Config
     */
    protected $_config;

    public function init() {
        // コンフィグの読み込み
        $this-&gt;_config = Zend_Registry::get('config');

        $extraParams = array(
            'compile_dir' =&gt; $config-&gt;smarty-&gt;compile_dir,
        );
        $this-&gt;view = new Sample_View_Smarty(null, $extraParams);
        $this-&gt;viewSuffix = 'tpl';
    }
}
</pre>
<p>が、上記だと上手くいかなかったわけで。</p>
<p>続いてActionHelperのViewRendererとしてSmartyを登録する方法で挑戦。</p>
<pre name="class" class="php">
<?php
$config = new Zend_Config_Ini('/path/to/config.ini', 'production');

$extraParams = array(
    'compile_dir' => $config->smarty->compile_dir,
);

// マニュアルに書かれているSmarty用View
$view = new Sample_View_Smarty(null, $extraParams);

$viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view);
$viewRenderer->setViewBasePathSpec($config->smarty->template_dir)
    ->setViewScriptPathSpec(':controller/:action.:suffix')
    ->setViewScriptPathNoControllerSpec(':action.:suffix')
    ->setViewSuffix('tpl');

Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);
</pre>
<p>上記方法で変更出来た。</p>
<p>これは継承したinit()では書かず、Controllerが呼ばれる前に書いた（Zend_Controller_Front::run()の前）。複数のテンプレートエンジン使い分ける事はほとんど無いと思われるのでこれで大丈夫かなと。</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.apecell.com/2007/09/26/id/10/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zend Frameworkで遊んでみる</title>
		<link>http://blog.apecell.com/2007/09/19/id/8</link>
		<comments>http://blog.apecell.com/2007/09/19/id/8#comments</comments>
		<pubDate>Tue, 18 Sep 2007 15:00:00 +0000</pubDate>
		<dc:creator>design</dc:creator>
				<category><![CDATA[Develop]]></category>
		<category><![CDATA[Program]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[zendframework]]></category>

		<guid isPermaLink="false">http://blog.apecell.com/1970/01/01/8</guid>
		<description><![CDATA[
自分用にコンディションシート的なものをZendFrameworkで作ろうと思い入れてみた。少し業務で使った事もあるけどSVNチェックアウト→OK!!な
状態だったので一からセットアップ。
一通りディレクトリ作ってphp.iniにパス通して
HelloWorld!!させてみる。問題無し。StaticなURLのルーティングを確かめる、以下が想定。
http://example.com/login
Controller =&#62; auth
Action =&#62; login

&#60;?php
$route = new
Zend_Controller_Router_Route_Static(
    'login',
     array('controller'=&#62; 'auth', 'action' =&#62;'login'));
$router-&#62;addRoute('login', $route);

これも問題無し。マニュアル通りだから問題無くて当然なんだけども。で、iniファイルにルーティング設定書こうと思って以下の様に書いてみた。
[production]
routes.login.type = "Zend_Controller_Router_Route_Static"
routes.login.route = "login"
routes.login.defaults.controller = "auth"
routes.login.defaults.action = "login"
読み込みはこんな感じ。

$config = new Zend_Config_Ini('../config/router.ini', 'production');
$router = new Zend_Controller_Router_Rewrite();
$router-&#62;addConfig($config, 'routes')

が、反映されてない。ルーターの値には同じものがセットされているというのに。
値が呼ばれてる所まで追ってみるかと思いつつ、先にガシガシコードに書いて後で精査してiniにしようとかなんとか。
そういえばPDT1.0がリリース。

]]></description>
			<content:encoded><![CDATA[<div class="section">
<p>自分用にコンディションシート的なものを<a href="http://framework.zend.com/" target="_blank">ZendFramework</a>で作ろうと思い入れてみた。少し業務で使った事もあるけどSVNチェックアウト→OK!!な</p>
<p>状態だったので一からセットアップ。</p>
<p>一通りディレクトリ作ってphp.iniにパス通して</p>
<p>HelloWorld!!させてみる。問題無し。StaticなURLのルーティングを確かめる、以下が想定。</p>
<pre>http://example.com/login
Controller =&gt; auth
Action =&gt; login</pre>
<pre name="code" class="php">
&lt;?php
$route = new
Zend_Controller_Router_Route_Static(
    'login',
     array('controller'=&gt; 'auth', 'action' =&gt;'login'));
$router-&gt;addRoute('login', $route);
</pre>
<p>これも問題無し。マニュアル通りだから問題無くて当然なんだけども。で、iniファイルにルーティング設定書こうと思って以下の様に書いてみた。</p>
<pre class="syntax-highlight"><span class="synSpecial">[production]</span>
<span class="synType">routes.login.type =</span> "Zend_Controller_Router_Route_Static"
<span class="synType">routes.login.route =</span> "login"
routes.login.defaults.controller = "auth"
<span class="synType">routes.login.defaults.action =</span> "login"</pre>
<p>読み込みはこんな感じ。</p>
<pre name="code" class="php">
$config = new Zend_Config_Ini('../config/router.ini', 'production');
$router = new Zend_Controller_Router_Rewrite();
$router-&gt;addConfig($config, 'routes')
</pre>
<p>が、反映されてない。ルーターの値には同じものがセットされているというのに。</p>
<p>値が呼ばれてる所まで追ってみるかと思いつつ、先にガシガシコードに書いて後で精査してiniにしようとかなんとか。</p>
<p>そういえばPDT1.0がリリース。</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.apecell.com/2007/09/19/id/8/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ほぼ年齢の計算式</title>
		<link>http://blog.apecell.com/2007/09/16/id/7</link>
		<comments>http://blog.apecell.com/2007/09/16/id/7#comments</comments>
		<pubDate>Sat, 15 Sep 2007 15:00:00 +0000</pubDate>
		<dc:creator>design</dc:creator>
				<category><![CDATA[Develop]]></category>
		<category><![CDATA[Howto]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://blog.apecell.com/1970/01/01/7</guid>
		<description><![CDATA[年齢の計算式は良く使う。
MySQLはマニュアルにも書いてあるけど。
SELECT (YEAR(CURDATE())-YEAR(`birth`)) - (RIGHT(CURDATE(), 5) &#62; RIGHT(`birth`, 5)) AS `age`
プログラムで書く場合
((現在日時-生年月日）/10000)切り上げ
$birth = 19830221;
echo (int) ((date('Ymd') - $birth) /10000);

となる。が「ほぼ」年齢の計算式と書いたのは正確には「誕生日の前日が終了する瞬間」に年齢が加算されるので前日には年齢が上がっている。
利用する業務によってはその1日で大きな違いにもなる。以下のリンクに具体的な問題点などの指摘があるので留意。

ある地方公務員電算担当のナヤミ
「生年月日から年齢を計算する簡単な計算式」は使えるとは限らない


]]></description>
			<content:encoded><![CDATA[<p>年齢の計算式は良く使う。</p>
<p>MySQLは<a href="http://dev.mysql.com/doc/refman/4.1/ja/date-calculations.html" target="_blank">マニュアル</a>にも書いてあるけど。</p>
<pre class="syntax-highlight"><span class="synStatement">SELECT</span> (YEAR(CURDATE())-YEAR(`birth`)) - (RIGHT(CURDATE(), <span class="synConstant">5</span>) &gt; RIGHT(`birth`, <span class="synConstant">5</span>)) <span class="synSpecial">AS</span> `age`</pre>
<p>プログラムで書く場合</p>
<pre>((現在日時-生年月日）/10000)切り上げ</pre>
<pre class="syntax-highlight"><span class="synSpecial"><span class="synStatement">$</span><span class="synIdentifier">birth</span> <span class="synStatement">=</span> <span class="synConstant">19830221</span>;
<span class="synPreProc">echo</span> <span class="synSpecial">(</span><span class="synType">int</span><span class="synSpecial">)</span> <span class="synSpecial">((</span><span class="synIdentifier">date</span><span class="synSpecial">(</span>'<span class="synConstant">Ymd</span>'<span class="synSpecial">)</span> <span class="synStatement">-</span> <span class="synStatement">$</span><span class="synIdentifier">birth</span><span class="synSpecial">)</span> <span class="synStatement">/</span><span class="synConstant">10000</span><span class="synSpecial">)</span>;
</span></pre>
<p>となる。が「ほぼ」年齢の計算式と書いたのは正確には「誕生日の前日が終了する瞬間」に年齢が加算されるので前日には年齢が上がっている。</p>
<p>利用する業務によってはその1日で大きな違いにもなる。以下のリンクに具体的な問題点などの指摘があるので留意。</p>
<dl>
<dt>ある地方公務員電算担当のナヤミ</dt>
<dd><a href="http://d.hatena.ne.jp/alittlething/20070827/p1" target="_blank">「生年月日から年齢を計算する簡単な計算式」は使えるとは限らない</a></dd>
</dl>
</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.apecell.com/2007/09/16/id/7/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
