A.Seddighi
A.Seddighi

Reputation: 1765

Call a Command from a Controller not work

i have this code to run schema update command from controller i got help from symfony document i have this code:

namespace AdminBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\KernelInterface;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

class DefaultController extends Controller
{
    /**
     * @Route("/admin")
     */
    public function indexAction(KernelInterface $kernel)
    {
        $application = new Application($kernal);

        $input = new ArrayInput(array(
            'command' => 'doctrine:schema:update'
        ));

        $output = new NullOutput();
        $application->run($input, $output);

        return new Response("");
    }
}

it's not work for me i get this error after open this url (http://127.0.0.1:8000/admin):

Controller "AdminBundle\Controller\DefaultController::indexAction()" requires that you provide a value for the "$kernel" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one.

how can i do?

Upvotes: 1

Views: 1353

Answers (2)

Jason Roman
Jason Roman

Reputation: 8276

While Michael's answer works, it is not the preferred method in Symfony 3.3, which had several changes to dependency injection. Your code will actually work just fine with some changes to your services configuration.

As the documentation states, the Dependency Injection Container changed in Symfony 3.3, and by default your controllers are registered as services:

# app/config/services.yml
services:
    # ...

    # controllers are imported separately to make sure they're public
    # and have a tag that allows actions to type-hint services
    AppBundle\Controller\:
        resource: '../../src/AppBundle/Controller'
        public: true
        tags: ['controller.service_arguments']

This allows you to autowire the kernel through arguments in your controller action method, like you tried. The reason yours isn't working is because your AdminBundle is likely not set up the way your AppBundle is by default in app/config/services.yml. To truly solve the issue in the way that Symfony 3.3 wants, you should add AdminBundle to your services configuration like so:

# app/config/services.yml
services:
    # add this below your AppBundle\Controller definition
    AdminBundle\Controller\:
        resource: '../../src/AdminBundle/Controller'
        public: true
        tags: ['controller.service_arguments']

With that, you no longer have to call $this->get('kernel');, and your original code will work as you have it, with KernelInterface as a parameter to your action method.

Furthermore, you can extend the new AbstractController instead of the regular Controller, and then calls to $this->get() will not work anymore, which is the way Symfony is going.

So again while Michael's answer will work just fine, I would advise you to implement the answer I've given simply because Symfony 3.3 prefers that method going forward.

Upvotes: 2

Michael Hirschler
Michael Hirschler

Reputation: 2518

Instead of injecting the KernelInterface $kernel directly into your action (I guess, you're not using it as a declared service), call your container directly for asking the kernel:

public function indexAction()
{
    $kernel = $this->get('kernel');
    $application = new Application($kernel); // btw: you have an typo in here ($kernal vs $kernel)

    $input = new ArrayInput(array(
        'command' => 'doctrine:schema:update'
    ));

    $output = new NullOutput();
    $application->run($input, $output);

    // tip: use "204 No Content" to indicate "It's successful, and empty"
    return new Response("", 204);
}

Upvotes: 4

Related Questions