Use Plates PHP with dependency injection

1.1k Views Asked by At

I want to use dependency injection to pass an instance of Plates to my controllers with PHP-DI that is integrated with my routing system Simple Router. I've tried to inject an instance of Plates, but I get this error:

<?php

namespace Controllers;

use \League\Plates\Engine;
use \League\Plates\Template\Template;
use \League\Plates\Extension\Asset;

class Controller {

  public function __construct(\League\Plates\Engine $templates)
  {
    $this->templates = $templates;
  }

?>

Uncaught LogicException: The template name "home" is not valid. The default directory has not been defined

How I can solve this issue? I need also to pass the assets path with the asset() method. Any help will be appreciated.

UPDATE

Thanks to the help of jcHache I've managed the injection of a Plates instance inside my base controller with this DI code:

<?php 

// config.php
return [
  League\Plates\Engine::class => DI\create()
    ->constructor(TEMPLATE_ROOT)
    ->method('loadExtension', DI\get('League\Plates\Extension\Asset')),
  League\Plates\Extension\Asset::class => DI\create()
    ->constructor(APP_ROOT),
];

index.php file

<?php 

use Pecee\SimpleRouter\SimpleRouter;
use DI\ContainerBuilder;

$container = (new \DI\ContainerBuilder())
  ->useAutowiring(true)
  ->addDefinitions('config.php')
  ->build();

SimpleRouter::enableDependencyInjection($container);

This is great but I'm facing a problem and I can't find a fix for it. I get this error that is relative to the assets loader of plates, it seems that it's instantiated more than once. I've extended my controllers with my base controller where the asset loader is instantiated, but I don't think is this the problem? Is there a fix?

Uncaught Pecee\SimpleRouter\Exceptions\NotFoundHttpException: The template function name "asset" is already registered

1

There are 1 best solutions below

9
jcheron On BEST ANSWER

Plates engine factory require a view folder parameter (see Plates doc):

so you have to add this creation in your PHP-DI configuration file:

For Plates V4:

// config.php
return [
    // ...
    \League\Plates\Engine::class => function(){
        return League\Plates\Engine::create('/path/to/templates', 'phtml');
    },
];

For Plates V3, I'll try:

// config.php
return [
    // ...
    \League\Plates\Engine::class => function(){
        return new League\Plates\Engine('/path/to/templates');
    },
];

or

// config.php
return [
    // ...
    \League\Plates\Engine::class =>  DI\create()
       ->constructor('/path/to/templates')
    ,
];

Design Note:

Personally, I won't use dependency injection for a template engine, I think it would be better to instantiate Plates engine in a base controller class.

namespace controllers;

use League\Plates\Engine;

abstract class BaseController 
{
    /**
     * @var \League\Plates\Engine
     */
    protected $templates;

    public function __construct()
    {
        $this->templates=new Engine(\TEMPLATE_ROOT);
        $this->templates->loadExtension(new \League\Plates\Extension\Asset(\APP_ROOT));
    }

    protected function renderView(string $viewname, array $variables=[])
    {
        return $this->templates->render($viewname,$variables);
    }
}

For a child controller using Plates:

namespace controllers;

class MyController extends BaseController
{
    public function index()
    {
        return $this->renderView('home');
    }
}