7

这与这个问题有关How to register a namespace in laravel 4但我相信我已经解决了,并且命名空间现在正在工作。

我遇到了一个新问题。我相信错误来自尝试在控制器构造函数中键入提示,并且与使用命名空间和使用 ioc 有关。

BindingResolutionException: Target [App\Models\Interfaces\PostRepositoryInterface] is not instantiable.

在我尝试引入命名空间之前,下面的方法运行良好。我可以删除所有命名空间并将接口和存储库放在同一目录中,但想知道如何使命名空间与这种使用 ioc 的方法一起工作。

以下是相关文件。

路由.php

Route::resource('posts', 'PostsController');

PostController.php

<?php
use App\Models\Interfaces\PostRepositoryInterface;
class PostsController extends BaseController {

    public function __construct( PostRepositoryInterface $posts )
    {
        $this->posts = $posts; 
    }

}

PostRepositoryInterface.php

<?php namespace App\Models\Interfaces;
interface PostRepositoryInterface {
    public function all();
    public function find($id);
    public function store($data);
}

EloquentPostRepository.php

<?php namespace App\Models\Repositories;
use App\Models\Interfaces\PostRepositoryInterface;
class EloquentPostRepository implements PostRepositoryInterface {

    public function all()
    {
        return Post::all();
            //after above edit it works to this point
            //error: App\Models\Repositories\Post not found
            //because Post is not in this namespace
    }

    public function find($id)
    {
        return Post::find($id);
    }

    public function store($data)
    {
        return Post::save($data);
    }
}

你可以看到 composer dump-autoload 完成了它的工作。

作曲家/autoload_classmap.php

return array(
    'App\\Models\\Interfaces\\PostRepositoryInterface' => $baseDir . '/app/models/interfaces/PostRepositoryInterface.php',
    'App\\Models\\Repositories\\EloquentPostRepository' => $baseDir . '/app/models/repositories/EloquentPostRepository.php',

    ....
    )

任何想法我需要更改哪些地方或哪些内容才能使其与命名空间一起工作,就像没有它们一样?

谢谢

4

2 回答 2

37

我知道这个问题已经得到解答,但我想提醒未来的读者,这个“ target interface is not instantiable”错误的另一个常见原因是忘记在app/config/app.php.

这仅适用于您扩展 ServiceProvider 类的情况,而不适用于使用App::bind().

我犯了太多次这个错误,所以没有发布关于它的东西。因此,在您走上上述漫长道路之前,请务必注册这些提供商!

于 2013-09-26T19:27:30.573 回答
13

好的,简短的回答:使用 App::bind() 中的完整命名空间来修复第一个错误。然后在 EloquentPostRepository.php 中,因为它有一个声明的命名空间,它会尝试将任何其他外部类调用视为在同一个命名空间中。添加一个简单的“使用帖子;” 让 PHP 知道“Post”不在同一个命名空间(App\Models\Repositories)中。我认为这是因为一旦使用了命名空间,其他类默认具有任何类名的命名空间。我认为重新发布所有更正并正常工作的代码是最简单的。

路由.php

<?php

App::bind('App\Models\Interfaces\PostRepositoryInterface',  'App\Models\Repositories\EloquentPostRepository');

Route::resource('posts', 'PostsController');

PostController.php

<?php
use App\Models\Interfaces\PostRepositoryInterface;

class PostsController extends BaseController {

    public function __construct(PostRepositoryInterface $posts)
    {
        $this->posts = $posts;
    }

EloquentPostRepository.php

<?php namespace App\Models\Repositories;
use App\Models\Interfaces\PostRepositoryInterface;
use Post;
class EloquentPostRepository implements PostRepositoryInterface {

    public function all()
    {
        return Post::all();
    }

    public function find($id)
    {
        return Post::find($id);
    }

    public function store($data)
    {
        return Post::save($data);
    }
}

PostRepositoryInterface.php

<?php namespace App\Models\Interfaces;
interface PostRepositoryInterface {
    public function all();
    public function find($id);
    public function store($data);
}

Post.php 除了显示它没有声明的命名空间之外,这里没有任何相关内容

<?php
class Post extends BaseModel {

    public static $rules = [
        'title' => 'required',
        'body' => 'required',
        'author_id' => 'required|numeric'
    ];

    public static $factory = [
        'title' => 'string',
        'body' => 'text'
    ];

    public function user()
    {
        return $this->belongsTo('User', 'author_id');
    }

}
于 2013-03-06T04:32:11.610 回答