How to override the native zf2 view helpers with a

2019-08-02 17:09发布

问题:

I wanted to create a custom basepath helper to replace the original zf2 basepath view helper.

So if i call $this->basepath, it will use my custom basepath instead of the original one. I am not sure if this is can be done. I want my custom basepath extends the original basepath class too.

I have found some answers on how to create custom helpers and how to register them in module.php or module.config.php

But i can't find any similar questions on how to override the original helpers!

回答1:

Factory definition of the basepath view helper is declared as a hardcoded invokable in HelperPluginManager (on line 45) however this definition also overridden in ViewHelperManagerFactory (line 80 to 93) because BasePath view helper requires the Request instance from ServiceLocator:

$plugins->setFactory('basepath', function () use ($serviceLocator) {
    // ...
})

I strongly recommend extending the built-in basepath helper with a different name (MyBasePath for example) instead of trying to override the existing one. Overriding that native helper may produce some unexpected headaches later (think about 3rd party modules which uses that helper to work).

For your question; yes, it is possible.

Create the Application\View\Helper\BasePath.php helper class like below:

namespace Application\View\Helper;

use Zend\View\Helper\BasePath as BaseBasePath; // This is not a typo

/**
 * Custom basepath helper
 */
class BasePath extends BaseBasePath
{
    /**
     * Returns site's base path, or file with base path prepended.
     */
    public function __invoke($file = null)
    {
        var_dump('This is custom helper');
    }
}

And override the factory in the onBootstrap() method of the Module.php file like below:

namespace Application;

use Zend\Mvc\MvcEvent;
use Application\View\Helper\BasePath; // Your basepath helper.
use Zend\View\HelperPluginManager;

class Module
{
    /**
     * On bootstrap for application module.
     *
     * @param  MvcEvent $event
     * @return void
     */
    public function onBootstrap(MvcEvent $event)
    {
        $services = $event->getApplication()->getServiceManager();

        // The magic happens here
        $services->get('ViewHelperManager')->setFactory('basepath', function (HelperPluginManager $manager) {
            $helper = new BasePath();
            // Here you can do whatever you want with the instance before returning
            return $helper;
        });
    }
}

Now you can try in any view like this:

echo $this->basePath('Bar');

This is not a perfect solution but it should work.