【问题标题】:How to execute Zend Framework 3 action with zf-console?如何使用 zf-console 执行 Zend Framework 3 操作?
【发布时间】:2018-10-06 23:50:05
【问题描述】:

我想用 zf-console 执行 ZF3 动作。
我可以使用 zend-mvc-console 模块来做到这一点,它工作正常。
例如。
应用程序/config/module.config.php:

'console' => [
    'router' => [
        'routes' => [
            'cronroute' => [
                'options' => [
                    'route'    => 'sync',
                    'defaults' => [
                        'controller' => Controller\ConsoleController::class,
                        'action' => 'syncEvents'
                    ]
                ]
            ]
        ]
    ]
],

Application/src/Controller/ConsoleController.php

class ConsoleController extends AbstractActionController 
{
    /**
     * Entity manager.
     * @var Doctrine\ORM\EntityManager
     */
    private $entityManager;

    /**
     * User Manager
     * @var Application\Service\UserManager 
     */
    private $userManager;

    /**
     * Constructor. 
     */
    public function __construct($entityManager, $userManager)
    {
        $this->entityManager = $entityManager;
        $this->userManager = $userManager;
    }

    public function syncAction() 
    {
        $response = $this->userManager->syncUserInfo();

        return $response ? 'Sync Success' : 'Failed to sync';
    }
}

但它说它将被弃用:
https://zendframework.github.io/zend-mvc-console/intro/#deprecated

建议使用 zfcampus 的 zf-console:
https://github.com/zfcampus/zf-console

但我找不到执行控制器操作或使用我的构建服务(如 UserManager)的方法。

有构建 Zend 应用程序和检索服务管理器的示例:

use Zend\Console\Console;
use Zend\Console\ColorInterface as Color;
use ZF\Console\Application;
use ZF\Console\Dispatcher;

chdir(dirname(__DIR__));

require __DIR__  . '/../vendor/autoload.php'; // Composer autoloader 

$application = Zend\Mvc\Application::init(require 'config/application.config.php');
$services    = $application->getServiceManager();

$buildModel = $services->get('My\BuildModel');

有没有办法用它执行控制器操作?或者我可以加载我的 UserManager 服务吗?
我试图获取 My UserManager:

$buildModel = $services->get('Application\Service\UserManager');

但是接收错误:

PHP Fatal error:  Uncaught exception 'Zend\ServiceManager\Exception\ServiceNotFoundException' with message 'Unable to resolve service "Application\Service\UserManager" to a factory; are you certain you provided it during configuration?' in /var/www/html/vendor/zendframework/zend-servicemanager/src/ServiceManager.php:687

