Building on my previous question: ZF2 Autoloader: Use factory for base class on extended classes as well
I'm trying to get an instance of a subclass of a class I've attached an abstract factory for in my service manager config. I know the factory is being called, because I've got an echo in it that is working. The problem I seem to be running into though is that I don't know how to ask the service manager for my class and get it properly.
When I make this call:
$x = $serviceManager->get('some\class\baseClass');
I get:
Error: Zend\ServiceManager\ServiceManager::get was unable to fetch or create an
instance for some\class\name
And when I output the name that is being passed into the factory, it is missing the slashes like so:
someclassbaseclass
Class File
use Zend\ServiceManager\AbstractFactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class baseClassFactory implements \Zend\ServiceManager\AbstractFactoryInterface
{
public function canCreateServiceWithName (ServiceLocatorInterface $locator, $name, $requestedName = '')
{
return ('baseClass' === $name || is_subclass_of($name, 'baseClass'));
}
public function createServiceWithName (ServiceLocatorInterface $locator, $name, $requestedName = '')
{
$db = $locator->get('db');
$query = new $name($db);
return $query;
}
}
Configuration
$serviceManager => array(
'abstract_factories' => array(
'baseClassFactory',
),
);
EDIT
After testing this code, I've worked out all the bugs. This is the code behind a correct factory accounting for namespaces:
namespace some\class;
use Zend\ServiceManager\AbstractFactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class baseClassFactory implements \Zend\ServiceManager\AbstractFactoryInterface
{
public function canCreateServiceWithName (ServiceLocatorInterface $locator, $name, $requestedName = '')
{
$baseClassName = 'some\class\baseClass';
return ($baseClassName === $requestedName || is_subclass_of($requestedName, $baseClassName));
}
public function createServiceWithName (ServiceLocatorInterface $locator, $name, $requestedName = '')
{
// This class and sub-classes need a database connection
$db = $locator->get('db');
// Use the fully qualified path to the class so it inits correctly
$createName = '\\' . $requestedName;
// Get the system class instance
$class = new $createName($db);
// Pass it back to the user
return $class;
}
}
The registered service name some\\class\\baseClass
is internally formatted by the service manager. The formatting is simply to lowercase and remove any non-alphanumeric characters, which results in someclassbaseclass
.
When you create an abstract factory, you have the choice of both the name you requested in the $serviceManager->get($requestedName)
method call and also the service manager's internal name $name
( someclassbaseclass
).
So the only change would be to replace the uses of $name
with $requestedName
.
use Zend\ServiceManager\AbstractFactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class baseClassFactory implements AbstractFactoryInterface
{
public function canCreateServiceWithName (ServiceLocatorInterface $locator, $name, $requestedName)
{
return ('baseClass' === $requestedName || is_subclass_of($requestedName, 'baseClass'));
}
public function createServiceWithName (ServiceLocatorInterface $locator, $name, $requestedName)
{
$db = $locator->get('db');
return new $requestedName($db);
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.