简体   繁体   中英

Zend Expressive, get service from Php Plates template

I use Zend Expressive framework via default ZE skeleton app with Zend ServiceManager as DIC and Plates as template engine.

Let's say I've got index.phtml template. I want to get some service, which dumps me assets, smth like:

<?= $this->getContainer()->get('my service class')->dumpAssets() ?>

Service is registered via factory and accesible in the app:

<? $container->get('my service class') ?>

How to pass external service instance or its result into template?

It's pretty much bad practice to inject the entire service container into a template (or any other class except a factory). A better approach would be to write an extension to dump the assets.

Extension class:

<?php

namespace App\Container;

use League\Plates\Engine;
use League\Plates\Extension\ExtensionInterface;
use App\Service\AssetsService;

class DumpAssetsExtension implements ExtensionInterface
{
    public $assetsService;

    /**
     * AssetsExtension constructor.
     * @param $container
     */
    public function __construct(AssetsService $assetsService)
    {
        $this->assetsService = $assetsService;
    }

    public function register(Engine $engine)
    {
        $engine->registerFunction('dumpAssets', [$this, 'dumpAssets']);
    }

    public function dumpAssets()
    {
        return $this->assetsService->dumpAssets();
    }
}

Factory:

<?php

namespace App\Container;

use Interop\Container\ContainerInterface;

class DumpAssetsFactory
{
    public function __invoke(ContainerInterface $container)
    {
        $assetsService = $container->get(App\Service\AssetsService::class);

        return new PlatesExtension($assetsService);
    }
}

Configuration:

<?php

return [
    // ...
   'factories' => [
       App\Container\DumpAssetsExtension::class => App\Container\DumpAssetsFactory::class,
   ]
];

In your template:

<?php
    $service = $this->dumpAssets();
?>

I figured out how to access container from template engine via extensions . It's not clear MVC-ly, but...

At first, add plates config into config/autoload/templates.global :

return [
    // some othe settings    
    'plates' => [
        'extensions' => [
            App\Container\PlatesExtension::class,
        ],
    ],
],

At second, create App\\Container\\PlatesExtension.php with code:

<?php

namespace App\Container;

use League\Plates\Engine;
use League\Plates\Extension\ExtensionInterface;

class PlatesExtension implements ExtensionInterface
{
    public $container;

    /**
     * AssetsExtension constructor.
     * @param $container
     */
    public function __construct($container)
    {
        $this->container = $container;
    }

    public function register(Engine $engine)
    {
        $engine->registerFunction('container', [$this, 'getContainer']);
    }

    public function getContainer()
    {
        return $this->container;
    }
}

At third, create factory App\\Container\\PlatesExtensionFactory.php to inject container into plates extension:

<?php

namespace App\Container;

use Interop\Container\ContainerInterface;

class PlatesExtensionFactory
{
    public function __invoke(ContainerInterface $container)
    {
        return new PlatesExtension($container);
    }
}

Next, register plates extension in ServiceManager ( config/dependencies.global.php ):

return [
    // some other settings
   'factories' => [
       App\Container\PlatesExtension::class => App\Container\PlatesExtensionFactory::class,
   ]
];

At last, get container and needed service from Plates template:

<?
    $service = $this->container()->get('my service class');
?>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM