Delphi for PHP - Zend Frameworkを統合する: ZCache - パート1

By: Tomohiro Takahashi

Abstract: この記事は、José León氏のブログに掲載されたもので、連載記事「Zend Frameworkを統合する」のパート1です。

Zend Frameworkを統合する: ZCache (パート1)

この記事は、連載記事「Zend Frameworkを統合する」のパート1です。VCL for PHPのロードマップにある作業の1つにZend Frameworkとの統合を改善・強化するという項目がありますので、コードを開発しつつ、同時にブログに掲載しようと思います。

この記事では、Zend_CacheコンポーネントのラッパーであるZCacheコンポーネントを開発しようと思います。これは、出力内容や関数の呼び出しなどを含む特定のデータをキャッシュすることにより、アプリケーションのパフォーマンスを改善することを可能にするものです。

もちろん最初に行わなければならないのは、ラップする対象に関するドキュメントを読むことで、以下から参照できます:

https://framework.zend.com/manual/ja/zend.cache.html

以下、行うべき一般的なアイデアを簡単に挙げてみます:

  • ZCacheラッパーコンポーネントは、次の2つの部分(frontendとbackend)から成ります。これらは、キャッシュとして何が格納できるのか、情報を何処に格納するのかを決定します
  • Frontendプロパティは、次のいずれかの値をドロップダウンから選択します:
    • cfOutput: 出力内容をキャッシュします。Control基本クラスと統合されているかチェックし、出力内容をキャッシュするために使用します
    • cfFunction: コード中で使用される関数の呼び出しをキャッシュします
    • cfClass: コード中で使用されるクラスおよびstaticメソッドをキャッシュします
    • cfFile: コード中で使用されるファイルの内容をキャッシュします
    • cfPage: ページ全体をキャッシュします。これはVCL for PHPのPageクラスとうまく統合できそうです
  • Backendプロパティ
    • cbFile: キャッシュをファイルに格納する
    • cbSQLite: キャッシュをSQLiteデータベースに格納する
    • cbMemCached: インストールされているmemcachedを使用する
    • cbAPC: インストールされているAPCを使用する
    • cbZendPlatform: インストールされているZend Platformのキャッシュの仕組みを使用する
  • frontendとbackendは共通のプロパティを持ち、それらはZCacheオブジェクト自身のプロパティになる可能性が極めて大きく、frontendとbackendのタイプに応じたカスタムプロパティをグループ化されたプロパティとして設計することになるでしょう
  • frontendとbackendに関するメソッドをZCacheオブジェクトに追加し、それぞれfrontendとbackendに対応することになります

ラッパーを記述する

ではまず、ラッパーコンポーネントを記述して、IDEにインストールしましょう。それには、空のユニットを作成して、<VCL for PHPのフォルダ>\Zend に zcache.inc.php という名前で保存してください。

スタブコードをいくつか追加します。次のようになります:

<?php
require_once("vcl/vcl.inc.php");
use_unit("Zend/zcommon.inc.php");
use_unit("classes.inc.php");

use_unit("Zend/framework/library/Zend/Cache.php");

class ZCache extends Component
{
}

?>

zcommon.inc.phpユニットは、Zend Frameworkのセッションシステムを適切に初期化するコードを含んでおり、VCL for PHPと相性良く動作します。これはZend Frameworkの全てのラッパーから利用されます。その後、今回のラッパーを開発するために必要なコードを含んだCache.phpをインクルードします。

次に、zf.package.phpを開き、コンポーネントをIDEにインストールするためのコードを追加します:

registerComponents("Zend",array("ZCache"),"Zend/zcache.inc.php");

メニューから[コンポーネント] | [パッケージ]を選択し、「VCL for PHP components for Zend Framework」パッケージのチェックを外してから再度チェックを付けます。これでコンポーネントがツールパレットにインストールされます。新規にフォームを作成してそのコンポーネントをドロップするとアイコンで表示されます。これは、今回のコンポーネントがビジュアル向けの出力を持たず、直接Componentを継承しているためです。

プロパティを追加する

2つのプロパティ(FrontendとBackend)を追加する必要があります。このプロパティは複数の決められた値の中からいずれかの値を持ち、それらはオブジェクトインスペクタのドロップダウンリストで表示されます。ではそれぞれのプロパティの値を追加しましょう:

