4

I made a command in TYPO3 which has arguments and dependency injection (DI). As I understood in symfony DI is made with the __construct method. But there I also have to state the argument which I want to pass to the command. So how is it done correctly?

Sources:

Versions: TYPO3 9.5.5, symfony 4.2.5

Say I want to pass one argument to the command AND inject the ObjectManager from TYPO3:

<?php

namespace Vendor\ExtensionName\Command;

use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
use Symfony\Component\Console\Command\Command;

class SomeCommand extends Command 
{

    /**
     * Object Manager
     *
     * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
     */
    protected $objectManager;

    /**
     * @param \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager
     */
    public function __construct(
        string $cliParameter,
        \TYPO3\CMS\Extbase\Object\ObjectManagerInterface $objectManager) 
    {
        $this->cliParameter = $cliParameter;
        $this->objectManager = $objectManager;
    }
}

Then I call this with

bin/typo3 extension_name:someCommand foo

(where foo is the $cliParameter)

I get

Uncaught TYPO3 Exception Cannot instantiate interface TYPO3\CMS\Extbase\Object\ObjectManagerInterface

So my question is: What did I wrong? What's the correct way to do this?

Rintisch
  • 424
  • 4
  • 15
  • what 's the symfony version ? – Yassine CHABLI Apr 03 '19 at 08:41
  • have you tried to inject the ObjectManager instead of the ObjectManagerInterface? (yes, it is frowned upon to rely on a specific implementation, but maybe typo3 DI is not smart enough...?) – Jakumi Apr 03 '19 at 09:02

1 Answers1

7

Symfony commands are unrelated to Extbase. So you cannot use DI before TYPO3v10. However, you can still get yourself an instance of the ObjectManager and then retrieve any object you need:

$objectManager = GeneralUtility::makeInstance(ObjectManager::class);
$exampleRepository = $objectManager->get(ExampleRepository::class);

If a class does not rely on Extbase or its DI, you can directly get an instance with GeneralUtility::makeInstance() instead.

Notice that with TYPO3v10 or newer you can use the native TYPO3 DI for commands instead.

Mathias Brodala
  • 5,905
  • 13
  • 30
  • 2
    Now ObjectManager::get is deprecated. I am searching for a way to inject my repository into the console command and I don't know how. – Martin May 08 '20 at 13:11
  • 1
    Yes I would like to know this too – Jacco van der Post Jun 02 '20 at 09:47
  • someone found solution how to inject repository in to console command? – patryno Jun 10 '20 at 08:54
  • 3
    Starting from TYPO3 version 10.3, you can use DI in symfony commands by defining the command in the Services.yaml configuration as explained [here](https://docs.typo3.org/c/typo3/cms-core/master/en-us/Changelog/10.3/Feature-89139-AddDependencyInjectionSupportForConsoleCommands.html). Don't forget to flush the cache in the install tool after changing the Services.yaml file. – Christian Fries Dec 17 '20 at 11:43
  • Thanks @ChristianFries, I've just incorporated this. – Mathias Brodala Mar 02 '22 at 11:40
  • Everything you say is correct (regarding availability of DI in different contexts and T3 versions etc.), but IMHO one key aspect of OP's question is never answered: how DO you combine your own dynamic (ie not hardcoded in services.yaml) "arguments AND dependency injection"? I'm struggling with that in V11 while migrating a service class and the docs are not really clear about this (not to me at least...). But maybe this should go into a separate question. It just seemed to me that this combination was the actual issue at the heart of this question. – Stoppeye Apr 05 '23 at 10:16
  • Yes, this is a different topic. Symfony command arguments are handled via an API, not via PHP "function arguments". – Mathias Brodala Apr 11 '23 at 06:41