可捕获致命错误:传递给Album \ Controller \ AlbumController :: __ construct()的参数1必须是Album \ Model \ AlbumTable的实例,没有给出

时间:2017-07-18 07:30:42

标签: php zend-framework3

我刚刚在文档的帮助下安装了项目;我收到了这个错误:

错误

  

可捕获的致命错误:传递给Album \ Controller \ AlbumController :: __ construct()的参数1必须是Album \ Model \ AlbumTable的实例,没有给出,在C:\ wamp64 \ www \ myalbums \ vendor中调用第30行的\ zendframework \ zend-servicemanager \ src \ Factory \ InvokableFactory.php,第15行的C:\ wamp64 \ www \ myalbums \ module \ Album \ src \ Controller \ AlbumController.php

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()
    {
    }
}

2 个答案:

答案 0 :(得分:1)

错误来自AlbumController构造函数,它需要在创建前者时注入AlbumTable对象。

控制器在

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

使用没有构造函数参数的标准工厂。

您需要将其更改为:

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

以便为工厂提供依赖性(AlbumTable)。

AlbumTable也应该有自己的工厂(也许你的配置中已经有了这个):

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);
            },
        ]
    ],

其中&#39;专辑&#39; at TableGateway('album')是您的数据库表名。

答案 1 :(得分:0)

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

更改为

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

然后在Controller dir中创建AlbumControllerFactory类

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);
    }
}

另外,如果你没有AlbumModel的工厂,你可以用同样的方式创建它 所以你的modlue.config.php看起来就像是。

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