Как получить базовый путь из модели или помощника в Zend Framework 3

Недавно я решил использовать Zend Framework 3 после 3 лет использования Zend Framework 1. Это решение доставило мне головную боль, Zend 3 вместо того, чтобы упростить задачу, усложнил задачу.

В Zend 1 я настраиваю URL-адрес для выбранного шаблона в базе данных следующим образом:

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

Затем в любой части приложения (модели, помощники, плагины и представления) я могу получить доступ к этой функции следующим образом:

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

В Zend 3 мне было очень сложно. Кто-нибудь знает, как это сделать в Zend 3? Или как получить baseUrl из модели в Zend 3?


person Andres Rojas Orozco    schedule 02.03.2017    source источник
comment
Ты просто опоздал на вечеринку 5 лет :)   -  person tasmaniski    schedule 02.03.2017
comment
@tasmaniski 3 года назад я использовал ZF2, но он был медленнее, чем ZF1. По этой причине я продолжил использовать ZF1 :)   -  person Andres Rojas Orozco    schedule 02.03.2017


Ответы (1)


В Zend Framework 2/3 вы можете внедрить почти любой класс в другой. Например, если вам нужен плагин basePath (который доступен в контексте представления), вы можете вставить этот плагин в свою модель / службу или класс контроллера. Это рекомендуемый способ:

Это класс, где вам нужен этот плагин или любая другая услуга

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

Теперь вам нужно на фабрике внедрить одну зависимость в другую.

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

Хорошо, теперь у MyService есть плагин basePath, но чтобы использовать его в контроллере, вы должны внедрить свою службу в контроллер. Так...

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
        //...
    }
}

... и фабрика для нашего контроллера ...

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

Почти готово. Последний шаг - установить конфигурацию в module.config.php файле.

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
        ],
    ],
]

Легко, не правда ли?
Если вам нужен плагин в контроллере, но не в вашей модели / классе обслуживания, вы можете пропустить MyService часть этого «руководства» и вставить плагин непосредственно в класс контроллера.

person SzymonM    schedule 02.03.2017