<?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; Program</title>
	<atom:link href="http://blog.apecell.com/category/program/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>Zend_MailのFromヘッダでDoCoMoから返信が出来ない</title>
		<link>http://blog.apecell.com/2008/05/31/id/39</link>
		<comments>http://blog.apecell.com/2008/05/31/id/39#comments</comments>
		<pubDate>Sat, 31 May 2008 09:10:17 +0000</pubDate>
		<dc:creator>design</dc:creator>
				<category><![CDATA[Develop]]></category>
		<category><![CDATA[Program]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[zendframework]]></category>

		<guid isPermaLink="false">http://blog.apecell.com/?p=39</guid>
		<description><![CDATA[Zend_Mailでメールする際のFromヘッダ作成時にメールアドレスのみ渡して名前を渡さない場合
"" &#60;foo@bar.com&#62;
の様な形で生成されてしまう。
この状態でDoCoMo宛にメール送信を行うとDoCoMo端末から返信が出来なかった（確認したのはD905とPROSOLID μ）
ダブルクォーテーションで囲われた所が無ければ返信が出来たのでFromヘッダ生成メソッド部を変更。

public function setFrom($email, $name = '')
{
    if ($this-&#62;_from === null) {
        $email = strtr($email,&#34;\r\n\t&#34;,'???');
        $this-&#62;_from = $email;

        $this-&#62;_storeHeader('From', $email, true);
    } else {
    [...]]]></description>
			<content:encoded><![CDATA[<p>Zend_Mailでメールする際のFromヘッダ作成時にメールアドレスのみ渡して名前を渡さない場合</p>
<pre>"" &lt;foo@bar.com&gt;</pre>
<p>の様な形で生成されてしまう。</p>
<p>この状態でDoCoMo宛にメール送信を行うとDoCoMo端末から返信が出来なかった（確認したのはD905とPROSOLID μ）</p>
<p>ダブルクォーテーションで囲われた所が無ければ返信が出来たのでFromヘッダ生成メソッド部を変更。</p>
<pre name="code" class="php">
public function setFrom($email, $name = '')
{
    if ($this-&gt;_from === null) {
        $email = strtr($email,&quot;\r\n\t&quot;,'???');
        $this-&gt;_from = $email;

        $this-&gt;_storeHeader('From', $email, true);
    } else {
        /**
         * Error
         */
    }
    return $this;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.apecell.com/2008/05/31/id/39/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>ZendFrameworkでfindAllBy{Field}メソッドを使う</title>
		<link>http://blog.apecell.com/2008/01/22/id/31</link>
		<comments>http://blog.apecell.com/2008/01/22/id/31#comments</comments>
		<pubDate>Mon, 21 Jan 2008 15:00:00 +0000</pubDate>
		<dc:creator>design</dc:creator>
				<category><![CDATA[Develop]]></category>
		<category><![CDATA[Program]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[zendframework]]></category>

		<guid isPermaLink="false">http://blog.apecell.com/1970/01/01/31</guid>
		<description><![CDATA[RailsやCakePHPなどのフレームワークではお馴染みのfindBy系メソッドをZendFrameworkで実装したいということで。
Zend_Db_Tableクラスを継承したMyZend_Db_Tableクラス内のマジックメソッドで実装し、ModelはMyZend_Db_Tableを継承する。

&#60;?php
class MyZend_Db_Table extends Zend_Db_Table {
    /**
     * 論理削除カラム名
     * @var string
     */
    private $_deleteCol = 'delete_time';

    /**
     * findAllBy[ColName]($value [, $flag])でデータアクセス
     *
     [...]]]></description>
			<content:encoded><![CDATA[<p>RailsやCakePHPなどのフレームワークではお馴染みのfindBy系メソッドをZendFrameworkで実装したいということで。</p>
<p>Zend_Db_Tableクラスを継承したMyZend_Db_Tableクラス内のマジックメソッドで実装し、ModelはMyZend_Db_Tableを継承する。</p>
<pre name="code" class="php">
&lt;?php
class MyZend_Db_Table extends Zend_Db_Table {
    /**
     * 論理削除カラム名
     * @var string
     */
    private $_deleteCol = 'delete_time';

    /**
     * findAllBy[ColName]($value [, $flag])でデータアクセス
     *
     * $flag = true で論理削除された行は除外して取得
     *
     * @param string $method
     * @param array  $args
     * @return Zend_Db_Table_Row_Abstract
     */
    public function __call($method, $args) {
        if (preg_match('/^findAllBy(\w+)?$/', $method, $matches)) {
            $field = strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', $matches[1]));

            $where = array();
            $where[&quot;`$field` = ?&quot;] = $args[0];

            if (isset($args[1]) &amp;&amp; $args[1] === true
                &amp;&amp; in_array($this-&gt;_deleteCol, $this-&gt;_cols)) {
                $where[] = &quot;`{$this-&gt;_deleteCol}` IS NULL&quot;;
            }
            return $this-&gt;fetchAll($where);
        }
        throw new Zend_Db_Table_Exception(&quot;Call undefine method $method()&quot;);
    }
}
</pre>
<p>これで<em>$model-&#62;findAllByName(&#8217;Design&#8217;);</em>のようにアクセスすれば<em>`name` = &#8216;Design&#8217;</em>という条件でのデータアクセスが可能になる。</p>
<p>データは論理削除する事が多いのでfindAllByName(&#8217;Design&#8217;, true)の形の呼び出しで<br /><em>`name` = &#8216;Design&#8217; AND `delete_time` IS NULL</em></p>
<p>有効な行のみ返すようにしている。</p>
<p>まぁそんな感じで移植実装がおこなわれていくわけです。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.apecell.com/2008/01/22/id/31/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<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/26/id/21</link>
		<comments>http://blog.apecell.com/2007/11/26/id/21#comments</comments>
		<pubDate>Sun, 25 Nov 2007 15:00:00 +0000</pubDate>
		<dc:creator>design</dc:creator>
				<category><![CDATA[Develop]]></category>
		<category><![CDATA[Program]]></category>
		<category><![CDATA[encrypt]]></category>
		<category><![CDATA[pear]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://blog.apecell.com/1970/01/01/21</guid>
		<description><![CDATA[ウノウラボ Unoh Labs: PHPで暗号化・復号あれこれに暗号化の話が出ていたので、追記する形で他にいくつか。
同じ記事を書いていた前のBlogが消えてしまったので流し書き程度に。
gnupg 関数
PHPからOpenPGPであるgnupg 関数を利用して鍵方式の暗号化がおこなえます。
gnupg関数を使用する為にPECLのgnupgモジュールが必要。
速度的にも以降の方法に比べて早い。PGP暗号化では一番最初に検討したい。
PEAR::Crypt_RSA
PEAR::Crypt_RSAパッケージで公開鍵暗号がおこなえる。
GMP, BigInt, BCMathの3種類が使え、速度は（GMP＞BigInt＞BCMath）でGMPを基準として（1倍＞5倍＞250倍）遅い。暗号化するものが少なければ問題無いものの、多くなると速度以外でも色々と問題がある。
動作環境はDebian / PHP5.2.0 / Crypt_RSA 1.2.0bで確認。

GMPを使うと暗号化時にメモリリーク（PHP自体）、復号は大丈夫。
BigIngを64bit環境で使うと暗号化できない（空文字になる）。

PEAR::Crypt_RSAを使うしか選択肢が無い状態で、3000レコード（1レコード１M）ほどのデータを各行暗号化してDBに入れ、しばらくして復元した時、テスト環境が32bitの本番環境が64bitで泣いた記憶があるので（結局分割してバックグラウンドでGMPで暗号化した）、そもそも環境が違うなんて･･･というのはおいておき、もしかしたら特有の問題かもしれませんが似たような環境で使う人は注意。
exec()でgpgコマンドを叩く
http://www.alt-php-faq.org/local/65/
もしかすると幾多もの外的要因によりこういった方法を選択せざるを得ない時もあるかもしれない。GnuPGが必要なのでインストールしておく。
とても重いので頻度が少ないならまだしも、多くなると実用には耐え切れない。既にGnuPGが入っている状態なら何も必要無いのでそういう点で利用は出来るかもしれない。
]]></description>
			<content:encoded><![CDATA[<p><a href="http://labs.unoh.net/2007/11/php_de_crypt.html" target="_blank">ウノウラボ Unoh Labs: PHPで暗号化・復号あれこれ</a><br />に暗号化の話が出ていたので、追記する形で他にいくつか。</p>
<p>同じ記事を書いていた前のBlogが消えてしまったので流し書き程度に。</p>
<h4>gnupg 関数</h4>
<p>PHPからOpenPGPである<a href="http://jp.php.net/manual/ja/ref.gnupg.php" target="_blank">gnupg 関数</a>を利用して鍵方式の暗号化がおこなえます。</p>
<p>gnupg関数を使用する為に<a href="http://pecl.php.net/package/gnupg" target="_blank">PECLのgnupgモジュール</a>が必要。</p>
<p>速度的にも以降の方法に比べて早い。PGP暗号化では一番最初に検討したい。</p>
<h4>PEAR::Crypt_RSA</h4>
<p><a href="http://pear.php.net/package/Crypt_RSA" target="_blank">PEAR::Crypt_RSA</a>パッケージで公開鍵暗号がおこなえる。</p>
<p>GMP, BigInt, BCMathの3種類が使え、速度は（GMP＞BigInt＞BCMath）でGMPを基準として（1倍＞5倍＞250倍）遅い。暗号化するものが少なければ問題無いものの、多くなると速度以外でも色々と問題がある。</p>
<p>動作環境はDebian / PHP5.2.0 / Crypt_RSA 1.2.0bで確認。</p>
<ul>
<li>GMPを使うと暗号化時にメモリリーク（PHP自体）、復号は大丈夫。</li>
<li>BigIngを64bit環境で使うと暗号化できない（空文字になる）。</li>
</ul>
<p>PEAR::Crypt_RSAを使うしか選択肢が無い状態で、3000レコード（1レコード１M）ほどのデータを各行暗号化してDBに入れ、しばらくして復元した時、テスト環境が32bitの本番環境が64bitで泣いた記憶があるので（結局分割してバックグラウンドでGMPで暗号化した）、そもそも環境が違うなんて･･･というのはおいておき、<em>もしかしたら特有の問題かもしれませんが似たような環境で使う人は注意</em>。</p>
<h4>exec()でgpgコマンドを叩く</h4>
<p><a href="http://www.alt-php-faq.org/local/65/" target="_blank">http://www.alt-php-faq.org/local/65/</a></p>
<p>もしかすると幾多もの外的要因によりこういった方法を選択せざるを得ない時もあるかもしれない。GnuPGが必要なのでインストールしておく。</p>
<p>とても重いので頻度が少ないならまだしも、多くなると実用には耐え切れない。既にGnuPGが入っている状態なら何も必要無いのでそういう点で利用は出来るかもしれない。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.apecell.com/2007/11/26/id/21/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Aptana Studio 1.0インストール</title>
		<link>http://blog.apecell.com/2007/11/19/id/24</link>
		<comments>http://blog.apecell.com/2007/11/19/id/24#comments</comments>
		<pubDate>Sun, 18 Nov 2007 15:00:00 +0000</pubDate>
		<dc:creator>design</dc:creator>
				<category><![CDATA[Develop]]></category>
		<category><![CDATA[Program]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[ide]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.apecell.com/1970/01/01/24</guid>
		<description><![CDATA[Ruby on Railsで共同開発をしようということになり、以前RoRのインストールだけはしたものの以降触ってないのでこれを機にRuby・RoRの勉強も兼ねて開発に参加してみる。

開発環境としてEclipseのRedRailsプラグインを使おうとしていたら、EclipseベースのAptana Studioというものが公開されていた（10/30にversion1.0）ので使ってみる事にする。あと、Aptana StudioのPHPプラグインをちょっと使ってみたかった。
Aptana Studioインストール
公式サイトからコミュニティ エディションをダウンロード。プロフェッショナルエディションはJSONエディタ、IEデバッグ機能、リモートプロジェクト作成機能、FTPS/SFTPサポート、レポートエンジン機能が使えて、優先サポートと最新開発版へのアクセスが可能らしい。
Aptana StudioはEclipse3.2ベースらしいのでPleiadesで日本語化する。ファイル名がEclipseとは違うのでPleiadesの設定はAptana.iniに書き、Aptana.exeを-cleanオプションで起動する。
Aptana.iniの最終行にdefault.splashを付けないと起動ロゴが変わる。

-name
Aptana
-vmargs
-Xmx384M
-Xms128M
-Djava.awt.headless=true
-XX:MaxPermSize=128m
-javaagent:plugins/jp.sourceforge.mergedoc.pleiades/pleiades.jar=default.splash

起動後、[ヘルプ]→[Aptana開始ページ]からPHPとRuby on Railsをインストール。RedRails（0.9.1）も問題無く日本語化されている。RedRailsはMylyn用のプラグインもあったりするので必要なら入れておくこと。
SVN用にSubversiveと、半角スペースが見えないエディタは嫌なのでJStyleもインストール。
設定
[ウィンドウ]→[設定]→[Rails]→[構成]でRailsとRakeのパス指定する。mongrel_railsを使いたい場合はここでパスを指定する、使わなければ空欄。
svn checkoutするなり、新しいRailsプロジェクトを作るなりで「RedRailsパースペクティブ」を開く。デフォルトで下部にあるサーバータブの追加ボタン（最小化ボタンの左）を押しプロジェクトで使用するサーバー・ポート・環境を指定。
この状態でサーバーの開始・停止、ジェネレーター、Rake、コンソール(script/console)がAptana Studioから使える。

とりあえずこんな感じで開発スタート。rails.vimも使ってみたいけど、とりあえずこれで。まずはRubyの書き方に慣れないと開発効率以前の問題かな。
PHP用のプラグインは、定義ジャンプも無いし補完も変数レベル（メソッドは無理）なので使う理由は今の所無さそう。
]]></description>
			<content:encoded><![CDATA[<p>Ruby on Railsで共同開発をしようということになり、以前RoRのインストールだけはしたものの以降触ってないのでこれを機にRuby・RoRの勉強も兼ねて開発に参加してみる。</p>
<p><a href="http://www.aptana.com" class="http-image" target="_blank"><img src="http://image.blog.livedoor.jp/apecell/imgs/4/8/4898d25c.png" class="http-image" alt="http://www.aptana.com"></a></p>
<p>開発環境としてEclipseのRedRailsプラグインを使おうとしていたら、Eclipseベースの<a href="http://www.aptana.com/" target="_blank">Aptana Studio</a>というものが公開されていた（10/30にversion1.0）ので使ってみる事にする。あと、Aptana StudioのPHPプラグインをちょっと使ってみたかった。</p>
<h4>Aptana Studioインストール</h4>
<p>公式サイトからコミュニティ エディションをダウンロード。プロフェッショナルエディションはJSONエディタ、IEデバッグ機能、リモートプロジェクト作成機能、FTPS/SFTPサポート、レポートエンジン機能が使えて、優先サポートと最新開発版へのアクセスが可能らしい。</p>
<p>Aptana StudioはEclipse3.2ベースらしいので<a href="http://mergedoc.sourceforge.jp/pleiades.html" target="_blank">Pleiades</a>で日本語化する。ファイル名がEclipseとは違うのでPleiadesの設定はAptana.iniに書き、Aptana.exeを-cleanオプションで起動する。</p>
<p>Aptana.iniの最終行にdefault.splashを付けないと起動ロゴが変わる。</p>
<pre>
-name
Aptana
-vmargs
-Xmx384M
-Xms128M
-Djava.awt.headless=true
-XX:MaxPermSize=128m
-javaagent:plugins/jp.sourceforge.mergedoc.pleiades/pleiades.jar=default.splash
</pre>
<p>起動後、<em>[ヘルプ]→[Aptana開始ページ]</em>からPHPとRuby on Railsをインストール。RedRails（0.9.1）も問題無く日本語化されている。RedRailsはMylyn用のプラグインもあったりするので必要なら入れておくこと。</p>
<p>SVN用に<a href="http://www.eclipse.org/subversive/" target="_blank">Subversive</a>と、半角スペースが見えないエディタは嫌なので<a href="http://mergedoc.sourceforge.jp/jstyle.html" target="_blank">JStyle</a>もインストール。</p>
<h4>設定</h4>
<p><em>[ウィンドウ]→[設定]→[Rails]→[構成]</em>でRailsとRakeのパス指定する。mongrel_railsを使いたい場合はここでパスを指定する、使わなければ空欄。</p>
<p>svn checkoutするなり、新しいRailsプロジェクトを作るなりで「RedRailsパースペクティブ」を開く。デフォルトで下部にあるサーバータブの追加ボタン（最小化ボタンの左）を押しプロジェクトで使用するサーバー・ポート・環境を指定。</p>
<p>この状態でサーバーの開始・停止、ジェネレーター、Rake、コンソール(script/console)がAptana Studioから使える。</p>
<p><a href="http://image.blog.livedoor.jp/apecell/imgs/c/7/c73b18a5.png" class="http-image" target="_blank"><img src="http://image.blog.livedoor.jp/apecell/imgs/c/7/c73b18a5.png" class="http-image" alt="http://image.blog.livedoor.jp/apecell/imgs/c/7/c73b18a5.png" width="159" height="107"></a></p>
<p>とりあえずこんな感じで開発スタート。<a href="http://www.vim.org/scripts/script.php?script_id=1567" target="_blank">rails.vim</a>も使ってみたいけど、とりあえずこれで。まずはRubyの書き方に慣れないと開発効率以前の問題かな。</p>
<p>PHP用のプラグインは、定義ジャンプも無いし補完も変数レベル（メソッドは無理）なので使う理由は今の所無さそう。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.apecell.com/2007/11/19/id/24/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>動的にｊQueryのCSSセレクタを確認できるサイト</title>
		<link>http://blog.apecell.com/2007/11/13/id/23</link>
		<comments>http://blog.apecell.com/2007/11/13/id/23#comments</comments>
		<pubDate>Tue, 13 Nov 2007 12:25:16 +0000</pubDate>
		<dc:creator>design</dc:creator>
				<category><![CDATA[Develop]]></category>
		<category><![CDATA[Program]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[tool]]></category>

		<guid isPermaLink="false">http://blog.apecell.com/2007/11/13/23</guid>
		<description><![CDATA[jQueryで使えるCSSセレクタを動的に確認できるサイトの紹介。

jQuery1.2.1（現時点で最新版）のセレクタを入力し、選択されたノードの背景をハイライトする。
複雑な選択対象が必要なら「Markup to test against」の内容が変更可能なので変更すればいい。
jQueryはいくつかの独自拡張セレクタも使う事が出来るので、使用可能なセレクタはjQueryマニュアル &#8211; API/1.2/Selectorsを見ながら試せばとても快適です。
快適なノード選択ライフを貴方に、jQuery。

Interactive jQuery selector tester
http://www.woods.iki.fi/interactive-jquery-tester.html

]]></description>
			<content:encoded><![CDATA[<p>jQueryで使えるCSSセレクタを動的に確認できるサイトの紹介。</p>
<p><a href="http://image.blog.livedoor.jp/apecell/imgs/5/d/5d912744.JPG" class="http-image" target="_blank"><img src="http://image.blog.livedoor.jp/apecell/imgs/5/d/5d912744.JPG" class="http-image" alt="http://image.blog.livedoor.jp/apecell/imgs/5/d/5d912744.JPG" width="692" height="349"></a></p>
<p>jQuery1.2.1（現時点で最新版）のセレクタを入力し、選択されたノードの背景をハイライトする。</p>
<p>複雑な選択対象が必要なら「Markup to test against」の内容が変更可能なので変更すればいい。</p>
<p>jQueryはいくつかの独自拡張セレクタも使う事が出来るので、使用可能なセレクタは<a href="http://docs.jquery.com/Selectors" target="_blank">jQueryマニュアル &#8211; API/1.2/Selectors</a>を見ながら試せばとても快適です。</p>
<p>快適なノード選択ライフを貴方に、jQuery。</p>
<dl>
<dt>Interactive jQuery selector tester</dt>
<dd><a href="http://www.woods.iki.fi/interactive-jquery-tester.html" target="_blank">http://www.woods.iki.fi/interactive-jquery-tester.html</a></dd>
</dl>
]]></content:encoded>
			<wfw:commentRss>http://blog.apecell.com/2007/11/13/id/23/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>なぜPHPのautoload()が早いのか</title>
		<link>http://blog.apecell.com/2007/10/22/id/19</link>
		<comments>http://blog.apecell.com/2007/10/22/id/19#comments</comments>
		<pubDate>Sun, 21 Oct 2007 15:00:00 +0000</pubDate>
		<dc:creator>design</dc:creator>
				<category><![CDATA[Develop]]></category>
		<category><![CDATA[Program]]></category>
		<category><![CDATA[performance]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[zendframework]]></category>

		<guid isPermaLink="false">http://blog.apecell.com/1970/01/01/19</guid>
		<description><![CDATA[__autoload()が早いというよりも、class_exists()に比べてrequre_once()、include_once()が遅いからというもの（クラスの読み込み判定の場合）。
通常__autoload()内でクラスの有無を調べて無ければ読み込みを行う。一度しか呼ばれないものならその場で読み込んだほうが早いが、複数回読み込み判定がおこなわれるものがある場合（Superクラスなど）一度autoload経由でclass_exists()の篩いにかけた方が良い。
PHP5のフレームワークではほとんどautoload系の読み込み実装がなされている事からも、その差は結構大きいので不特定回数読み込まれるファイルが多数ある場合は注意。
以下の動作環境で最も単純なクラス( class Sample{} )を1000回読み込んでインスタンス生成した場合、class_exists()で見つからなければrequire()と、常にrequire_once()だと100倍以上差があった。

PHP 5.2.3
WindowsXP SP2
AMD Athlon&#x2122;  64 Processor 3500+ 1.79GHz
2.00GB RAM

1000回require_once() &#8211; 0.450819秒

&#60;?php
for ($i=0;$i&#60;1000;$i++) {
    require_once('Sample.php');
    $sample = new Sample();
}


----------------------------------------------------
marker  time index            ex time         perct
----------------------------------------------------
Start   [...]]]></description>
			<content:encoded><![CDATA[<p>__autoload()が早いというよりも、class_exists()に比べてrequre_once()、include_once()が遅いからというもの（クラスの読み込み判定の場合）。</p>
<p>通常__autoload()内でクラスの有無を調べて無ければ読み込みを行う。一度しか呼ばれないものならその場で読み込んだほうが早いが、<em>複数回読み込み判定がおこなわれるものがある場合</em>（Superクラスなど）一度autoload経由でclass_exists()の篩いにかけた方が良い。</p>
<p>PHP5のフレームワークではほとんどautoload系の読み込み実装がなされている事からも、その差は結構大きいので不特定回数読み込まれるファイルが多数ある場合は注意。</p>
<p>以下の動作環境で最も単純なクラス( class Sample{} )を1000回読み込んでインスタンス生成した場合、class_exists()で見つからなければrequire()と、常にrequire_once()だと100倍以上差があった。</p>
<ul>
<li>PHP 5.2.3</li>
<li>WindowsXP SP2</li>
<li>AMD Athlon&#x2122;  64 Processor 3500+ 1.79GHz</li>
<li>2.00GB RAM</li>
</ul>
<h4>1000回require_once() &#8211; 0.450819秒</h4>
<pre name="code" class="php">
&lt;?php
for ($i=0;$i&lt;1000;$i++) {
    require_once('Sample.php');
    $sample = new Sample();
}
</pre>
<pre>
----------------------------------------------------
marker  time index            ex time         perct
----------------------------------------------------
Start   1193042528.49833500   -                0.00%
----------------------------------------------------
Stop    1193042528.94915400   0.450819       100.00%
----------------------------------------------------
</pre>
<h4>999回class_exists(), 1回require() &#8211; 0.003704秒</h4>
<pre name="code" class="php">
&lt;?php
for ($i=0;$i&lt;1000;$i++) {
    if (!class_exists('Sample', false)) {
        require('Sample.php');
    }
    $sample = new Sample();
}
</pre>
<pre>
----------------------------------------------------
marker  time index            ex time         perct
----------------------------------------------------
Start   1193042740.50069500   -                0.00%
----------------------------------------------------
Stop    1193042740.50439900   0.003704       100.00%
----------------------------------------------------
</pre>
<p>require()よりinclude()の方が早いのでinclude()にすればもう少し差は縮まるものの、なぜPHPのautoload()が早いかというとautoloadをclass_existsな実装で書く事が多いからであり、<em>autoloadの中で全てrequire_once()していたら別に早くない</em>という事。</p>
<p>クラス名の_をディレクトリとするPEAR風構成のオートローダーならZend FrameworkのZend_Loderがすぐ導入できます（Zend_LoaderとZend_Exceptionの2つで）。</p>
<p>環境違うと全然違うよ、な状態なら教えてください。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.apecell.com/2007/10/22/id/19/feed</wfw:commentRss>
		<slash:comments>0</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>
	</channel>
</rss>
