/**
* typeに対応するアプリケーションマネージャオブジェクトを返す
+ * 注意: typeは大文字小文字を区別しない
+ * (PHP自体が、クラス名の大文字小文字を区別しないため)
*
* @access public
- * @param string $type ã\82¯ã\83©ã\82¹ã\82ã\83¼
+ * @param string $type ã\82¢ã\83\97ã\83ªã\82±ã\83¼ã\82·ã\83§ã\83³ã\83\9eã\83\8dã\83¼ã\82¸ã\83£ã\83¼å\90\8d
* @param bool $weak オブジェクトが未生成の場合の強制生成フラグ(default: false)
* @return object Ethna_AppManager マネージャオブジェクト
- *
- * TODO: 現状の実装では、typeを名前として扱っているのに、
- * 大文字小文字を区別して違うインスタンスを返しているのを修正する
*/
function &getManager($type, $weak = false)
{
$obj = null;
- // check if object class exists
+ // すでにincludeされていなければ、includeを試みる
+ // ここで返されるクラス名は、AppObjectの命名規約によるもの
+ //
+ // これは、AppObject のファイル中にAppManagerが含まれる場合が
+ // あるため必要なルーチンである
$obj_class_name = $this->controller->getObjectClassName($type);
if (class_exists($obj_class_name) === false) {
- // try include.
$this->_include($obj_class_name);
}
- // check if manager class exists
+ // すでにincludeされていなければ、includeを試みる
+ // ここで返されるクラス名は、AppManagerの命名規約によるもの
$class_name = $this->controller->getManagerClassName($type);
if (class_exists($class_name) === false
&& $this->_include($class_name) === false) {
- return $obj;
+ return $obj; // include 失敗。戻り値はNULL。
}
+ // メソッド情報を集める
if (isset($this->method_list[$class_name]) == false) {
$this->method_list[$class_name] = get_class_methods($class_name);
for ($i = 0; $i < count($this->method_list[$class_name]); $i++) {
}
}
- // see if this should be singlton or not
+ // PHPのクラス名は大文字小文字を区別しないので、
+ // 同じクラス名と見做されるものを指定した場合には
+ // 同じインスタンスが返るようにする
+ $type = strtolower($type);
+
+ // 以下のルールに従って、キャッシュが利用可能かを判定する
+ // 利用可能と判断した場合、キャッシュされていればそれを返す
+ //
+ // 1. メソッドに getInstance があればキャッシュを利用可能と判断する
+ // この場合、シングルトンかどうかは getInstance 次第
+ // 2. weak が true であれば、キャッシュは利用不能と判断してオブジェクトを再生成
+ // 3. weak が false であれば、キャッシュは利用可能と判断する(デフォルト)
if ($this->_isCacheAvailable($class_name, $this->method_list[$class_name], $weak)) {
if (isset($this->manager[$type]) && is_object($this->manager[$type])) {
return $this->manager[$type];
}
}
- // see if we have helper methods
+ // インスタンス化のヘルパ(getInstance)があればそれを使う
if (in_array("getinstance", $this->method_list[$class_name])) {
$obj = call_user_func(array($class_name, 'getInstance'));
} else {
$obj =& new $class_name($backend);
}
+ // 生成したオブジェクトはとりあえずキャッシュする
if (isset($this->manager[$type]) == false || is_object($this->manager[$type]) == false) {
$this->manager[$type] =& $obj;
}
/**
* クラスキーに対応するオブジェクトを返す/クラスキーが未定義の場合はAppObjectを探す
+ * クラスキーとは、[Appid]_Controller#class に定められたもの。
*
* @access public
- * @param string $key クラスキー
- * @param bool $weak オブジェクトが未生成の場合の強制生成フラグ(default: false)
+ * @param string $key [Appid]_Controller#class に定められたクラスキー
+ * このキーは大文字小文字を区別する
+ * (配列のキーとして使われているため)
+ * @param bool $ext オブジェクトが未生成の場合の強制生成フラグ(default: false)
* @return object 生成されたオブジェクト(エラーならnull)
- *
- * TODO: 現状の実装では、typeを名前として扱っているのに、
- * 大文字小文字を区別して違うインスタンスを返しているのを修正する
*/
function &getObject($key, $ext = false)
{
list($weak) = $ext;
}
- // try to include if not defined
+ // すでにincludeされていなければ、includeを試みる
if (class_exists($class_name) == false) {
if ($this->_include($class_name) == false) {
- return $object;
+ return $object; // include 失敗。返り値はnull
}
}
- // handle app object first
+ // AppObject をはじめに扱う
+ // AppObject はキャッシュされないことに注意
if (isset($this->class[$key]) == false) {
$backend =& $this->controller->getBackend();
$object =& new $class_name($backend, $key_type, $key_value, $prop);
return $object;
}
+ // Ethna_Controllerで定義されたクラスキーの場合
+ // はメソッド情報を集める
if (isset($this->method_list[$class_name]) == false) {
$this->method_list[$class_name] = get_class_methods($class_name);
for ($i = 0; $i < count($this->method_list[$class_name]); $i++) {
}
}
- // see if this should be singlton or not
+ // 以下のルールに従って、キャッシュが利用可能かを判定する
+ // 利用可能と判断した場合、キャッシュされていればそれを返す
+ //
+ // 1. メソッドに getInstance があればキャッシュを利用可能と判断する
+ // この場合、シングルトンかどうかは getInstance 次第
+ // 2. weak が true であれば、キャッシュは利用不能と判断してオブジェクトを再生成
+ // 3. weak が false であれば、キャッシュは利用可能と判断する(デフォルト)
if ($this->_isCacheAvailable($class_name, $this->method_list[$class_name], $weak)) {
if (isset($this->object[$key]) && is_object($this->object[$key])) {
return $this->object[$key];
}
}
- // see if we have helper methods
+ // インスタンス化のヘルパがあればそれを使う
$method = sprintf('_getObject_%s', ucfirst($key));
if (method_exists($this, $method)) {
$object =& $this->$method($class_name);
$object =& new $class_name();
}
+ // クラスキーに定められたクラスのインスタンスは
+ // とりあえずキャッシュする
if (isset($this->object[$key]) == false || is_object($this->object[$key]) == false) {
$this->object[$key] =& $object;
}
--- /dev/null
+<?php
+// vim: foldmethod=marker
+/**
+ * Ethna_ClassFactory_Test.php
+ *
+ * @author Yoshinari Takaoka <takaoka@beatcraft.com>
+ * @version $Id$
+ */
+
+require_once ETHNA_BASE . '/test/Ethna_MocktestManager.php';
+
+//{{{ Ethna_ClassFactory_Test
+/**
+ * Test Case For Ethna_ClassFactory_Test
+ *
+ * @access public
+ */
+class Ethna_ClassFactory_Test extends Ethna_UnitTestBase
+{
+ var $cf;
+
+ function setUp()
+ {
+ $ctl =& new Ethna_Controller();
+ $this->cf =& $ctl->getClassFactory();
+ }
+
+ // Ethna_Controller と Ethna_ClassFactory は
+ // 循環参照している。PHP4では、循環参照しているオブジェクト同士を
+ // 比較しようとすると延々再帰的にプロパティと値を比較しようとする
+ // ため Fatal Error を起こす。よって、PHP5以降でのみ以下はテストする
+ // @see http://www.php.net/manual/en/language.oop.object-comparison.php
+ // @see http://www.php.net/manual/en/language.oop5.object-comparison.php
+
+ function test_getManager()
+ {
+ // 大文字小文字を区別されても、
+ // 同じインスタンスを返さなければ
+ // ならない
+ if (version_compare(phpversion(), '5', '>=')) {
+ $manager = $this->cf->getManager('mocktest');
+ $manager_alt = $this->cf->getManager('Mocktest');
+ $this->assertTrue($manager === $manager_alt);
+
+ // weakパラメータが指定された場合は
+ // 強制的に違うオブジェクトを返さなければならない
+ $manager = $this->cf->getManager('mocktest');
+ $manager_alt = $this->cf->getManager('Mocktest', true);
+ $this->assertFalse($manager === $manager_alt);
+ }
+ }
+}
+// }}}
+
+?>