Laravel 5 - 接口不可实例化

时间:2015-04-17 04:04:03

标签: php laravel repository-pattern laravel-5 laravel-ioc

我知道这个问题被问了很多次,但答案都没有帮助我。

我在Laravel 5中得到例外

BindingResolutionException in Container.php line 785:
Target [App\Contracts\CustomModelInterface] is not instantiable.

我没有成功的事情:

  • App\Providers\AppRepositoryProvider个提供商
  • 中注册app.php
  • php artisan clear-compiled
  • 如果我在MyService中替换存储库中的接口,一切都有效,但我觉得它错了(它应该由IoC容器处理吗?)。

结构:

app
  - Contracts
    - CustomModelInterface.php
  - Models
    - CustomModel.php
  - Repositories
    - CustomModelRepository.php
  - Providers
    - AppRepositoryProvider.php
  - Services
    - MyService.php

应用\合同\ CustomModelInterface.php

<?php namespace App\Contracts;

interface CustomModelInterface {
    public function get();
}

应用\库\ CustomModelRepository.php

<?php namespace App\Repositories;

use App\Contracts\CustomModelInterface;
use App\Models\CustomModel;

class CustomModelRepository implements CustomModelInterface {

    private $Model;

    public function __construct(CustomModel $model) {
        $this->Model = $model;
    }

    public function get() {
        return 'result';
    }
}

App \ Services \ MyService.php(在控制器和存储库之间保留业务逻辑/层)

<?php namespace App\Services;

use App\Contracts\CustomModelInterface;

class MyService {

    private $Model;

    public function __construct(CustomModelInterface $customModel) {
        $this->Model= $customModel;
    }

    public function getAll() {
        return $this->Model->get();
    }
}

应用\提供商\ AppRepositoryProvider.php

<?php namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppRepositoryProvider extends ServiceProvider {

    public function boot() {}

    public function register() {
        $models = array(
            'CustomModel'
        );

        foreach ($models as $idx => $model) {
            $this->app->bind("App\Contracts\{$model}Interface", "App\Repositories\{$model}Repository");
        }
    }
}

我的控制器如下:

<?php namespace App\Http\Controllers;

use App\Services\MyService;

class SuperController extends Controller {

    private $My;

    public function __construct(MyService $myService) {
        $this->My = $myService;
    }

    public function getDetails() {
        return $this->My->getAll();
    }
}

composer.json

"autoload": {
        "classmap": [
            "database"
        ],
        "psr-4": {
            "App\\": "app/",
            "App\\Models\\": "app/Models/",
            "App\\Contracts\\": "app/Contracts/",
            "App\\Repositories\\": "app/Repositories/"
        }
    },

12 个答案:

答案 0 :(得分:37)

谢谢大家,但问题出现在我的AppRepositoryProvider中。由于它的绑定异常,显然问题在于绑定:)

正确的文件是:

<?php namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class AppRepositoryProvider extends ServiceProvider {

    public function boot() {}

    public function register() {
        $models = array(
            'CustomModel',
            'CustomModel2',
            'CustomModel3'
        );

        foreach ($models as $model) {
            $this->app->bind("App\Contracts\\{$model}Interface", "App\Repositories\\{$model}Repository");
        }
    }
}

