ECWorks Blog

ECWorks Blog

CakePHPを中心としたサイト開発情報をメインに公開。新しもの好きなので時々製品レポートなんかも。

【CakePHP】Shellを拡張してTaskで親シェルのメソッドが使える「ShellEx」クラス

CakePHPを利用するにあたり、基本的にはWeb上で動作するアプリケーションを作成すると思いますが、バックエンド等でCakeの機能を用いながら処理を実行したい場合も当然出てきます。そんなときは「シェル」が活躍します。みなさんシェルは活用されていますか?

CakePHP1.2/1.3では、シェルの中で「タスク」という小機能を呼び出す仕組みがあります。Shellの中に膨大な機能を全部押し込まなくても済むようになるためコードの可読性が上がり、大変に便利な機能です。膨大な機能を提供しているCake機能の一つ「Bake」も、コアコードを覗けば多数のタスクで構成されています。
使い方も簡単です。「app/vendors/shells/」内に、例えば「hoge_shell.php」を作成します。中身はShellクラスを継承した「HogeShell」クラスを作成します。そしてその中には「main()」メソッドを用意すれば動作します。詳しくは こちら をご覧いただくか「Pocket詳解 CakePHP辞典」をご覧ください(出来れば買って!(笑))。

さてここからなのですが、Taskを使う場合、ShellからTaskが呼ばれるのですが、Shell内は素通りしてしまうため例えばタイトルなどをShell内で制作しても表示されません。また、タイトルを表示するためのメソッドを作って共通化をはかろうとしても、タスクからは呼び出し元のシェルはアクセスが出来ないため、利用することが出来ません。タイトルに限らず、シェル内で利用したいプロパティ・メソッドがあってもアクセスが不可能のため利用不可能です。

そこで、タスク内から親シェルのオブジェクトを参照することが可能な機能を付加する「ShellExクラス」を作成してみました。やっていることは非常に簡単で、タスクの初期化時に親クラスのオブジェクト参照を付加するのみです。しかしタスクの初期化・スタートアップ・実行が全てシェルのinitialize()とstartup()の間に挟まれていますので付加するタイミングがありません。このため、ShellExクラスのinitialize()内でタスクの初期化を先行して行っています。タスク初期化は「Shell::loadTasks()」が行っていますが、結果として二度実行されます。
Shell::loadTasks()が二度実行されることで若干問題点があります。それは親シェル内にロードされる各タスクオブジェクトが1回上書きされることです。幸いだったのが、このとき上書きされるのはClassRegistry::getObject()で入手できる参照オブジェクトでした。実体ではないため、結果として同じオブジェクトになります。単純に無駄な処理が走るだけです。多少気持ち悪さは残りますが、とりあえず要求していた機能は実現できます。

ソースコードはgistに上げました。このファイルを「app/vendors/shells」等にアップロードし、シェル内であらかじめApp::import()でこれを読み込み、extendsを「ShellEx」にすれば動作します。ファイル名は「shell_ex.php」とします。

利用例


App::import('Shell', 'ShellEx');
class MyShell extends ShellEx {
	var $tasks = array('Mytask');

	function commonFunc(){
		//共通処理
		$this->out('MyShell::commonFunc()');
	}

	function main(){
		//メインで共通処理を呼び出します
		$this->commonFunc();
	}
}


App::import('Shell', 'ShellEx');
class MytaskTask extends ShellEx {
	function excute(){
		//共通処理を実行
		$this->parentShell->commonFunc();
	}
}

タイトル云々の話は、Ktai Library1.0のシェル関連機能を実装している最中に必要になりました。やっぱりオリジナルのタイトルは作りたいので(笑)。まあこのほかいくつか共通機能を実装したかったので、それだけのためって事はないですが…
また @hiromi2424 さんによりますと、CakePHP2.0ではShell機能は改良されているそうです。まあ今回の記事は思いっきりバッドノウハウですね(^^;。


Tagged as: , , ,

Comments are closed.