How get basepath from model or helper en Zend Framework 3

喜欢而已 提交于 2019-12-08 11:17:28

问题


I recently decided to use Zend Framework 3 after 3 years of using Zend Framework 1. This decision has given me headaches, Zend 3 instead of making things easier made things more difficult.

In Zend 1, I customize the url for the selected template in the database as follows:

public function getUrl(string $file = '')
{
    if($this->_helperBaseUrl === null) {
        $this->_helperBaseUrl = new Zend_View_Helper_BaseUrl();
    }
    return $this->_helperBaseUrl->baseUrl($file);
}

public function getSkinUrl(string $file = '')
{
    $themePath = 'themes/my-theme/'; //get from database
    return $this->getUrl($themePath . ltrim($file, '/\\'));
}

Then in any part of the application (models, helpers, plugins and views) I can access this function like this:

//view/scripts/index/index.phtml
$url_logo = My::app()->getSkinUrl('logo.jpg');
//this return http://example.com/themes/my-theme/logo.jpg

In Zend 3 it has been very difficult for me. Does anyone know of any way to do it in Zend 3? Or How to get the baseUrl from a model in Zend 3?


回答1:


In Zend Framework 2/3 you can inject almost any class into another. For example if you need basePath plugin (which is available in view context) you can inject this plugin into your model/service or controller class. This is the recommended way:

This is class where you need this plugin or any other service

use Zend\View\Helper\BasePath;

class MyService
{
    /**
     * @var BasePath
     */
    protected $plugin;

    /**
     * MyService constructor.
     *
     * @param BasePath $basePath
     */
    public function __construct(BasePath $basePath)
    {
        $this->plugin = $basePath;
    }

    /**
     * @return BasePath
     */
    public function getPlugin()
    {
        return $this->plugin;
    }

    /**
     * @param BasePath $plugin
     */
    public function setPlugin($plugin)
    {
        $this->plugin = $plugin;
    }
}

Now, you need to factory to inject one dependency into another

use Interop\Container\ContainerInterface;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use MyNamespace\Service\MyService;

class MyServiceFactory implements FactoryInterface
{
    /**
     *
     * @param ContainerInterface $container
     * @param string $requestedName
     * @param null|array $options
     * @return MyService
     */
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $class = $requestedName ? $requestedName : MyService::class;
        $plugin = $container->get('ViewHelperManager')->get('BasePath'); // inject this class
        $myService = new $class($plugin); // into this class

        return $myService;

    }
    /**
     * Provided for backwards compatibility; proxies to __invoke().
     *
     * @param ContainerInterface|ServiceLocatorInterface $container
     * @return MyService
     */
    public function createService(ServiceLocatorInterface $container)
    {
        return $this($container, MyService::class);
    }
}

Ok, now MyService has basePath plugin, but to use it in controller you have to inject your service into controller. So...

IndexController

use MyNamespace\Service\MyService;
use Zend\Mvc\Controller\AbstractActionController;

class IndexController extends AbstractActionController
{
    /**
     * @var MyService
     */
    protected $service;

    /**
     * IndexController constructor.
     * 
     * @param MyService $service
     */
    public function __construct(MyService $service)
    {
        $this->service = $service;
    }

    public function indexAction()
    {
        $plugin = $this->service->getPlugin(); // Zend\View\Helper\BasePath object
        //...
    }
}

... and factory for our controller...

use Interop\Container\ContainerInterface;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use MyNamespace\Controller\IndexController;

class IndexControllerFactory implements FactoryInterface
{
    /**
     *
     * @param ContainerInterface $container
     * @param string $requestedName
     * @param null|array $options
     * @return IndexController
     */
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $class = $requestedName ? $requestedName : IndexController::class;
        $myService = $container->getServiceLocator()->get('MyNamespace\Service\MyService');
        $controller = new $class($myService);

        return $controller;

    }
    /**
     * Provided for backwards compatibility; proxies to __invoke().
     *
     * @param ContainerInterface|ServiceLocatorInterface $container
     * @return IndexController
     */
    public function createService(ServiceLocatorInterface $container)
    {
        return $this($container, IndexController::class);
    }
}

It's almost done. Last step is to set configuration in module.config.php file

use MyNamespace\Controller;
use MyNamespace\Factory;

return [
    //...
    'service_manager' => [
        'factories' => [
            Service\MyService::class => Factory\Service\MyServiceFactory::class
        ]
    ],
    'controllers' => [
        'factories' => [
            Controller\IndexController::class => Factory\Controller\IndexControllerFactory::class
        ],
    ],
]

Easy, isn't it?
If you need plugin in controller, but not in your model/service class, you can skip MyService part of this "tutorial" and inject plugin directly into controller class



来源:https://stackoverflow.com/questions/42548822/how-get-basepath-from-model-or-helper-en-zend-framework-3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!