请注意,我使用"App\Contracts\\{$model}Interface"(未转义&#34; {&#34;符号)并生成正确的字符串App\Contracts\CustomModelInterface而不是App\Contracts\{$model}Interface(与意外逃脱)。

答案 1 :(得分:17)

每次我创建新的存储库/合同对时,我都要确保执行以下操作:

  1. 检查服务提供程序中使用的类(复制/粘贴命名空间)
  2. 在config / app.php
  3. 中注册新绑定
  4. php artisan optimize
  5. 许多小时的无用调试使我得到了这份简短的清单。

答案 2 :(得分:6)

对我来说,我忘了绑定app->providers->RepositoryServiceProvider 注册表方法中的存储库

public function register()
{
    $this->app->bind(
        \App\Play\Contracts\PatientRepository::class,
        \App\Play\Modules\PatientModule::class
    );
}

确保您的RepositoryServiceProvide r已在AppServiceProvider注册。

public function register()
{   
    $this->app->register(RepositoryServiceProvider::class);
}

答案 3 :(得分:5)

我跑过这个错误:

php artisan config:clear
php artisan clear-compiled
php artisan optimize
php artisan config:cache

相关:

Target is not instantiable. Laravel 5 - App binding service provider

答案 4 :(得分:2)

App\Services\MyService.php上,您正在通过依赖注入传递该接口,尝试实例化该 -

public function __construct(CustomModelInterface $customModel) {
    $this->Model= $customModel;
}

这是错误的。

尝试在该类中实现 - class MyService implements CustomModelInterface {并使用该接口的功能,如 -

$this->get();

或者您正在使用它 - class CustomModelRepository implements CustomModelInterface {

所以,如果你这样做 -

public function __construct(CustomModelRepository $customModel) {
    $this->Model= $customModel;
}

然后你也可以访问界面方法。

答案 5 :(得分:1)

我刚刚遇到了与此类似的问题,并且导致错误的原因是我在服务提供者类中将$defer设置为true,但是没有实现所需的{{1 }}方法。

如果您将类的创建推迟到需要时才进行,而不是急于加载,则还需要实现provides()方法,该方法应该简单地返回提供程序提供的类的数组。对于接口,我相信它应该是接口的名称而不是具体的类。

例如

provides

当前文档:https://laravel.com/docs/5.5/providers#deferred-providers

我希望这对其他人有帮助。

答案 6 :(得分:1)

别担心。我有解决您问题的方法。

我有个例子给你。

步骤1: php artisan make:repository存储库/发布 //通过添加此命令,您可以创建存储库和雄辩的文件

步骤2:添加该文件后,您必须在要使用的控制器中添加/使用此存储库。

例如:使用App \ Repositories \ Contracts \ PostRepository;

第3步:在您的控制器中添加该存储库后,如果您要运行该应用程序,则会收到类似“接口不可实例化”的错误。之所以会这样,是因为您已经创建了一个存储库并在控制器中使用了它,但是laravel不知道该存储库在何处注册并与哪个雄辩者绑定。这样就会引发错误。

第4步:要解决此错误,您必须在 AppServiceProvider 中将您的仓库与您的口才绑定。     例如:

AppServiceProvider.php文件

<?php
namespace App\Providers;

// **Make sure that your repo file path and eloquent path must be correct.**

use App\Repositories\Contracts\PostRepository;         // **Use your repository here**

use App\Repositories\Eloquent\EloquentPostRepository;  **// Use your eloquent here**

use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider {
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register() {

**// And bind your repository and eloquent here. **

        $this->app->bind(PostRepository::class, EloquentPostRepository::class);
    }
}

Step5:绑定回购协议并雄辩地说,您可以在控制器中使用所有回购方法。享受.....

如果您有任何疑问,请告诉我。

答案 7 :(得分:1)

通过在app / providers / AppServiceProvider中添加存储库解决了问题 像下面的例子一样。

public function register()
{
    $this->app->singleton(UserRepository::class, EloquentUser::class);
 }

不要忘记名称空间

use Test\Repositories\EloquentUser;
use Test\Repositories\UserRepository;

对我有用

答案 8 :(得分:0)

我认为这里的问题是你没有将App\Contracts\CustomModelInterface绑定到任何东西,所以Laravel试图创建接口的实例。

App\Providers\AppRepositoryProvider.php中你只有:

$models = array(
            'Model'
        );

但你也应该在这个数组中CustomModel,所以看起来应该是这样的:

$models = array(
            'Model',
            'CustomModel',
        );

答案 9 :(得分:0)

请注意,这也可能是由于类上的_constructor被声明为private,或者被阻止... 如果它无法调用构造函数,则绑定将失败

答案 10 :(得分:0)

您要做的最后一件事是使用绑定到存储库的接口。

设置它并尝试运行您的laravel应用程序以确保您没有错误。

就我而言,我的存储库和界面之间存在不匹配。

interface UserRepositoryInterface{
  public function get($userId); 
}

class UserRepository implements UserRepositoryInterface{
  public function get(int $userId);
}

正如您所看到的,接口get方法不包含类型提示,但UserRepository类的'get方法有类型提示。

如果您立即开始使用接口绑定,则不会出现此错误。

答案 11 :(得分:-1)

执行此命令:

composer dump-autoload

此命令将重新映射您的laravel自动加载类以及我以前遇到过的所有其他供应商,这是可以将其与“ -o”参数一起使用以进行优化的技巧。