Zend Framework 3 : Unable to resolve service as a factory

Tags: , ,



I already saw many threads about my issue but none of the was able to fix it..

Indeed, I made a factory for my FournitureTable Model and the error returned is :

Unable to resolve service "FournitureModelFournitureTable" to a factory; are you certain you provided it during configuration?

Here’s the main structure of my module:

... Fourniture
  /config/module.config.php
  /src/Controller/FournitureController.php
      /Factory/FournitureControllerFactory.php
      /Model
         /Factory/FournitureTableFactory.php
         Fourniture.php
         FournitureTable.php
      Module.php # Which only contains getConfig() method


FournitureTable.php

<?php 
    namespace FournitureModel;

    use RuntimeException;
    use ZendDbTableGatewayTableGatewayInterface;
    use ZendDbSqlExpression;
    use ZendDbSqlSelect;

    class FournitureTable {
        private $tableGateway;
        
        public function __construct(TableGatewayInterface $tableGateway){
            $this->tableGateway = $tableGateway;
        }

        public function fetchAll(){
            return $this->tableGateway->select();
        }

        public function getSupplyByCategId($id){
            
            $select = $this->tableGateway->getSql()->select()
            ->join(['sc' => 'sous_categorie'], 'fournitures.categorie = sc.id', ['nom'],
                Select::JOIN_LEFT)
            ->where(['fournitures.categorie' => (int)$id]);
            
            $result = $this->tableGateway->selectWith($select);
            return $result;
        }
    }
?>

FournitureTableFactory.php

<?php

namespace FournitureModelFactory;

use FournitureModelFourniture;
use FournitureModelFournitureTable;

use InteropContainerContainerInterface;
use InteropContainerExceptionContainerException;

use ZendDbResultSetResultSet;
use ZendDbAdapterAdapterInterface;
use ZendDbTableGatewayTableGateway;

use ZendServiceManagerExceptionServiceNotCreatedException;
use ZendServiceManagerExceptionServiceNotFoundException;
use ZendServiceManagerFactoryFactoryInterface;

class FournitureTableFactory implements FactoryInterface
{
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
    {
        $dbAdapter = $container->get(AdapterInterface::class);
        $resultSetPrototype = new ResultSet();
        $resultSetPrototype->setArrayObjectPrototype(new Fourniture());
        $tableGateway = new TableGateway('fournitures', $dbAdapter, null, $resultSetPrototype);

        return new FournitureTable($tableGateway);
    }
}

module.config.php

<?php
//@NOTE : Se référer aux commentaires de /module/Application/config/module.config.php pour le routage, les contrôleurs et les vues

use FournitureModelFournitureTable;
use FournitureControllerFournitureController;
use FournitureFactoryFournitureControllerFactory;
use FournitureModelFactoryFournitureTableFactory;
use ZendRouterHttpSegment;

return [
    'controllers' => [
        'factories' => [
            FournitureControllerFournitureController::class => FournitureFactoryFournitureControllerFactory::class,
            FournitureModelFournitureTable::class => FournitureModelFactoryFournitureTableFactory::class,
        ],
    ],
    'view_manager' => [
        'template_path_stack' => [
            'fourniture' => __DIR__ . '/../view',
            __DIR__ . '/../view', 
        ],
    ],
];
?>

I’m new on Zend 3 and StackOverflow so sorry if my explanation are a little consfused.

Also sorry if my English is not perfect, I’m French.

Thank’s in advance !

Answer

You declared the factory under the wrong configuration key.

controllers configuration is meant, as the name suggests, for… controllers. Only the ControllerManager looks inside into that configuration.

The one you are looking for is service_manager, as told in the tutorial.
Actually, in the tutorial they retrieve the configuration through the ConfigProviderInterface methods, but here you’ll find the corresponding array key configuration.

Last two tips:

  • since you are declaring all the classes at the beggining of the file (use ....), there is no need to use the fully qualified name space inside the array
  • try to keep consistence in your structure. You put FournitureTableFactory inside the ModelFactory folder, but the FournitureControllerFactory inside Factory folder. Two factories located in two locations, following two different logics, it doesn’t make a lot of sense 😉

Change your module.config.php with this:

<?php

use FournitureModelFournitureTable;
use FournitureControllerFournitureController;
use FournitureFactoryFournitureControllerFactory;
use FournitureModelFactoryFournitureTableFactory;
use ZendRouterHttpSegment;

return [
    'controllers' => [
        'factories' => [
            FournitureController::class => FournitureControllerFactory::class
        ],
    ],
    'service_manager' => [
        'factories' => [
            FournitureTable::class => FournitureTableFactory::class
        ]
    ],
    'view_manager' => [
        'template_path_stack' => [
            'fourniture' => __DIR__ . '/../view',
            __DIR__ . '/../view', 
        ],
    ],
];
?>


Source: stackoverflow