最好的方法是從這裏完全刪除你的類的靜態方法。 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