...............
use_unit("Zend/framework/library/Zend/Cache.php");

define('cfOutput','cfOutput');
define('cfFunction','cfFunction');
define('cfClass','cfClass');
define('cfFile','cfFile');
define('cfPage','cfPage');

define('cbFile','cbFile');
define('cbSQLite','cbSQLite');
define('cbMemcached','cbMemcached');
define('cbAPC','cbAPC');
define('cbZendPlatform','cbPlatform');

class ZCache extends Component
...............

次に、「Shift+Ctrl+Alt+U」を使用してプロパティを追加します。それぞれのデフォルト値を以下のように設定します:

protected $_frontend=cfOutput;

function getFrontend() { return $this->_frontend; }
function setFrontend($value) { $this->_frontend=$value; }
function defaultFrontend() { return cfOutput; }

protected $_backend=cbFile;

function getBackend() { return $this->_backend; }
function setBackend($value) { $this->_backend=$value; }
function defaultBackend() { return cbFile; }

Frontendの共通のプロパティを追加する

前述したようにfrontendには共通のプロパティ(その一覧)があります。では、それらをコンポーネントに追加しますが、VCL for PHPの一般的な命名規約に合わせてください:

protected $_enabled="1";

function getEnabled() { return $this->_enabled; }
function setEnabled($value) { $this->_enabled=$value; }
function defaultEnabled() { return "1"; }

protected $_prefix="";

function getPrefix() { return $this->_prefix; }
function setPrefix($value) { $this->_prefix=$value; }
function defaultPrefix() { return ""; }

protected $_lifetime=3600;

function getLifetime() { return $this->_lifetime; }
function setLifetime($value) { $this->_lifetime=$value; }
function defaultLifetime() { return 3600; }

protected $_logging="0";

function getLogging() { return $this->_logging; }
function setLogging($value) { $this->_logging=$value; }
function defaultLogging() { return "0"; }

protected $_checkwrite="1";

function getCheckWrite() { return $this->_checkwrite; }
function setCheckWrite($value) { $this->_checkwrite=$value; }
function defaultCheckWrite() { return "1"; }

protected $_serialization="0";

function getSerialization() { return $this->_serialization; }
function setSerialization($value) { $this->_serialization=$value; }
function defaultSerialization() { return "0"; }

protected $_cleaningfactor=10;

function getCleaningFactor() { return $this->_cleaningfactor; }
function setCleaningFactor($value) { $this->_cleaningfactor=$value; }
function defaultCleaningFactor() { return 10; }

protected $_ignoreuserabort="0";

function getIgnoreUserAbort() { return $this->_ignoreuserabort; }
function setIgnoreUserAbort($value) { $this->_ignoreuserabort=$value; }
function defaultIgnoreUserAbort() { return "0"; }

Backendの共通のプロパティを追加する

backendの共通のプロパティも追加します:

protected $_cachedir='/tmp/';

function getCacheDir() { return $this->_cachedir; }
function setCacheDir($value) { $this->_cachedir=$value; }
function defaultCacheDir() { return '/tmp/'; }

protected $_filelocking="1";

function getFileLocking() { return $this->_filelocking; }
function setFileLocking($value) { $this->_filelocking=$value; }
function defaultFileLocking() { return "1"; }

protected $_checkread="1";

function getCheckRead() { return $this->_checkread; }
function setCheckRead($value) { $this->_checkread=$value; }
function defaultCheckRead() { return "1"; }

protected $_readcontroltype=rctCRC32;

function getReadControlType() { return $this->_readcontroltype; }
function setReadControlType($value) { $this->_readcontroltype=$value; }
function defaultReadControlType() { return rctCRC32; }

protected $_hasheddirectorylevel=0;

function getHashedDirectoryLevel() { return $this->_hasheddirectorylevel; }
function setHashedDirectoryLevel($value) { $this->_hasheddirectorylevel=$value; }
function defaultHashedDirectoryLevel() { return 0; }

protected $_hasheddirectoryumask='700';

function getHashedDirectoryUmask() { return $this->_hasheddirectoryumask; }
function setHashedDirectoryUmask($value) { $this->_hasheddirectoryumask=$value; }
function defaultHashedDirectoryUmask() { return '700'; }

protected $_filenameprefix='zend_cache';

