我创建了一个名为AbstractApplicationForm
的抽象表单类。我希望通过Zend\ServiceManager\ServiceLocatorAwareInterface
将服务定位器注入其中以访问翻译器:
namespace Application\Form;
use Zend\Form\Form;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
abstract class AbstractApplicationForm
extends Form
implements ServiceLocatorAwareInterface
{
protected $serviceLocator;
protected $translator;
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
}
public function getServiceLocator()
{
return $this->serviceLocator;
}
public function getTranslator()
{
if (!$this->translator) {
$this->translator = $this->getServiceLocator()->get('translator');
}
return $this->translator;
}
}
我的申请表扩展了这个类,如下所示:
namespace Trade\Form;
use Zend\Captcha;
use Zend\Captcha\Image;
use Zend\Form\Element;
use Application\Form\AbstractApplicationForm;
class MemberForm extends AbstractApplicationForm
{
public function init()
{
$this->setAttribute('method', 'post');
// Add the elements to the form
$id = new Element\Hidden('id');
$first_name = new Element\Text('first_name');
$first_name->setLabel($this->getTranslator('First Name'))
通过这种方式,我可以使用getTranslator来翻译标签。
到目前为止一切顺利。在我的控制器操作中,我创建了这样的表单:
public function joinAction()
{
// Create and initialize the member form for join
$formManager = $this->serviceLocator->get('FormElementManager');
$form = $formManager->get('Trade\Form\MemberForm');
结果是ServiceManager异常:
Zend \ ServiceManager \ ServiceManager :: get无法获取或创建翻译实例
我在Module.php
或module.config.php
中没有定义任何其他内容,我认为我不需要。我在module.config.php
中定义了这样的翻译器:
'translator' => array(
'locale' => 'en_US',
'translation_patterns' => array(
array(
'type' => 'gettext',
'base_dir' => __DIR__ . '/../language',
'pattern' => '%s.mo',
),
),
当我在控制器中获取它时,哪个工作正常:
$sm = $this->getServiceLocator();
$this->translator = $sm->get('translator');
所以翻译配置实际上是正确的,但我无法以我的形式检索它。 谁知道我做错了什么?
答案 0 :(得分:9)
这实际上与您在ZF2 when to use getServiceLocator() and when not to
中看到的问题相同 FormElementManager
是AbstractPluginManager
,在AbstractPluginManager
的构造函数中,添加了以下service initializer:
$this->addInitializer(function ($instance) use ($self) {
if ($instance instanceof ServiceLocatorAwareInterface) {
$instance->setServiceLocator($self);
}
});
事实是,在这种情况下,$self
指的是插件管理器本身。这意味着任何实现Zend\ServiceManager\ServiceLocatorAwareInterface
且由插件管理器生成的服务(在本例中为FormElementManager
)都会自动注入插件管理器。
插件管理器不是主要服务定位器(再次参见ZF2 when to use getServiceLocator() and when not to)。
Zend\Form\FormElementManager
实例是由主服务管理器在您调用时生成的:
$formElementManager = $this->serviceLocator->get('FormElementManager');
由于Zend\Form\FormElementManager
实现了Zend\ServiceManager\ServiceLocatorAwareInterface
,因此它引用了实际的“主要”服务管理器。
因此,以您的形式:
$formElementManager = $this->getServiceLocator();
$mainServiceManager = $formElementManager->getServiceLocator();
$translator = $mainServiceManager->get('translator');
答案 1 :(得分:1)
您可能必须getServiceLocator()->getServiceLocator()->get('translator')
我不明白为什么你有时必须这样做,但它确实有效。
答案 2 :(得分:1)
我有一个抽象的fieldset类和一个具体的fieldset类。翻译器以完全相同的方式注入,但是当我在字段集中尝试“$ this-> getTranslator()”时,抛出以下异常:
Zend \ ServiceManager \ ServiceManager :: get无法获取或创建翻译实例
因此SM无法找到翻译服务。 我按以下方式添加(配置)了翻译器:
'service_manager' => array(
'factories' => array(
'translator' => 'Zend\I18n\Translator\TranslatorServiceFactory',
'Navigation' => 'Zend\Navigation\Service\DefaultNavigationFactory',
'logger' => function ($sm) {
$logger = new \Zend\Log\Logger();
$config = $sm->get('Config');
if ($config['logger']['writer'] == 'ChromePhp'):
$logger->addWriter(new \Application\Log\Writer\ChromePhp()); else:
$logger->addWriter('FirePhp');
endif;
return $logger;
}
),
),
'translator' => array(
'locale' => 'de_DE',
'translation_file_patterns' => array(
array(
'type' => 'gettext',
'base_dir' => __DIR__ . '/../language',
'pattern' => '%s.mo',
),
),
),
在我看来,翻译工作得很完美。 所以在momemnt我不知道,接下来要尝试什么。您能告诉我您如何将翻译服务添加到您的应用程序中吗?
编辑------------------------- 附加信息: 在字段集类
中$this->getServiceLocator();
给我一个“Zend \ Form \ FormElementManager”类型的对象。这对于表单元素是正确的。
$this->getServiceLocator()->getServiceLocator();
但是这给了我NULL而不是ServiceLocator-Object ......
谢谢, 迈克尔