最好的方法是从这里完全删除你的类的静态方法。 ZF2使得通过名字获取服务变得非常简单,所以你不应该为这种用例真正需要静态方法。
首先,清理您的服务:
namespace MyApp\Service;
use Doctrine\Common\Persistence\ObjectRepository;
use DoctrineModule\Validator\ObjectExists;
class ApiService
{
// ...
protected $validator;
public function __construct(ObjectRepository $objectRepository)
{
$this->validator = new \DoctrineModule\Validator\ObjectExists(array(
'object_repository' => $objectRepository,
'fields' => array('email')
));
}
public function exists($apiKey)
{
return $this->validator->isValid($apiKey);
}
// ...
}
现在定义一个工厂它:
namespace MyApp\ServiceFactory;
use MyApp\Service\ApiService;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class ApiServiceFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
$entityManager = $serviceLocator->get('Doctrine\ORM\EntityManager');
$repository = $entityManager->getRepository('Application\Entity\User');
return new ApiService($repository);
}
}
服务名称,然后映射到工厂(通常在你的模块) :
namespace MyApp;
use Zend\ModuleManager\Feature\ConfigProviderInterface;
class Module implements ConfigProviderInterface
{
public function getConfig()
{
return array(
'service_manager' => array(
'factories' => array(
'MyApp\Service\ApiService'
=> 'MyApp\ServiceFactory\ApiServiceFactory',
),
),
);
}
}
注意:您可能只想简单地使用闭包而不是定义单独的工厂类,但在不使用服务时使工厂类可以提高性能。此外,在配置中使用闭包意味着您无法缓存合并的配置,因此请考虑使用此处提供的方法。
这里没有工厂类的实例(再次,可以考虑使用这种方法如上所述):
namespace MyApp;
use Zend\ModuleManager\Feature\ServiceProviderInterface;
class Module implements ServiceProviderInterface
{
public function getServiceConfig()
{
return array(
'factories' => array(
'MyApp\Service\ApiService' => function ($sl) {
$entityManager = $serviceLocator->get('Doctrine\ORM\EntityManager');
$repository = $entityManager->getRepository('Application\Entity\User');
return new MyApp\Service\ApiService($repository);
},
),
);
}
}
现在你可以在你的控制器使用服务:
class MyController extends AbstractActionController
{
// ...
public function apiAction()
{
$apiService = $this->getServiceLocator()->get('MyApp\Service\ApiService');
if (! $apiService->isValid($this->params('api-key')) {
throw new InvalidApiKeyException($this->params('api-key'));
}
// ...
}
// ...
}
您也可以检索它在任何你有服务经理的地方:
$validator = $serviceLocator->get('MyApp\Service\ApiService');
作为额外的建议请考虑简化您的服务。由于isValid
已经是你的验证的方法,你可以简单地返回验证本身(在此使用简单的方法关闭):
namespace MyApp;
use Zend\ModuleManager\Feature\ServiceProviderInterface;
use DoctrineModule\Validator\ObjectExists;
class Module implements ServiceProviderInterface
{
public function getServiceConfig()
{
return array(
'factories' => array(
'MyApp\Validator\ApiKeyValidator' => function ($sl) {
$entityManager = $serviceLocator->get('Doctrine\ORM\EntityManager');
$repository = $entityManager->getRepository('Application\Entity\User');
new ObjectExists(array(
'object_repository' => $objectRepository,
'fields' => array('email')
));
},
),
);
}
}
嗨@Ocramius,谢谢你的帮助。 – Roman 2013-03-07 10:41:57
@Ocramius,我喜欢ServiceFactory实现。但是,我们怎样才能以这种方式将$ entityManager用于其他事情呢?我想使用Hydrator,但我无法确定在哪里/如何。我不认为它的好做法是让控制器再次获得$ entitymanager。 – SimonV 2013-03-10 16:27:16
@SimonV,正如我在http://marco-pivetta.com/doctrine-orm-zf2-tutorial/#/38/11中解释的那样,在控制器中使用持久层可能不是一个好主意。考虑将水合物本身定义为服务,然后将水合物传递给你自己的服务(例如)'MyFooService :: save(Foo $ foo)' – Ocramius 2013-03-10 16:37:45