我写了一个自定义的服务,为我的模块。 该服务提供了应验证一个给定的令牌公共静态函数。
现在,我要实现它检查如果主义实体的存在与否的另一个公共静态功能。 对于这种情况,我需要的对象的管理器或我的服务的服务定位器。
class ApiService
{
const KEY_LENGTH = 10;
const USE_NUMBERS = true;
const USE_CHARS = true;
public static function isValid($apiKey) {
$isValid = false;
# more code tbd
$isValid = self::exists($apiKey);
return $isValid;
}
public static function exists($apiKey) {
# Insert Object-Manager here
$validator = new \DoctrineModule\Validator\ObjectExists(array(
'object_repository' => $objectManager->getRepository('Application\Entity\User'),
'fields' => array('email')
));
}
}
它是“最佳实践”实现我作为公共静态,并呼吁他们为静态方法?
什么是注入的对象经理到我的最佳实践doesEntityExist()
函数?
最好的办法是在这里彻底去除类的静态方法。 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')
));
},
),
);
}
}
就个人而言,我会做的服务“服务”,并把它放在的ServiceManager。 此外,我会考虑重构代码。 现在你对ObjectExists验证,而这又取决于与实体仓库的依赖,并依赖于实体管理器。 这将是简单得多撰写验证服务外,并从工厂注入它。 这样,如果你需要使用不同的验证,你只要把它不同的一个。
class ApiService
{
protected $validator;
public function isValid($apiKey)
{
// other code
$isValid = $this->exists($apiKey);
}
public function exists($apiKey)
{
return $this->getValidator()->isValid($apiKey);
}
public function setValidator(\Zend\Validator\AbstractValidator $validator)
{
$this->validator = $validator;
return $this;
}
public function getValidator()
{
return $this->validator;
}
}
在Module.php创建服务作为工厂方法,或者更好的是作为一个工厂类,但剩下的作为练习你:)
public function getServiceConfig()
{
return array(
'factories' => array(
'ApiService' => function($sm) {
$em = $sm->get('Doctrine\ORM\EntityManager');
$repo = $em->getRepository('Application\Entity\User');
$validator = new \DoctrineModule\Validator\ObjectExists($repo,
array('fields' => array('email')));
$service = new ApiService();
$service->setValidator($validator);
return $service;
},
),
);
}
现在,如果你需要一个不同的EntityManager,不同的实体库,甚至是完全不同的验证,你只需要改变几行上面,而不是深入到你的服务代码。