11

How can I use $this->renderView inside a symfony Command (not inside a controller)? I new about the function "renderView" but what do I have to setup to use it wihtin a command?

Thank you in advance an regards

3 Answers 3

31

Your command class must extends the ContainerAwareCommand abstract class and then you can do:

$this->getContainer()->get('templating')->render($view, $parameters);

When it comes to commands that extend ContainerAwareCommand the proper way to obtain the container is by getContainer() unlike in controller shortcut.

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you, this is how it works perfectly. Well, thanks for your reply!!
Just another Question about the Command: How can I access security.content in a Command? $user = $this->get('security.context')->getToken()->getUser(); this won't work so I stuck again :(
Maybe because $this->get('security.context')->getToken() === null
Hm oky, this might be becaus I call it by console. therefor noone must be logged in. Uhhh my fault. sorry and thx for the hint !!
I tried it but I got the error as "You have requested a non-existent service "templeting"."
2

In Symfony 4 I could not get $this->getContainer()->get('templating')->render($view, $parameters); to work.

I set the namespace use for Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand and extended ContainerAwareCommand class EmailCommand extends ContainerAwareCommand

I get an exception thrown

[Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException]
      You have requested a non-existent service "templating".

For Symfony 4, this is the solution I came up with.

First I installed Twig.

composer require twig

Then created my own twig service.

<?php

# src/Service/Twig.php

namespace App\Service;

use Symfony\Component\HttpKernel\KernelInterface;

class Twig extends \Twig_Environment {

    public function __construct(KernelInterface $kernel) {
        $loader = new \Twig_Loader_Filesystem($kernel->getProjectDir());

        parent::__construct($loader);
    }
}

Now my email command looks like this.

<?php

# src/Command/EmailCommand.php

namespace App\Command;

use Symfony\Component\Console\Command\Command,
    Symfony\Component\Console\Input\InputInterface,
    Symfony\Component\Console\Output\OutputInterface,
    App\Service\Twig;

class EmailCommand extends Command {

    protected static $defaultName = 'mybot:email';

    private $mailer,
            $twig;

    public function __construct(\Swift_Mailer $mailer, Twig $twig) {
        $this->mailer = $mailer;
        $this->twig = $twig;

        parent::__construct();
    }

    protected function configure() {
        $this->setDescription('Email bot.');
    }

    protected function execute(InputInterface $input, OutputInterface $output) {

        $template = $this->twig->load('templates/email.html.twig');

        $message = (new \Swift_Message('Hello Email'))
            ->setFrom('[email protected]')
            ->setTo('[email protected]')
            ->setBody(
                $template->render(['name' => 'Fabien']),
                'text/html'
            );

        $this->mailer->send($message);
    }
}

6 Comments

Because services are private by default meaning removed during container compilation process thus not available afterwards. You can verify this by running debug:container templating command. You could inject the EngineInterface instead and you would end up with Twig wired automatically.
@Mike is there a way to make core services, by default not available to console, available? Edit ( just saw you solution )
You mean make private services public? Sure, just declare them public in your services.yml or such.
@Mike thank you for you time. I am having a hard time declaring templating as public. What is the templating name I should declare public in services.yml?
Have you tried with EngineInterface? If not declare it as alias of the templating service and declare public. However command as a service is a better approach. The class is easier to test.
|
2

Yet another one: rely on dependency injection, i.e. inject ContainerInterface

namespace AppBundle\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Psr\Container\ContainerInterface;

class SampleCommand extends Command
{
    public function __construct(ContainerInterface $container)
    {
        $this->templating = $container->get('templating');
        parent::__construct();
    }

    protected function configure()
    {
        $this->setName('app:my-command')
             ->setDescription('Do my command using render');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $data = retrieveSomeData();
        $csv = $this->templating->render('path/to/sample.csv.twig',
                                         array('data' => $data));
        $output->write($csv);
    }

    private $templating;
}

This relies on Symfony to inject the container, which in turn is used to retrieve either templating or twig or whatever you need for your custom command.

1 Comment

Using the templating service is deprecated since Symfony 4.2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.