Zend framework 2 : Service locator in view helper
Asked Answered
E

1

6

I'm trying to access the service locator in a view helper so i can access to my config. I'm using this view helper for a recursive function so i don't know where to declare the service locator.

namespace Application\View\Helper;

use Zend\View\Helper\AbstractHelper;
use CatMgt\Model\CategoryTable as RecursiveTable;

class CategoryRecursiveViewHelper extends AbstractHelper
{
    protected $table;

    public function __construct(RecursiveTable $rec)
    {
        $this->table = $rec; 
    }

    public function __invoke($project_id, $id, $user_themes_forbidden, $level, $d, $role_level)
    {

       $config = $serviceLocator->getServiceLocator()->get('config');

       //So i can access $config['templates']

       $this->__invoke($val->project_id, $id, $user_themes_forbidden, $level, $d, $role_level);

    }

}

I tried the solution give here link

But it didn't helped, is it all right to do it that way?

namespace Application\View\Helper;

use Zend\View\Helper\AbstractHelper;
use CatMgt\Model\CategoryTable as RecursiveTable;
use Zend\View\HelperPluginManager as ServiceManager;

class CategoryRecursiveViewHelper extends AbstractHelper
{
    protected $table;
    protected $serviceManager;

    public function __construct(RecursiveTable $rec, ServiceManager $serviceManager)
    {
        $this->table = $rec; 
        $this->serviceManager = $serviceManager;
    }

    public function __invoke($project_id, $id, $user_themes_forbidden, $level, $d, $role_level)
    {

       $config = $this->serviceManager->getServiceLocator()->get('config');

       //So i can access $config['templates']

       $this->__invoke($val->project_id, $id, $user_themes_forbidden, $level, $d, $role_level);

    }

}
Ellison answered 8/5, 2014 at 1:58 Comment(0)
M
16

First of all, your ViewHelper is an infinite loop and your app will crash like that. You call the __invoke within the __invoke - this just can't work.

Registering a ViewHelper with dependencies

First off, you'd write your ViewHelper like:

class FooBarHelper extends AbstractHelper
{
    protected $foo;
    protected $bar;

    public function __construct(Foo $foo, Bar $bar)
    {
        $this->foo = $foo;
        $this->bar = $bar;
    }

    public function __invoke($args)
    {
        return $this->foo(
            $this->bar($args['something'])
        );
    }
}

Next comes registering the ViewHelper. As it requires a dependency you're required to use a factory as target.

// module.config.php
'view_helpers' => [
    'factories' => [
        'foobar' => 'My\Something\FooBarHelperFactory'
    ]
]

The target is now a factory-class, that we have yet to write. So onwards to it:

class FooBarHelperFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $sl)
    {
        // $sl is instanceof ViewHelperManager, we need the real SL though
        $rsl = $sl->getServiceLocator();
        $foo = $rsl->get('foo');
        $bar = $rsl->get('bar');

        return new FooBarHelper($foo, $bar);
    }
}

Now you're able to use your ViewHelper via $this->foobar($args) in any of your view-files.

Don't ever use the ServiceLocator AS a dependency

Whenever you rely on the ServiceManager as a dependency you're falling down into bad design. Your classes will have dependencies of unknown type and they are hidden. Whenever your class needs some outside data, make it available through the __construct() directly and don't hide the dependencies by injecting the ServiceManager.

Macadamia answered 8/5, 2014 at 5:11 Comment(4)
Okay thank you, this is more clear to me, i was always confuse how to use serviceLocator.Ellison
// $sl is instanceof ViewHelperManager, we need the real SL though you just saved me hours of research, thank you!!. And also I now have less faith in ZF design team. This should probably be posted to /r/lol_phpEmpathize
@ChristopherFrancisco The Design decision had it's valid point but it was too complicated for most people to easily grasp. Luckily we got the PSR Container stuff going on right now ;)Macadamia
Awesome! Follow the steps and it works! Really nice post!Asset

© 2022 - 2024 — McMap. All rights reserved.