function getFileNamePrefix() { return $this->_filenameprefix; }
function setFileNamePrefix($value) { $this->_filenameprefix=$value; }
function defaultFileNamePrefix() { return 'zend_cache'; }

protected $_cachefileumask='700';

function getCacheFileUmask() { return $this->_cachefileumask; }
function setCacheFileUmask($value) { $this->_cachefileumask=$value; }
function defaultCacheFileUmask() { return '700'; }

protected $_metadatasize=100;

function getMetadataSize() { return $this->_metadatasize; }
function setMetadataSize($value) { $this->_metadatasize=$value; }
function defaultMetadataSize() { return 100; }

プロパティ用にデザイン時のインターフェースを追加する

いくつかのプロパティはboolean値を持ち、また、複数の値の中からいずれかの値を持つプロパティもあります。パッケージでそれらに適切なプロパティエディタを登録します:

registerPropertyValues("ZCache", "ReadControlType", array('rctCRC32', 'rctMD5', 'rctADLER32', 'rctSTRLEN'));

registerBooleanProperty("ZCache", "Enabled");
registerBooleanProperty("ZCache", "Logging");
registerBooleanProperty("ZCache", "CheckWrite");
registerBooleanProperty("ZCache", "Serialization");
registerBooleanProperty("ZCache", "IgnoreUserAbort");
registerBooleanProperty("ZCache", "FileLocking");
registerBooleanProperty("ZCache", "CheckRead");

Frontendのそれぞれの設定項目用にグループ化されたプロパティを追加する

frontendの中にはカスタムプロパティを持つものがあり、それらのプロパティを保持するクラスを作成する必要があります。この記事では、FrontendのFunctionプロパティの実装だけを見ていきますが、その他の実装は記事が長くなるので省略しています:

class ZCacheFrontendFunctionOptions extends Persistent
{
protected $_cachebydefault = "1";

function getCacheByDefault() { return $this->_cachebydefault; }
function setCacheByDefault($value) { $this->_cachebydefault = $value; }
function defaultCacheByDefault() { return "1"; }

protected $_cachedfunctions = array();

function getCachedFunctions() { return $this->_cachedfunctions; }
function setCachedFunctions($value) { $this->_cachedfunctions = $value; }
function defaultCachedFunctions() { return array(); }

protected $_noncachedfunctions = array();

function getNonCachedFunctions() { return $this->_noncachedfunctions; }
function setNonCachedFunctions($value) { $this->_noncachedfunctions = $value; }
function defaultNonCachedFunctions() { return array(); }
}

このクラスはPersistentから継承しなければならず、これによりIDEはサブプロパティにしたいものを認識することができます。では、このプロパティをコンポーネントに追加しましょう:

protected $_frontendfunctionoptions = null;

function getFrontendFunctionOptions() { return $this->_frontendfunctionoptions; }
function setFrontendFunctionOptions($value) { $this->_frontendfunctionoptions = $value; }
function defaultFrontendFunctionOptions() { return null; }

そして、それをコンポーネントのコンストラクタ内で初期化します:

class ZCache extends Component
{
function __construct($aowner = null)
{

//Calls inherited constructor
parent::__construct($aowner);

$this->_frontendfunctionoptions= new ZCacheFrontendFunctionOptions();

}
....................

これでZCacheコンポーネントをPageにドロップすると、グループ化されたプロパティが表示されて、その名前の左側にある「+」を使って展開でき、このプロパティのサブプロパティを確認できます。

以上のことを全てのfrontendの設定項目に対して行う必要があります。

サブプロパティ用のプロパティエディタを登録する

これらのサブプロパティを編集するのにどのプロパティエディタを使用するのかIDEに知らせる必要もあります。では、それらを追加しましょう:

registerBooleanProperty("ZCache", "FrontendFunctionOptions.CacheByDefault");
registerPropertyEditor("ZCache","FrontendFunctionOptions.CachedFunctions","TStringListPropertyEditor","native");
registerPropertyEditor("ZCache","FrontendFunctionOptions.NonCachedFunctions","TStringListPropertyEditor","native");

全ての作業が終了すると、オブジェクトインスペクタでは次のような表示になります:

Hide image
Hide image

この後、Backendの設定項目全てを追加し、それらのプロパティを使用してZend_Cacheオブジェクトを生成する記事を掲載しようと思います。

Server Response from: ETNASC01