2

我有自定义路由器,我必须访问Zend\Navigation这个自定义路由器内部。我在谷歌上搜索、询问和搜索,但没有结果:/

我只需要在 Alias::match 函数中使用 Zend\Navigation 找到具有“链接”参数的节点。

这是我的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'
                                    ),
                    ),
                ),
            ),
        ),
    ),
[...]

这是我的别名课程:

// 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);        
    }

}

编辑:

现在我知道我应该将服务管理器注入我的自定义路由器。如果你知道怎么做,请告诉我:)

编辑:

好的,它不是自定义路由器,而是路由。我的错。我在谈论#zftalkirc chanell 和AliasSegmentclass should implements ServiceLocatorAwareInterface。好的,我已经尝试过了,但现在还有另一个问题。

setServiceLocator功能上我无法获得service locator。它返回 null 对象,但是$serviceLocator是 class 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 类中可见,但事实并非如此。

match在课堂上的函数中加入了Alias这一行:

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

而且$servicesArray几乎是空的。没有服务,没有工厂。onBootstrap在设置新工厂(如上)之后插入的同一行返回数组navigation和其他服务。

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

我不得不说,我想做的一切在 ZF1 中都是可能的,而且非常简单。

编辑

我找到了解决方案。答案如下

4

2 回答 2

2

那是因为对象本身并没有声明任何属性。但如果你这样做:

echo get_class($sl);

你会看到它确实是一个实例Zend\ServiceManager\ServiceManager

您应该能够通过执行以下操作来获取导航实例:

$nav = $sl->get('Navigation');

编辑:

我只是注意到你在代码的错误位置有一些东西。你正在调用getServiceLocator() which $serviceLocator已经是那个实例。你也在setServiceLocator(). 您应该将其更改为:

// EDIT - file within ModuleName/src/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 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)
    {
        $nav = $this->getServiceLocator()->get('Navigation');
        // ...
        return parent::match($request, $pathOffset);
    }
}
于 2012-11-10T22:15:26.750 回答
1

我找到了解决方案,但我认为这不是优雅的解决方案。然而,一切都完美无缺。如果有人知道此解决方案的缺点,请评论此答案或添加另一个更好的答案。我不得不修改@mmmshuddup 的想法(你可以阅读对话)。

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

在函数Module.php内部onBootstrap

    $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);

首先我们实例Navigation化工厂ServiceManager然后我们的自定义路由。之后,我们可以使用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在静态变量中收集我们的类。这很糟糕,但效果很好。也许有一种方法可以只实例化一次并在路由配置中获取它的实例,但目前这是我问题的最佳答案。足够简单并且可以正常工作。

于 2012-11-11T14:36:26.107 回答