ZF2:如何在自定义路线中获取Zend \ Navigation? [英] ZF2: How to get Zend\Navigation inside custom route?

查看:89
本文介绍了ZF2:如何在自定义路线中获取Zend \ Navigation?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有自定义路由器,并且必须访问此自定义路由器内的Zend\Navigation.我正在谷歌搜索,询问和搜索,但没有结果:/

我需要做的就是在Alias :: match函数中使用Zend \ Navigation查找具有"link"参数的节点.

这是我的module.config.php:

'navigation' => array(
        'default' => array(
            'account' => array(
                'label' => 'Account',
                'route' => 'node',
                'pages' => array(
                    'home' => array(
                        'label' => 'Dashboard',
                        'route' => 'node',
                        'params' => array(
                                    'id' => '1',
                                    'link' => '/about/gallery'
                                    ),
                    ),
                ),
            ),
        ),
    ),
[...]

这是我的Alias课:

// file within ModuleName/src/ModuleName/Router/Alias.php
namespace Application\Router;

use Traversable;
use Zend\Mvc\Router\Exception;
use Zend\Stdlib\ArrayUtils;
use Zend\Stdlib\RequestInterface as Request;
use Zend\Mvc\Router\Http;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class Alias extends Http\Segment implements ServiceLocatorAwareInterface
{

    public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
    {
        $this->serviceLocator = $serviceLocator;
        return $this;
    }

    public function getServiceLocator()
    {
        return $this->serviceLocator;
    }

    public function match(Request $request, $pathOffset = null)
    {
        [...]

        return parent::match($request, $pathOffset);        
    }

}

已编辑

:

现在我知道我应该将服务管理器注入到我的自定义路由器中.让我知道您是否知道该怎么做:)

已编辑

:

好,它不是自定义路由器,而是路由.我的错.我在说#zftalk irc chanell,而AliasSegment类应该实现ServiceLocatorAwareInterface.好的,我已经尝试过了,但是现在还有另一个问题.

setServiceLocator函数中,我无法获得service locator.它返回空对象,但是$serviceLocator是类Zend\Mvc\Router\RoutePluginManager.

public function setServiceLocator(ServiceLocatorInterface $serviceLocator){
    $sl = $serviceLocator->getServiceLocator();
    var_dump($sl); // NULL
}

有什么想法如何从中获得Zend导航吗?

已编辑

与@mmmshuddup所说的相对应,我已经更改了自定义路由器类. (上面是新版本).同样在我的Module.php中,在onBootstrap函数中,我添加了以下行:

$sm->setFactory('Navigation', 'Zend\Navigation\Service\DefaultNavigationFactory', true);

导航有效并且在route之前实例化,因此它应该在我的Alias类中可见,但是不可见.

我在Alias类的match函数中加入了这一行:

$servicesArray = $this->getServiceLocator()->getRegisteredServices();

$servicesArray几乎为空.没有服务,没有工厂.设置新工厂(如上)后,插入到onBootstrap的同一行将返回包含navigation和其他服务的数组.

问题是:如何与我的自定义路由器Alias共享此阵列(或ServiceManager)?

我不得不说我想做的一切都可以在ZF1中完成,而且非常简单.

编辑

我找到了解决方案.答案在下面

解决方案

我找到了解决方案,但是我认为这不是不优雅的解决方案.但是,一切正常.如果有人知道此解决方案的缺点,请评论此答案或添加另一个更好的答案.我不得不修改@mmmshuddup的想法(您可以阅读对话)./p>

首先,不再需要在自定义路由类中实现ServiceLocatorAwareInterface.

onBootstrap函数内的Module.php中:

    $app = $e->getApplication();
    $sm  = $app->getServiceManager();
    $sm->get('translator');
    $eventManager        = $e->getApplication()->getEventManager();
    $moduleRouteListener = new ModuleRouteListener();
    $moduleRouteListener->attach($eventManager);

    $sm->setFactory('Navigation', 
                    'Zend\Navigation\Service\DefaultNavigationFactory', true);

    $nav = $sm->get('Navigation');
    $alias = $sm->get('Application\Router\Alias');
    $alias->setNavigation($nav);

首先,我们在ServiceManager中实例化Navigation工厂,然后实例化我们的自定义路线.之后,我们可以使用setNavigation函数将Navigation类传递到自定义路线. 要完成我们的自定义路线的实例化,我们需要在同一文件的getServiceConfig中:

    return array(
        'factories' => array(
            'Application\Router\Alias' => function($sm) {
                $alias = new \Application\Router\Alias('/node[/:id]');
                return $alias;
            },
            'db_adapter' =>  function($sm) {
                $config = $sm->get('Configuration');
                $dbAdapter = new \Zend\Db\Adapter\Adapter($config['db']);
                return $dbAdapter;
            },
        )
    );

这是一个棘手的部分.该实例是临时的.在路由时,该类将被再一次实例化,这就是为什么我认为它不是很优雅.我们必须将参数插入构造函数中,但是此时此参数的值并不重要.

自定义路线类别:

// file within ModuleName/src/ModuleName/Router/Alias.php
namespace Application\Router;

use Traversable;
use Zend\Mvc\Router\Exception;
use Zend\Stdlib\ArrayUtils;
use Zend\Stdlib\RequestInterface as Request;
use Zend\Mvc\Router\Http;

class Alias extends Http\Segment
{

    private static $_navigation = null;

    public function match(Request $request, $pathOffset = null)
    {
        //some logic here

        //get Navigation
        $nav = self::$_navigation;

        return parent::match($request, $pathOffset);
    }

    public function setNavigation($navigation){
        self::$_navigation = $navigation;
    }

}

