Zend Framework 2中的服务实体管理器

Rom*_*man 3 doctrine-orm zend-framework2

我为我的模块编写了一个自定义服务.此服务提供公共静态函数,这些函数应验证给定的标记.

现在我想实现另一个公共静态函数,它检查是否存在Doctrine-Entity.对于这种情况,我需要在我的服务中使用对象管理器或服务定位器.

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')
        )); 
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 将我的函数实现为public static并将它们称为静态方法是"最佳实践"吗?

  2. 将对象管理器注入我的doesEntityExist()函数的最佳实践是什么?

Ocr*_*ius 15

最好的方法是在这里完全删除类中的静态方法.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);
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

现在为它定义一个工厂:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后将服务名称映射到工厂(通常在您的模块中):

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',
                ),
            ),
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:您可能只想使用闭包而不是定义单独的工厂类,但是当您不使用该服务时,拥有工厂类可以提高性能.此外,在配置中使用闭包意味着您无法缓存合并配置,因此请考虑使用此处建议的方法.

这是一个没有工厂类的例子(再次考虑使用上面解释的方法):

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);
                },
            ),
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

现在您可以在控制器中使用该服务:

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'));
        }

        // ...
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

您还可以在任何有服务管理器的地方检索它:

$validator = $serviceLocator->get('MyApp\Service\ApiService');
Run Code Online (Sandbox Code Playgroud)

作为补充建议,请考虑简化您的服务.由于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')
                    )); 
                },
            ),
        );
    }
}
Run Code Online (Sandbox Code Playgroud)