如何从bin / console命令调用特定方法

时间:2019-06-27 05:09:27

标签: php symfony

我需要每2小时运行一次控制器方法。我读到某处您需要创建命令并使用CRON运行该命令。是对的吗?

MY COMMAND:
namespace AppBundle\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Routing\Annotation\Route;

class RunCommand extends Command
{
    // the name of the command (the part after "bin/console")
    protected static $defaultName = 'app:run';

    protected function configure()
    {
        // ...
    }


    protected function execute(InputInterface $input, OutputInterface $output)
    {
        echo 'BEGIN';

        $controller = new \AppBundle\Controller\DefaultController();
        $controller->storeAction();

        echo 'END';
    }
}


MY CONTROLLER:
/**
 * @Route("/to-db", name="to-db")
 */
public function storeAction()
{
    $entityManager = $this->getDoctrine()->getManager();

    $data = new Skuska();
    $data->setName('Keyboard');
    $entityManager->persist($data);
    $entityManager->flush();

    // die();
}

我的错误:在ControllerTrait.php第424行:调用成员函数has()为null

我的代码正确吗?如何使用cron运行方法?

我不想使用其他捆绑软件。我想自己编程

1 个答案:

答案 0 :(得分:3)

如注释中所述,您应将逻辑移出控制器并移入服务,并在命令和控制器中使用该服务。

使用默认的服务自动加载配置,您甚至不必关心服务声明。您的命令将自动成为服务,并且您可以将其他服务注入其中。
https://symfony.com/doc/current/console/commands_as_services.html

对于控制器,您甚至不需要使用特定的构造函数。
https://symfony.com/doc/current/controller.html#fetching-services

<?php
// AppBundle/Service/StoreService.php

use AppBundle\Entity\Skuska;
use Doctrine\ORM\EntityManager;

class StoreService
{
    /** @var EntityManager */
    private $entityManager;

    /**
     * StoreService constructor.
     * @param EntityManager $entityManager
     */
    public function __construct(EntityManager $entityManager)
    {
        $this->entityManager = $entityManager;
    }

    public function store()
    {
        $data = new Skuska();
        $data->setName('Keyboard');
        $this->entityManager->persist($data);
        $this->entityManager->flush();
    }

}
<?php
// AppBundle/Controller/StoreController.php

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

class StoreController extends Controller
{
    /**
     * @Route("/to-db", name="to-db")
     * @param StoreService $storeService
     * @return Response
     */
    // Hinting to you service like this should be enough for autoloading.
    // No need for a specific constructor here.
    public function storeAction(StoreService $storeService)
    {
        $storeService->store();
        return new Response(
        // Return something in you response.
        );
    }
}
<?php
// AppBundle/Command/RunCommand.php

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use AppBundle\Service\StoreService;

class RunCommand extends Command
{
    protected static $defaultName = 'app:run';

    /** @var StoreService */
    protected $storeService;

    /**
     * RunCommand constructor.
     * @param StoreService $storeService
     */
    public function __construct(StoreService $storeService)
    {
        $this->storeService = $storeService;
        parent::__construct();
    }

    protected function configure()
    {
        // ...
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {
        echo 'BEGIN';

        $this->storeService->store();

        echo 'END';
    }
}