Zend Framework 2将变量传递给模型 [英] Zend Framework 2 passing variable to models

查看:67
本文介绍了Zend Framework 2将变量传递给模型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在开发一个多语言网站.对于多语言部分,我使用翻译器/poedit.我将所选的语言存储在会话中.效果很好.

I'm currently developing a multilangual website. For the multilangual part i use translator / poedit. I store the selected language in session. It works fine.

Module.php:

Module.php:

public function onBootstrap(MvcEvent $e)
{
    // ...

    $session = new Container('base');

    if ($session->language !== NULL) {
        $e->getApplication()->getServiceManager()->get('translator')->setLocale($session->language);
    }
}

在控制器中设置语言的操作:

Action for setting language in a controller:

public function setLanguageAction()
{
    $language = $this->params()->fromRoute('language');

    if (isset($this->languages[$language])) {

        $session = new Container('base');

        if ($language == 'en') {
            $session->language = NULL;
        } else {
            $session->language = $language;
        }
    }

    return $this->redirect()->toRoute('home');
}

在module.config.php中,默认语言环境设置为en.

In module.config.php the default locale is set to en.

我说过,除了一件事,一切都很好.

As i said everything works fine, except for one thing.

我也将一些语言相关的数据存储在DB中,因此在我的模型中,我需要知道当前的语言是什么.模型中的其他目的也需要当前语言.

I store some language dependent data in DB too, so in my models i need to know what the current language is. The current language is needed for other purposes in the models too.

因此,我在每个模型的构造函数中包含以下代码:

So i include the following code in every model's construct function:

$session = new Container('base');

if ($session->language !== NULL) {
    $this->language = $session->language;
} else {
    $this->language = 'default';
}

我认为这不是最佳解决方案.我的模型太多,无法始终包含此代码.

I think it's not the best solution. I have too much models to always include this code.

我想知道是否存在一种解决方案,例如可以通过Module.php/getServiceConfig函数将$ language变量自动传递给我的所有模型:

I would like to know if there is a solution to pass a $language variable automatically to all of my models for example from Module.php / getServiceConfig function:

public function getServiceConfig()
{        
    $session = new Container('base');

    return array(
        'factories' => array(
            'Application\Model\SomeThing' => function($sm) {
                $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                $c = new SomeThing($dbAdapter);
                $c->language = $session->language;
                return $c;
            }
        )
    );
}

当然这是行不通的,但是能够执行类似的操作或更通用的解决方案(这是非常必要的),因为不必将当前语言的值分配给每个模型的language变量.工厂数组(例如,用于模型的通用引导程序,可以在同一位置为所有模型完成此分配).

Of course this is not working, but it would be great to be able to do something similar like this, or a more general solution, where it is not necessary to assign the value of the current language to every model's language variable in the factory array (for example a common bootstrap for models, where this assignment can be done for all models in one place).

我的问题有解决方案吗?

Is there a solution for my problem?

谢谢您的帮助!

M

推荐答案

如果您不想将语言注入到所有模型中,那么我至少可以想到另外一种方法.

If you don't want to inject the language into all of your models, then I can think of at least one other way off the top of my head.

您可以使用初始化程序.初始化程序基本上允许您对通过服务管理器获取的服务执行初始化任务.因此,要使用这种方法,必须通过服务管理器获取模型(至少是需要语言的模型).这与添加可调用项或工厂(如果需要注入任何依赖项)一样容易.有关初始化程序的更多信息,请阅读我写的文章关于服务管理器(向下滚动到有关初始化程序的部分).

You could make use of an initializer. An initializer basically allows you to perform initialization tasks on services fetched through the service manager. Thus, to use this approach, you must fetch your models (at least the ones that need the language) through the service manager. This is as easy as adding them as invokables or perhaps factories if you need to inject any dependencies. For more information about initializers, you can read the article I wrote about the service manager (scroll down to the section about initializers).

因此,您可以做的是让模型实现一个接口,例如LanguageAwareInterface.

