简体   繁体   中英

Catchable fatal error: Argument 1 passed to Album\Controller\AlbumController::__construct() must be an instance of Album\Model\AlbumTable, none given

I have just installed the project with the help of documentation; and I am getting this error:

ERROR

Catchable fatal error: Argument 1 passed to Album\Controller\AlbumController::__construct() must be an instance of Album\Model\AlbumTable, none given, called in C:\wamp64\www\myalbums\vendor\zendframework\zend-servicemanager\src\Factory\InvokableFactory.php on line 30 and defined in C:\wamp64\www\myalbums\module\Album\src\Controller\AlbumController.php on line 15

module.config.php

<?php
namespace Album;

use Zend\Router\Http\Segment;
use Zend\ServiceManager\Factory\InvokableFactory;

return [
    'controllers' => [
        'factories' => [
            Controller\AlbumController::class => InvokableFactory::class,
        ],
    ],


    // The following section is new and should be added to your file:
    'router' => [
        'routes' => [
            'album' => [
                'type'    => Segment::class,
                'options' => [
                    'route' => '/album[/:action[/:id]]',
                    'constraints' => [
                        'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
                        'id'     => '[0-9]+',
                    ],
                    'defaults' => [
                        'controller' => Controller\AlbumController::class,
                        'action'     => 'index',
                    ],
                ],
            ],
        ],
    ],

    'view_manager' => [
        'template_path_stack' => [
            'album' => __DIR__ . '/../view',
        ],
    ],
];

AlbumTable.php

namespace Album\Model;

use RuntimeException;
use Zend\Db\TableGateway\TableGatewayInterface;

class AlbumTable
{
    private $tableGateway;

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

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

    public function getAlbum($id)
    {
        $id = (int) $id;
        $rowset = $this->tableGateway->select(['id' => $id]);
        $row = $rowset->current();
        if (! $row) {
            throw new RuntimeException(sprintf(
                'Could not find row with identifier %d',
                $id
            ));
        }

        return $row;
    }

    public function saveAlbum(Album $album)
    {
        $data = [
            'artist' => $album->artist,
            'title'  => $album->title,
        ];

        $id = (int) $album->id;

        if ($id === 0) {
            $this->tableGateway->insert($data);
            return;
        }

        if (! $this->getAlbum($id)) {
            throw new RuntimeException(sprintf(
                'Cannot update album with identifier %d; does not exist',
                $id
            ));
        }

        $this->tableGateway->update($data, ['id' => $id]);
    }

    public function deleteAlbum($id)
    {
        $this->tableGateway->delete(['id' => (int) $id]);
    }
}

AlbumController.php

namespace Album\Controller;

use Album\Model\AlbumTable;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;

class AlbumController extends AbstractActionController
{

        // Add this property:
    private $table;

    // Add this constructor:
    public function __construct(AlbumTable $table)
    {
        $this->table = $table;
    }


    public function indexAction()
    {
        return new ViewModel([
            'albums' => $this->table->fetchAll(),
        ]);
    }

    public function addAction()
    {
    }

    public function editAction()
    {
    }

    public function deleteAction()
    {
    }
}

The error comes from AlbumController constructor which expects an AlbumTable object to be injected when the former is created.

The controller is created at

Controller\AlbumController::class => InvokableFactory::class,

using the standard factory with no constructor arguments.

You need to change this to:

Controller\AlbumController::class => function($container) {
    return new Controller\AlbumController(
         $container->get(\Album\Model\AlbumTable::class)
    );
},

so that the factory is provided the dependancy(AlbumTable).

Also AlbumTable should have its own factory(maybe you already have this in your config):

use Zend\Db\ResultSet\ResultSet;
use Zend\Db\TableGateway\TableGateway;

'service_manager' => [
        'factories' => [
            \Album\Model\AlbumTable::class =>  function($sm) {
                $tableGateway = $sm->get('AlbumTableGateway');
                $table = new \Album\Model\AlbumTable($tableGateway);
                return $table;
            },
            'AlbumTableGateway' => function ($sm) {
                $dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
                $resultSetPrototype = new ResultSet();
                return new TableGateway('album', $dbAdapter, null, $resultSetPrototype);
            },
        ]
    ],

where 'album' at TableGateway('album') is your database table name.

References

Controller\AlbumController::class => InvokableFactory::class,

change to

 Controller\AlbumController::class => Controller\AlbumControllerFactory::class,

then create AlbumControllerFactory class in Controller dir

namespace Album\Controller;

use    Album\Controller\AlbumController;
use    Zend\ServiceManager\Factory\FactoryInterface;
use    Interop\Container\ContainerInterface;
use    Album\Model\AlbumTable;

class AlbumControllerFactory implements FactoryInterface {
    public function __invoke(ContainerInterface $container, $requestedName, array $options = null){
        $model = $container->get(AlbumTable::class);
        return new AlbumController($model);
    }
}

also, if you don't have factory for AlbumModel you can create it same way so your modlue.config.php would look like for eg.

....
'controllers' => [
    'factories' => [
        Controller\AlbumController::class => Controller\AlbumControllerFactory::class,
    ],
],
'service_manager' => [
    'factories' => [
        Model\AlbumModel::class => Model\AlbumModelFactory::class,
    ],
],
....

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM