Reputation: 6978
AbstractPluginManager
has an interesting property called $autoAddInvokableClass
which, when enabled, automatically adds any class you attempt to invoke to its list of invokables. Unfortunately, as far as I know, this behaviour is not implemented by ServiceManager itself.
What would be the best way to implement this behaviour in the Application's ServiceManager such that $applicationServiceManager->get(SomeUnregisteredClass::class)
would load SomeUnregisteredClass
even without registering it with $applicationServiceManager
and therefore still run any relevant initializers on the object?
Attempting to do this without registering SomeUnregisteredClass
normally throws an exception similar to the following.
Zend\ServiceManager\Exception\ServiceNotFoundException: Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for SomeUnregisteredClass
Upvotes: 1
Views: 273
Reputation: 13558
First, please realise all the possibilities you create with this feature: do you really need this?
Then, the "root" service manager does not have a autoAddInvokableClass
property. You can, however, create your own service manager and register that as the default one.
Create your custom one:
<?php
namespace MyLib\ServiceManager;
use Zend\ServiceManager as BaseServiceManager;
class ServiceManager extends BaseServiceManager
{
protected $autoAddInvokableClass = true;
public function get($name, $options = array(), $usePeeringServiceManagers = true)
{
// Allow specifying a class name directly; registers as an invokable class
if (!$this->has($name) && $this->autoAddInvokableClass && class_exists($name)) {
$this->setInvokableClass($name, $name);
}
return parent::get($name, $options, $usePeeringServiceManagers);
}
}
Mind that ALL service managers will extend from this one, including the controllers loader. So if you have a route /foo/:controller[/:action]
you can load ANY class this way as you specify a FQCN in the :controller
parameter!
Anyhow, that being said, just enable this SM in your application config:
<?php
return array(
'modules' => array(
'Application',
// Your module here
),
'module_listener_options' => array(
'module_paths' => array(
'./module',
'./vendor',
),
'config_glob_paths' => array(
'config/autoload/{,*.}{global,local}.php',
),
),
// Used to create an own service manager. May contain one or more child arrays.
'service_listener_options' => array(
array(
'service_manager' => 'MyLib\ServiceManager\ServiceManager',
),
),
);
Upvotes: 3