最善の方法は、ここでクラスから静的メソッドを完全に削除することです。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')
));
},
),
);
}
}