Rlecomte
Rlecomte

Reputation: 3

Zend Framework 3 : Unable to resolve service as a factory

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 "Fourniture\Model\FournitureTable" 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 Fourniture\Model;

    use RuntimeException;
    use Zend\Db\TableGateway\TableGatewayInterface;
    use Zend\Db\Sql\Expression;
    use Zend\Db\Sql\Select;

    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 Fourniture\Model\Factory;

use Fourniture\Model\Fourniture;
use Fourniture\Model\FournitureTable;

use Interop\Container\ContainerInterface;
use Interop\Container\Exception\ContainerException;

use Zend\Db\ResultSet\ResultSet;
use Zend\Db\Adapter\AdapterInterface;
use Zend\Db\TableGateway\TableGateway;

use Zend\ServiceManager\Exception\ServiceNotCreatedException;
use Zend\ServiceManager\Exception\ServiceNotFoundException;
use Zend\ServiceManager\Factory\FactoryInterface;

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 Fourniture\Model\FournitureTable;
use Fourniture\Controller\FournitureController;
use Fourniture\Factory\FournitureControllerFactory;
use Fourniture\Model\Factory\FournitureTableFactory;
use Zend\Router\Http\Segment;

return [
    'controllers' => [
        'factories' => [
            Fourniture\Controller\FournitureController::class => Fourniture\Factory\FournitureControllerFactory::class,
            Fourniture\Model\FournitureTable::class => Fourniture\Model\Factory\FournitureTableFactory::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 !

Upvotes: 0

Views: 1145

Answers (1)

Ermenegildo
Ermenegildo

Reputation: 1308

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 \Model\Factory 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 Fourniture\Model\FournitureTable;
use Fourniture\Controller\FournitureController;
use Fourniture\Factory\FournitureControllerFactory;
use Fourniture\Model\Factory\FournitureTableFactory;
use Zend\Router\Http\Segment;

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

Upvotes: 1

Related Questions