Laravel 4目标接口不可实例化

时间:2013-03-06 00:37:35

标签: namespaces ioc-container laravel laravel-4

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

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

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

以下方法完美无缺,直到我尝试引入命名空间。我可以删除所有名称空间并将接口和存储库放在同一目录中,但是想知道如何使用这种使用ioc的方法使名称空间工作。

以下是相关文件。

routes.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',

    ....
    )

我需要更改哪些或哪些内容以使其与名称空间一起使用,而不使用它们?

由于

2 个答案:

答案 0 :(得分:37)

我知道这个问题已经得到解答,但我想提醒未来的读者,这个问题的另一个常见原因是target interface is not instantiable&#34;错误是忘记在app/config/app.php注册服务提供商。

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

我犯了太多次错误,不发表任何相关信息。因此,在您沿着上面描述的冗长路径走下去之前,请确保注册这些提供商!

答案 1 :(得分:13)

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

<强> routes.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');
    }

}