个性化阅读
专注于IT技术分析

如何从控制器执行symfony命令

本文概述

有很多原因导致你应该在控制器中执行控制台命令, 而不是再次重写控制器中的所有逻辑。实际上, 如果需要在两个不同的区域中使用相同的代码, 则可能需要隔离该逻辑并将其公开在服务中。然后, 在控制台中, 就像在控制台命令中一样, 你将能够访问容器, 需要服务并执行它。但是, 如果我们谈论的是第三方捆绑软件的逻辑该怎么办?你不会从捆绑包中复制命令代码, 然后将其粘贴到控制器中, 该死。相反, 建议仅从控制器执行console命令。

在本文中, 你将学习如何直接从控制器中使用控制台命令。

继续之前

在这种情况下, 我们将执行以下命令(php bin /控制台应用程序:print-lines –firstline =” Hello” –secondline =” World”):

<?php
// myapplication/src/AppBundle/Command/TestCommand.php
// Change the namespace according to your bundle
namespace AppBundle\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

// Add the required classes
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;


class TestCommand extends Command
{
    protected function configure()
    {
        $this
            // the name of the command (the part after "bin/console")
            ->setName('app:print-lines')
            // the short description shown while running "php bin/console list"
            ->setHelp("This command allows you to print some text in the console")
            // the full command description shown when running the command with
            ->setDescription('Prints some text into the console with given parameters.')
            // Set options
            ->setDefinition(
                new InputDefinition(array(
                    new InputOption('firstline', 'a', InputOption::VALUE_REQUIRED, "The first line to be printed", "Default First Line Value"), new InputOption('secondline', 'b', InputOption::VALUE_OPTIONAL, "The second line to be printed", "Default First Line Value"), ))
            )
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        // outputs multiple lines to the console (adding "\n" at the end of each line)
        $output->writeln([
            'My Third Symfony command', // A line
            '============', // Another line
            '', // Empty line
        ]);
        
        $firstLine = $input->getOption('firstline');
        $secondline = $input->getOption('secondline');
        
        $output->writeln("First line value : ".$firstLine);
        
        if($secondline){
            $output->writeln("Second line value : ".$secondline);
        }
        
        // Instead of retrieve line per line every option, you can get an array of all the providen options :
        //$output->writeln(json_encode($input->getOptions()));
    }
}

如果要学习如何为Symfony创建自定义控制台命令, 请阅读本文。否则, 如果你已经拥有一个, 则继续执行。

实现

你可以从控制器执行任何控制台命令, 只要它不是动态的(需要在其中进行交互的命令)或与项目中的文件混淆的命令(例如clear cache命令)即可。从命令的执行中, 你可以决定是否检索输入:

带输出

要在控制器内执行命令, 请使用以下代码:

<?php

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;

// Import the required classed
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\BufferedOutput;


class DefaultController extends Controller
{
    /**
     * @Route("/", name="homepage")
     */
    public function indexAction()
    {
        $kernel = $this->get('kernel');
        $application = new Application($kernel);
        $application->setAutoExit(false);

        $input = new ArrayInput(array(
            'command' => 'app:print-lines', '--firstline' => "Hello", '--secondline' => "World"
        ));

        $output = new BufferedOutput();

        $application->run($input, $output);

        // return the output
        $content = $output->fetch();

        // Send the output of the console command as response
        return new Response($content);
    }
}

先前的控制器将在浏览器中作为响应返回”我的第三Symfony命令=============第一行值:Hello第二行值:World”。

无输出

如果你不关心命令生成的输出, 因为它不重要或生成了自定义日志, 则可以忽略BufferedOutput。在这种情况下, 由于无法知道命令是否已成功执行, 因此将使用以下自定义命令(它将在项目的/ web文件夹中创建一个文本文件, 以确保该命令已通过控制台执行可以使用php bin /控制台应用程序执行:create-file-web –filename =” test” –extension =” txt”):

<?php
// myapplication/src/AppBundle/Command/TestCommand.php
// Change the namespace according to your bundle
namespace AppBundle\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

// Add the required classes
use Symfony\Component\Console\Input\InputDefinition;
use Symfony\Component\Console\Input\InputOption;

// Add the Container
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;

class TestCommand extends ContainerAwareCommand
{
    protected function configure()
    {
        $this
            // the name of the command (the part after "bin/console")
            ->setName('app:create-file-web')
            // the short description shown while running "php bin/console list"
            ->setHelp("This command creates a file")
            // the full command description shown when running the command with
            ->setDescription('Creates a file with a custom filename')
            // Set options
            ->setDefinition(
                new InputDefinition(array(
                    new InputOption('filename', 'a', InputOption::VALUE_REQUIRED, "The filename", "mytextfile"), new InputOption('extension', 'b', InputOption::VALUE_OPTIONAL, "The extension of the file", "txt"), ))
            )
        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $filename = $input->getOption('filename');
        $extension = $input->getOption('extension');
        $webFolder = $this->getContainer()->get('kernel')->getRootDir() . '/../web/';

        // Create the file with custom name and extension in the /web path
        $myfile = fopen($webFolder. "$filename.$extension", "w");
        $txt = "Command succesfully executed";
        fwrite($myfile, $txt);
        fclose($myfile);
    }
}

可以使用以下代码从控制器执行此操作(无需检索输出):

注意

完全不使用BufferedOutput, 需要将其替换为NullOutput

<?php

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Response;

// Import the required classed
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;


class DefaultController extends Controller
{
    /**
     * @Route("/", name="homepage")
     */
    public function indexAction()
    {
        $kernel = $this->get('kernel');
        $application = new Application($kernel);
        $application->setAutoExit(false);

        $input = new ArrayInput(array(
            'command' => 'app:create-file-web', '--filename' => "test", '--extension' => "txt"
        ));
        
        // Use the NullOutput class instead of BufferedOutput.
        $output = new NullOutput();

        $application->run($input, $output);

        return new Response("Command succesfully executed from the controller");
    }
}

控制器应返回响应”从控制器成功执行命令”, 即使未正确执行也是如此。要检查它是否真正执行, 请验证文件是否在项目的/ web路径中创建。如果你需要有关控制台组件的更多信息, 请在此处阅读文档。

编码愉快!

赞(0)
未经允许不得转载:srcmini » 如何从控制器执行symfony命令

评论 抢沙发

评论前必须登录!