So, what you can do is to have your models implement an interface, e.g. LanguageAwareInterface.

namespace User\Model;

interface LanguageAwareInterface {
    /**
    * Gets the language
    *
    * @return string
    */
    public function getLanguage();

    /**
    * Sets the language
    *
    * @param string $language
    */
    public function setLanguage($language);
}

然后,您可以在模型中执行以下操作.

Then you can do like the following in your model.

namespace User\Model;

class MyModel implements \User\Model\LanguageAwareInterface {
    /**
    * @var string $language The current language
    */
    protected $language;

    /**
    * Gets the language
    *
    * @return string
    */
    public function getLanguage() {
        return $this->language;
    }

    /**
    * Sets the language
    *
    * @param string $language
    */
    public function setLanguage($language) {
        $this->language = $language;
    }
}

如果您愿意,甚至可以制作一个具有上述代码的抽象基模型类,或者,如果您想避免扩展一个类,则可以编写一个简单的特征.然后,每个模型都可以扩展此基类,但这取决于实际需要多少模型才能使用当前语言.

If you wish, you could even make an abstract base model class that has the above code, or perhaps write a simple trait if you want to avoid extending a class. Then your models could each extend this base class, but that depends how many of your models actually need to work with the current language.

现在是初始化程序.在我的文章中,我有一个有关如何通过方法调用添加它的示例,但是您很可能希望在配置文件中进行添加(如果使用Zend Skeleton Application,则可能是在Application模块中).您可以在getServiceConfig()方法中从模块的Module类返回数组(或指向配置文件),也可以将其添加到service_manager键下的YourModule/config/module.config.php文件中.官方文件没有给出任何例子.实际上,初始化器是唯一缺少的东西.但是,它应该可以工作.

Now for the initializer. In my article I have an example of how to add it with method calls, but chances are that you will want to do it in your configuration file (perhaps in the Application module if you are using the Zend Skeleton Application). You can either return an array (or point to a config file) from the module's Module class in the getServiceConfig() method, or you can just add it to the YourModule/config/module.config.php file under the service_manager key. The official documentation does not give any example of this; in fact, initializers are the only thing missing. It should, however, work.

return array(
    /* Other configuration here */

    'service_manager' => array(
        'initializers' => array(
            'language' => function($service, $sm) {
                // $service is the service that is being fetched from the service manager
                // $sm is the service manager instance
                if ($service instanceof \User\Model\LanguageAwareInterface) {
                    $session = new \Zend\Session\Container('base');

                    if ($session->language === null) {
                        // Fetch default language from configuration
                        $config = $sm->get('Config');

                        $session->language = $config['translator']['locale'];
                    }

                    $service->setLanguage($session->language);
                }
            },
        ),
    ),
);

上面的初始化程序检查从服务管理器获取的每个对象,以查看它是否实现了我们上面创建的接口.如果是这样,则可以注入该语言.在我的示例中,我检查是否在会话中设置了它,如果没有,请从配置中获取它.您可能需要根据实际需要调整逻辑.请注意,每次您从服务管理器中获取对象时,初始化器将在每次中运行,因此确实会增加一点点开销.但是,这并不重要,因为我们仅在服务未实现接口时才进行简单的类型检查.同样,服务默认情况下是共享的,这意味着服务将仅实例化一次.随后对同一服务的请求将重用先前实例化的服务.这有助于进一步限制开销.

The above initializer checks every object that is fetched from the service manager to see if it implements the interface we created above. If it does, the language can be injected. In my example, I check to see if it is set in the session and if not, fetch it from the configuration. You may have to tweak the logic depending on your exact needs. Note that the initializer will be run every time you fetch an object from the service manager, and thus it does add a little bit of overhead. This is, however, not significant because we are only doing a simple type check when the service does not implement the interface. Also, services are shared by default, which means that a service will only be instantiated once; subsequent requests for the same service will then reuse the previously instantiated one. This helps to limit the overhead even further.

这篇关于Zend Framework 2将变量传递给模型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