$serviceManager->get('\Foo\Bar');
// Exception
// Invalid instantiator of type "\\Foo\\Bar" for "NULL".
検索されるクラス名に\が付いていると、RuntimeDefinitionでReflectionにより処理されたクラス名と不一致が起きるため。
/** @var $rClass \Zend\Code\Reflection\ClassReflection */
$rClass = new Reflection\ClassReflection($class);
$className = $rClass->getName();
$matches = null; // used for regex below
// setup the key in classes
$this->classes[$className] = array(
'supertypes' => array(),
'instantiator' => null,
'methods' => array(),
'parameters' => array()
);
同じ例外を起こす別のパターンとしては、
- Diを使っている時に、必須パラメーターが不足しているとき
- AbstractPluginManagerなどでDiAbstractFactoryの使用時、DIを優先するためにUSE_SL_AFTER_DIを指定できるが、一部のパラメーターでSL上のサービスをインジェクションしたい場合、DI上に定義が存在しないとき。
など、その他、Definition上の不一致で生じることがある。
なお、依存性の解決優先順位はコメントを抜き出すと、
// PRIORITY 1 - consult user provided parameters
// PRIORITY 2 - specific instance configuration (thisAlias) - this alias
// PRIORITY 3 - THEN specific instance configuration (thisClass) - this class
// PRIORITY 4 - THEN specific instance configuration (requestedAlias) - requested alias
// PRIORITY 5 - THEN specific instance configuration (requestedClass) - requested class
// PRIORITY 6 - globally preferred implementations
// next consult class level preferred instances
となっている。
InvalidInstantiatorが設定ミスのために発生するのでこれを完全に抑止することは好ましくないが、たとえば、Loggerのようにグローバルに使いまわす可能性が高いものや、ServiceLocatorのように暗黙にアプリケーションスコープのサービスロケーターを期待する場合などは、typePreferenceを追加して自動的に解決させるという選択肢がある。
上記のようにPriority6 と6+でTypePreferencesは解決されるので、別のオブジェクトを抽入したい場合には適切に設定を行う必要がある。特定のinterfaceに対してグローバルなオブジェクトを割り当てておき、スコープ内でのオブジェクトを使うときだけ明示的に指定するといった場合にTypePreferencesは便利な選択となる。