php Laravel 5 - 接口不可实例化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29690056/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-26 00:31:34  来源:igfitidea点击:

Laravel 5 - Interface is not instantiable

phplaravelrepository-patternlaravel-5laravel-ioc

提问by Andrew Kulakov

I know that this question was asked so many times, but none of answers helped me.

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

I'm getting exception in Laravel 5

我在 Laravel 5 中遇到异常

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

What I've done without success:

我所做的没有成功:

  • Register App\Providers\AppRepositoryProviderin app.phpproviders
  • php artisan clear-compiled
  • Everything works if I replace interfaces on repositories in MyService, but I feel that it's wrong (should it be handled by IoC container?).
  • App\Providers\AppRepositoryProviderapp.php提供者中注册
  • php artisan clear-compiled
  • 如果我在 MyService 中替换存储库上的接口,一切正常,但我觉得这是错误的(应该由 IoC 容器处理吗?)。

Structure:

结构:

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

App\Contracts\CustomModelInterface.php

App\Contracts\CustomModelInterface.php

<?php namespace App\Contracts;

interface CustomModelInterface {
    public function get();
}

App\Repositories\CustomModelRepository.php

App\Repositories\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 (Keep business logic / layer between controller and repositories)

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

App\Providers\AppRepositoryProvider.php

App\Providers\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");
        }
    }
}

My controller looks like:

我的控制器看起来像:

<?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

作曲家.json

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

采纳答案by Andrew Kulakov

Thank you everyone, but problem was in my AppRepositoryProvider. As it's binding exception, then obviously the problem was with binding :)

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

Correct file is:

正确的文件是:

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

Note, that I'm using "App\Contracts\\{$model}Interface"(not escaping "{" symbol) and it generate correct string App\Contracts\CustomModelInterfaceinstead of App\Contracts\{$model}Interface(with unexpected escaping).

请注意,我正在使用"App\Contracts\\{$model}Interface"(不转义“{”符号)并且它生成正确的字符串App\Contracts\CustomModelInterface而不是App\Contracts\{$model}Interface(意外转义)。

回答by Vlad Visinescu

Every time I create a new repository/contract pair I make sure I do the following:

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

  1. check the classes used in the service provider (copy/paste the namespaces)
  2. register a new binding in config/app.php
  3. php artisan optimize
  1. 检查服务提供者中使用的类(复制/粘贴命名空间)
  2. 在 config/app.php 中注册一个新的绑定
  3. php工匠优化

Many hours of useless debugging led me to this short checklist.

许多小时的无用调试使我找到了这个简短的清单。

回答by Beulah Ana

For me, I forgot to bind in app->providers->RepositoryServiceProviderthe repository like this in the register method

对我来说,我忘记app->providers->RepositoryServiceProvider在注册方法中像这样绑定到存储库中

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

Make sure your RepositoryServiceProvider is registered in AppServiceProvider.

确保您的RepositoryServiceProvider 已在AppServiceProvider.

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

回答by Connor Leech

I got past this error running:

我克服了这个错误运行:

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

Related to:

相关:

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

目标不可实例化。Laravel 5 - 应用绑定服务提供者

回答by Sougata Bose

On App\Services\MyService.phpyou are passing that interface with dependency injection which tries to instantiate that -

App\Services\MyService.php你逝去的依赖注入该接口它试图实例化-

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

which is wrong.

这是错误的。

Try implement that in that class - class MyService implements CustomModelInterface {and use the function of that interface like -

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

$this->get();

Or you are using it - class CustomModelRepository implements CustomModelInterface {

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

So if you do -

所以如果你这样做——

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

then also you can access the interface methods.

然后你也可以访问接口方法。

回答by Kenny Body

I've just experienced an issue similar to this and the cause of my error was that I had set $deferto truein the service provider class but I had not implemented the required provides()method.

我刚刚遇到了一个与此类似的问题,我的错误的原因是我在服务提供者类中设置$defertrue,但我没有实现所需的provides()方法。

If you have deferred the creation of your class until it is need rather than it being loaded eagerly, then you need to also implement the providesmethod which should simply return an array of the classes that the provider provides. In the case of an interface, I believe it should be the name of the interface rather than the concrete class.

如果您推迟了类的创建,直到需要它而不是急切地加载它,那么您还需要实现该provides方法,该方法应该简单地返回提供者提供的类的数组。在接口的情况下,我认为它应该是接口的名称而不是具体的类。

E.g.

例如

public method provides(): array
{
    return [
        MyInterface::class,
    ];
}

Current documentation: https://laravel.com/docs/5.5/providers#deferred-providers

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

I hope this helps somebody else.

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

回答by Umang Soni

Don't worry guys. I have a solution to your problem.

别担心,伙计们。我有一个解决你的问题的方法。

I have an example for you.

我有一个例子给你。

Step1: php artisan make:repository Repository/Post//By adding this command you can create a repository and eloquent files

Step1: php artisan make:repository Repository/Post//添加这个命令就可以创建repository和eloquent文件

Step2: After adding that file you have to add/use this repository in the controller in which you want to use.

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

for eg: use App\Repositories\Contracts\PostRepository;

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

Step3: After adding that repo in your controller if you will run the app you will get an error like " Interface is not instantiable". It comes because you have created a repo and used in a controller, but laravel don't know where this repository is register and bind with which eloquent. So that it throws an error.

第 3 步:在您的控制器中添加该 repo 后,如果您将运行该应用程序,您将收到类似“接口不可实例化”的错误消息。这是因为你已经创建了一个 repo 并在一个控制器中使用,但是 laravel 不知道这个存储库在哪里注册并绑定到哪个 eloquent。所以它会抛出一个错误。

Step4: To solve this error you have to bind your repo with your eloquent in AppServiceProvider. E.g:

步骤 4:要解决此错误,您必须将您的 repo 与AppServiceProvider 中的 eloquent 绑定。例如:

AppServiceProvider.php file

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: After binding repo and eloquent you can use all method of repo in your controller. Enjoy.....

第五步:绑定 repo 和 eloquent 后,您可以在控制器中使用所有 repo 方法。享受.....

Please let me know if you have any query.

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

回答by jibril90

The problem is solved by adding your repository in app/providers/AppServiceProvider like the example below.

通过在 app/providers/AppServiceProvider 中添加您的存储库来解决该问题,如下例所示。

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

Dont forget the name space

不要忘记命名空间

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

It worked for me

它对我有用

回答by Softmixt

execute this command :

执行这个命令:

composer dump-autoload

回答by Lea de Groot

Note that this can also be caused by the _constructor on the class being declared private, or otherwise being blocked... If it cant call the constructor, the binding will fail

请注意,这也可能是由于类上的 _constructor 被声明为私有导致的,或者以其他方式被阻塞......如果它无法调用构造函数,则绑定将失败