1

我创建了一个名为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.phpor中定义任何其他内容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');

所以翻译器配置实际上是正确的,但我无法在我的表单中检索它。有人知道我在做什么错吗?

4

3 回答 3

9

这实际上是您在ZF2 看到的相同问题,何时使用 getServiceLocator() 何时不使用

FormElementManager是一个,并且在的AbstractPluginManager构造函数中AbstractPluginManager,添加了以下服务初始化程序:

$this->addInitializer(function ($instance) use ($self) {
     if ($instance instanceof ServiceLocatorAwareInterface) {
        $instance->setServiceLocator($self);
    }
});

事实是$self,在这种情况下,指的是插件管理器本身。这意味着任何实现Zend\ServiceManager\ServiceLocatorAwareInterface并由插件管理器(在本例中为FormElementManager)生成的服务都会注入插件管理器本身。

插件管理器不是主要的服务定位器(再次,请参阅ZF2 何时使用 getServiceLocator() 以及何时不使用)。

当您调用时,该Zend\Form\FormElementManager实例由主服务管理器生成:

$formElementManager = $this->serviceLocator->get('FormElementManager');

由于Zend\Form\FormElementManagerimplements Zend\ServiceManager\ServiceLocatorAwareInterface,它引用了实际的“主要”服务管理器。

因此,以您的形式:

$formElementManager = $this->getServiceLocator();

$mainServiceManager = $formElementManager->getServiceLocator();

$translator = $mainServiceManager->get('translator');
于 2013-03-13T02:02:03.157 回答
1

你可能不得不做getServiceLocator()->getServiceLocator()->get('translator')

我不明白为什么有时你必须这样做,但它确实有效。

于 2013-03-13T01:24:48.807 回答
1

我有一个抽象字段集类和一个具体字段集类的相同构造。翻译器以完全相同的方式注入,但是当我尝试在字段集中“$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',
        ),
    ),
),

在我看来,翻译工作完美。所以目前我不知道下一步该尝试什么。您能告诉我您是如何将翻译服务添加到您的应用程序中的吗?

编辑 ------------- 附加信息:在字段集类中

$this->getServiceLocator();

给我一个“Zend\Form\FormElementManager”类型的对象。这对于表单元素是正确的。

$this->getServiceLocator()->getServiceLocator();

但这给了我 NULL 而不是 ServiceLocator-Object ...

谢谢,迈克尔

于 2013-04-06T09:17:46.217 回答