因为第一个实例是临时的,所以我们必须在静态变量中收集我们的Navigation类.糟透了,但是效果很好.也许有一种方法只能实例化一次,并在路由配置中获取它的实例,但是目前,这是我的问题的最佳答案.足够简单并且可以正常工作.

I have custom router and I have to get access to Zend\Navigation inside this custom router. I was googling, asking and searching and no results :/

All I need is to find nodes with 'link' param using Zend\Navigation in my Alias::match function.

Here is my module.config.php:

'navigation' => array(
        'default' => array(
            'account' => array(
                'label' => 'Account',
                'route' => 'node',
                'pages' => array(
                    'home' => array(
                        'label' => 'Dashboard',
                        'route' => 'node',
                        'params' => array(
                                    'id' => '1',
                                    'link' => '/about/gallery'
                                    ),
                    ),
                ),
            ),
        ),
    ),
[...]

And here is my Alias class:

// file within ModuleName/src/ModuleName/Router/Alias.php
namespace Application\Router;

use Traversable;
use Zend\Mvc\Router\Exception;
use Zend\Stdlib\ArrayUtils;
use Zend\Stdlib\RequestInterface as Request;
use Zend\Mvc\Router\Http;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class Alias extends Http\Segment implements ServiceLocatorAwareInterface
{

    public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
    {
        $this->serviceLocator = $serviceLocator;
        return $this;
    }

    public function getServiceLocator()
    {
        return $this->serviceLocator;
    }

    public function match(Request $request, $pathOffset = null)
    {
        [...]

        return parent::match($request, $pathOffset);        
    }

}

EDITED:

Now i know that I should inject service manager into my custom router. Let me know if You know how to do this :)

EDITED:

Ok, its not custom router but route. My bad. I was talking on #zftalk irc chanell and AliasSegment class should implements ServiceLocatorAwareInterface. Ok I've tried it but now there is another problem.

In setServiceLocator function i can't get service locator. It returns null object, however $serviceLocator is class Zend\Mvc\Router\RoutePluginManager.

public function setServiceLocator(ServiceLocatorInterface $serviceLocator){
    $sl = $serviceLocator->getServiceLocator();
    var_dump($sl); // NULL
}

Any ideas how to get Zend navigation from it ?

EDITED

Corresponding to what @mmmshuddup said, I've changed my custom router class. (New version is above). Also in my Module.php, within onBootstrap function, I added this line:

$sm->setFactory('Navigation', 'Zend\Navigation\Service\DefaultNavigationFactory', true);

Navigation works and its instantiated before route so it should be visible within my Alias class but it's not.

I've put into my match function in Alias class this line:

$servicesArray = $this->getServiceLocator()->getRegisteredServices();

and $servicesArray is almost empty. There is no service, no factories. The same line inserted into onBootstrap, just after setting new factory (as above) returns array with navigation and other services.

The question is: how can i share this array (or ServiceManager) with my custom router: Alias ?

I have to say that all I want to do was possible in ZF1 and it was quite easy.

EDIT

I found a solution. The answer is below

解决方案

I found the solution but this is NOT elegant solution i think. However everything works perfectly. If somebody knows disadvantages of this solution, please comment this answer or add another, better. I had to modify @mmmshuddup's idea (you can read the conversation).

First of all, the implementation of ServiceLocatorAwareInterface in custom route class is no more necessary.

In Module.php within onBootstrap function:

    $app = $e->getApplication();
    $sm  = $app->getServiceManager();
    $sm->get('translator');
    $eventManager        = $e->getApplication()->getEventManager();
    $moduleRouteListener = new ModuleRouteListener();
    $moduleRouteListener->attach($eventManager);

    $sm->setFactory('Navigation', 
                    'Zend\Navigation\Service\DefaultNavigationFactory', true);

    $nav = $sm->get('Navigation');
    $alias = $sm->get('Application\Router\Alias');
    $alias->setNavigation($nav);

First we instantiate Navigation factory in ServiceManager and then our custom route. After that we can pass Navigation class into custom route using setNavigation function. To complete instantiate of our custom route we need in getServiceConfig in the same file:

    return array(
        'factories' => array(
            'Application\Router\Alias' => function($sm) {
                $alias = new \Application\Router\Alias('/node[/:id]');
                return $alias;
            },
            'db_adapter' =>  function($sm) {
                $config = $sm->get('Configuration');
                $dbAdapter = new \Zend\Db\Adapter\Adapter($config['db']);
                return $dbAdapter;
            },
        )
    );

And here is a tricky part. This instance is temporary. While routing, this class will be instantiated one more time and this is why, I think, it's not very elegant. We have to insert parameter into constructor however at this moment value of this parameter is not important.

The custom route class:

// file within ModuleName/src/ModuleName/Router/Alias.php
namespace Application\Router;

use Traversable;
use Zend\Mvc\Router\Exception;
use Zend\Stdlib\ArrayUtils;
use Zend\Stdlib\RequestInterface as Request;
use Zend\Mvc\Router\Http;

class Alias extends Http\Segment
{

    private static $_navigation = null;

    public function match(Request $request, $pathOffset = null)
    {
        //some logic here

        //get Navigation
        $nav = self::$_navigation;

        return parent::match($request, $pathOffset);
    }

    public function setNavigation($navigation){
        self::$_navigation = $navigation;
    }

}

Because first instance is temporary, we have to collect our Navigation class in static variable. It's awful but works nice. Maybe there is a way to instantiate it only once and in route configuration get instance of it, but at this moment this is best answer for my question. Simply enough and working correctly.

这篇关于ZF2:如何在自定义路线中获取Zend \ Navigation?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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