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
)
{
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"
);
全ての作業が終了すると、オブジェクトインスペクタでは次のような表示になります:


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