【问题讨论】:

    标签: php zend-framework3


    【解决方案1】:

    zend-mvc-console 模块似乎确实处于弃用的边缘。就像你一样,我试图实现 zfcampus/zf-console。由于 mvc-console 模块似乎(几乎)已被弃用,我建议您在控制台工作中使用与(mvc)控制器不同的东西。我使用了一个可以处理调用的类(以 zf-console 期望的方式)。

    这是我正在为我的项目工作的一个虚拟示例;

    这是在命令行上调用的脚本:

    use Zend\Console\Console;
    use Zend\ServiceManager\ServiceManager;
    use Zend\Stdlib\ArrayUtils;
    use Zend\Stdlib\Glob;
    use ZF\Console\Application;
    use ZF\Console\Dispatcher;
    
    require_once __DIR__ . '/vendor/autoload.php'; // Composer autoloader
    
    $configuration = [];
    foreach (Glob::glob('config/{{*}}{{,*.local}}.php', Glob::GLOB_BRACE) as $file) {
        $configuration = ArrayUtils::merge($configuration, include $file);
    }
    
    // Prepare the service manager
    $smConfig = isset($config['service_manager']) ? $configuration['service_manager'] : [];
    $smConfig = new \Zend\Mvc\Service\ServiceManagerConfig($smConfig);
    
    $serviceManager = new ServiceManager();
    $smConfig->configureServiceManager($serviceManager);
    $serviceManager->setService('ApplicationConfig', $configuration);
    
    // Load modules
    $serviceManager->get('ModuleManager')->loadModules();
    
    $routes = [
        [
            'name' => 'dumb',
            'route' => '[--foo=]',
            'description' => 'Some really cool feature',
            'short_description' => 'Cool feature',
            'options_descriptions' => [
                'foo'   => 'Lorem Ipsum',
            ],
            'defaults' => [
                'foo'   => 'bar',
            ],
            'handler' => function($route, $console) use ($serviceManager) {
                $handler = new \Application\Command\DumbCommand();
                return $handler($route, $console);
            }
        ],
    ];
    
    $config = $serviceManager->get('config');
    $application = new Application(
        $config['app'],
        $config['version'],
        $routes,
        Console::getInstance(),
        new Dispatcher()
    );
    
    $exit = $application->run();
    exit($exit);
    

    处理函数可以使用服务管理器将任何依赖注入到命令处理程序中:

    'handler' => function($route, $console) use ($serviceManager) {
        /** @var \Doctrine\ORM\EntityManager $entityManager */
        $entityManager = $serviceManager->get(\Doctrine\ORM\EntityManager::class);
        /** @var mixed $repository */
        $contactRepository = $entityManager->getRepository(\Application\Entity\Contact::class);
        $handler = new \Application\Command\DumbCommand($contactRepository);
        return $handler($route, $console);
    }
    

    命令类放在一个Command文件夹中,它看起来像:

    <?php
    
    namespace Application\Command;
    
    use Application\Entity\Contact;
    use Application\Repository\ContactRepository;
    use Zend\Console\Adapter\AdapterInterface;
    use ZF\Console\Route;
    
    class DumbCommand
    {
        /** @var ContactRepository */
        private $contactRepository;
    
        public function __construct($contactRepository)
        {
            $this->contactRepository = $contactRepository;
        }
    
        /**
         * @param Route $route
         * @param AdapterInterface $console
         * @throws \Doctrine\ORM\ORMException
         */
        public function __invoke(Route $route, AdapterInterface $console)
        {
            $console->writeLine('Bob was here');
            foreach ($this->contactRepository->findAll() as $item) {
                /** @var Contact $item */
                $console->writeLine($item->getFirstName() . ' was here');
            }
        }
    }
    

    (

    【讨论】:

    • 谢谢,它对我有用并且能够使用我的服务和 entityManager。
    • 它询问“您是否为 \Doctrine\ORM\EntityManager 提供工厂”?
    【解决方案2】:

    这是我的解决方案:

    1. 我将控制台命令路由添加到我的 module.config.php 文件中
    'console' => array(
        'commands' => array(
            array(
                'name' => 'sendemail',
                'handler' => PostCommand::class,
            ),
            array(
                'name' => 'sendsms',
                'handler' => SmsTransferCommand::class,
            )
        )
    ),
    
    1. 我在 /public 中创建了一个 console.php(这将使用参数运行以启动 CLI 应用程序)
    use Zend\Console\Console;
    use Zend\ServiceManager\ServiceManager;
    use ZF\Console\Application;
    use ZF\Console\Dispatcher;
    
    chdir(dirname(__DIR__));
    
    require_once 'vendor/autoload.php'; // Composer autoloader
    
    // Prepare application and service manager
    $appConfig = require 'config/application.config.php';
    $application = Zend\Mvc\Application::init($appConfig);
    $serviceManager = $application->getServiceManager();
    
    // Load modules
    $serviceManager->get('ModuleManager')->loadModules();
    $config = $serviceManager->get('config');
    $routes = $config['console']['commands']; // This depends on your structure, this is what I created (see. 1.)
    
    $application = new Application(
        $config['app'],
        $config['version'],
        $routes,
        Console::getInstance(),
        new Dispatcher($serviceManager)  // Use service manager as a dependency injection container
    );
    
    $exit = $application->run();
    exit($exit);
    
    1. 我将 CLI 命令处理程序分离到 src/Command 文件夹中。我的 CLI 命令处理程序是我定义的服务,由工厂创建。 (这就是我使用服务管理器作为容器的原因 - 请参阅。2。)

    [这里的serviceEmail是一个本地类变量,由这个命令处理程序的工厂加载。]

    /**
     * @param Route            $route
     * @param AdapterInterface $console
     *
     * @return int
     */
    public function __invoke(Route $route, AdapterInterface $console)
    {
        $mails = $this->serviceEmail->sendMailFromDb();
        $console->writeLine('Sent mails: ' . \count($mails), ColorInterface::WHITE, ColorInterface::RED);
        return 0;
    }
    

    【讨论】:

    • 它对我不起作用。我的指挥部也有一家工厂。但它不使用工厂,它直接实例化了我的命令类。
    • @bitkorn 我认为服务/工厂配置一定有问题。如果您查看并调试 zf-campus/zf-console 库的 Dispatcher.php 调度函数,您可以更接近。你缓存模块配置吗?如果是,你删除了吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-23
    • 2011-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多