将ServiceLocator注入并使用到抽象的Zend \ Form基类中

时间:2013-03-13 00:39:56

标签: zend-form zend-framework2

我创建了一个名为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.phpmodule.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');

所以翻译配置实际上是正确的,但我无法以我的形式检索它。 谁知道我做错了什么?

3 个答案:

答案 0 :(得分:9)

这实际上与您在ZF2 when to use getServiceLocator() and when not to

中看到的问题相同

FormElementManagerAbstractPluginManager,在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 ......

谢谢, 迈克尔