Problems with instancing a command for laminas-cli

Hi there, I’m pretty new on PHP/Laminas. I joined a nice team and we try to migrate an old project to PHP 8.
We were using Laminas/Console and now we try to use Symfony.
We have a service to update currencies into DB. So we want to keep it and beeing able to run it with a command like this :
.\vendor\bin\laminas import-currency
To do it, we created a CurrencyCommand class, extending from Command. In this class we want to call our previous method to update currencies:

 class CurrencyCommand extends Command implements AbstractCustomService {
     /**
      * @var CurrencyService
      */
     protected $service;
 
     /** @var string */
     protected static $defaultName = 'import-currency';
 
     public function __construct(CurrencyService $currencyService, string $name = null){
         parent::__construct($name);
 
         $this->serivce = $currencyService;
     }
 
     protected function configure() : void
     {
         $this->setName(self::$defaultName);
         $this->addOption('name', null, InputOption::VALUE_REQUIRED, 'Module name');
     }
 
     protected function execute(InputInterface $input, OutputInterface $output): int
     { 
         $this->getService()->importData();
         return 0;
     }
 
     /**
      * @return CurrencyService
      */
     public function getService(): CurrencyService {
         return $this->service;
     }
 
     /**
      * @param CurrencyService $service
      * @return ConsoleController
      */
     public function setService($service): ConsoleController {
         $this->service = $service;
         return $this;
     }
 
     public function getServiceName(): string {
         return CurrencyService::class;
     }
 }

We were also using a factory :

class CurrencyServiceFactory implements FactoryInterface {
    /**
     * @param ContainerInterface $container
     * @param string $requestedName
     * @param array|null $options
     * @return CurrencyService
     * @throws ContainerException
     */
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null) {
        $baseServiceFactory = new BaseServiceFactory();
        /**
         * @var $currencyService CurrencyService
         */
        $currencyService = $baseServiceFactory($container, CurrencyService::class, $options);

        $config = $container->get('Config');

        if (!isset($config['fixerio_api_key'])) {
            throw new ServiceNotCreatedException("Please provide Fixer IO api key in config -> fixerio_api_key");
        }
        $currencyService->setApiKey($config['fixerio_api_key']);

        return $currencyService;
    }

}

The config file looks like this :

<?php

namespace Currency;

use Currency\Command\CurrencyCommand;
use Currency\Service\Factory\CurrencyServiceFactory;

return [
    'laminas-cli' => [
        'commands' => [
            'import-currency' => CurrencyCommand::class,
        ],
    ],
    'service_manager' => [
        'factories' => [
            CurrencyCommand::class => CurrencyServiceFactory::class,
        ],
    ],
];

Our problem is, when we run the command, we get :

Expected an instance of Symfony\Component\Console\Command\Command. Got: Currency\Service\CurrencyService

If we remove the service_manager, we’re not able to call the “importData()” function anymore

Any idea ?

Thanks

Hello and welcome to our forums! :smiley:

You mean laminas-cli. :wink:

You should recheck the command class because the $this->serivce !== $this->service.

Hey ! Thanks for you answer !
Yes yes, Laminas-cli… Probably too tired :slight_smile:

I guess it’s not correct, but don’t really know how to fix it in fact. My CurrencyCommand class extends from Command, but CurrencyService extends from a custom service (extends from BaseService, here below):

class BaseService {

    /**
     * @var Logger
     */
    protected $logger;

    /**
     * @var ContactRecordService
     */
    protected $contactRecordService;

    /**
     * @var Adapter
     */
    protected $dbAdapter;

    /**
     * @var EntityManager
     */
    private $entityManager;

    /**
     * @var User
     */
    protected $identity;

    /**
     * @var Login
     */
    private $login;

    /**
     * @var TranslatorInterface
     */
    protected $translator;

    /**
     * @var LogMessageService
     */
    protected $logMessageService;

    /**
     * BaseService constructor.
     * @param $dbAdapter Adapter
     * @param $entityManager EntityManager
     * @param $identity User
     * @param $logMessageService LogMessageService
     * @param $logger Logger
     */
    public function __construct($dbAdapter, $entityManager, $identity, $logMessageService, $logger) {
        $this->dbAdapter = $dbAdapter;
        $this->entityManager = $entityManager;
        $this->identity = $identity;
        $this->logMessageService = $logMessageService;
        $this->logger = $logger;
    }

    /**
     * @param $translator TranslatorInterface
     */
    public function setTranslator($translator) {
        $this->translator = $translator;
    }

    /**
     * @return Login
     */
    protected function getLoginFromIdentity() {
        if (is_null($this->login)) {
            $this->login = $this->entityManager->getRepository(Login::class)->findOneBy(["id" => $this->identity->getId()]);
        }

        return $this->login;
    }

    protected function resetLoginEntityFromIdentity() {
        $this->login = null;
    }

    /**
     * @return EntityManager
     * @throws \Doctrine\ORM\ORMException
     */
    protected function getEntityManager(): EntityManager {

        if (!$this->entityManager->isOpen()) {
            $this->entityManager = $this->entityManager->create(
                $this->entityManager->getConnection(), $this->entityManager->getConfiguration());
        }

        return $this->entityManager;
    }


    /**
     * @param $object object
     * @param $key string
     * @param $value string
     * @throws
     */
    protected function saveValue($object, $key, $value, $forceCreation = false) {
        if ($key == "security") {
            return;
        } else if ($key == "address") {
            /**
             * @var $addressRepository AddressRepository
             */
            $addressRepository = $this->getEntityManager()->getRepository(Address::class);
            $address = $addressRepository->getAddress($value, $forceCreation);
            if(!is_null($object)){
                $object->setAddress($address);
            }
            return $address;

        } else if (Tools::in_array_recursive($key, ContactRecordService::TYPE_TO_NAME) &&
            Tools::isClassOrSubClassOfWithArray($object, ContactRecordService::LIST_OBJECT_TYPE_MAPPING) &&
            $value != "") {
            $this->contactRecordService->saveRecord($key, $value, $object);
        } else {
            $functionName = "set" . Tools::snakeToCamelCase($key, true);
            if (method_exists($object, $functionName)) {
                $object->$functionName($value);

            }
        }
    }

    /**
     * @return User
     */
    public function getIdentity(): User {
        return $this->identity;
    }

    /**
     * @param ContactRecordService $contactRecordService
     */
    public function setContactRecordService(ContactRecordService $contactRecordService) {
        $this->contactRecordService = $contactRecordService;
    }

    protected function filterSearchText($textSearch) {
        $textSearch = trim($textSearch);
        return $textSearch;
    }
}

This is just a typo! Change from $this->serivce to $this->service.

Which is a God object. You need to get rid of that because it will always create problems.
At the moment you have the problem that something is wrongly assigned or wrongly created.

1 Like

Hmmm as I thought, too tired to see the typo… :frowning:

I will try to deal without the God object. Thanks