dezgo's avatar

Cannot instantiate interface error

I'm trying to decouple my code by creating an interface to a settings class.

I have this interface class in app\Contracts\Settings.php

<?php

namespace App\Contracts;

use Illuminate\Http\Request;

interface Settings
{
    public function set($key, $value);

    public function get($key, $default = null);

    public function setAllUsing(Request $request);
}

Then I have a concrete implementation of that interface in app\Services\AnlutroSettings.php

<?php

namespace App\Services;

use App\Contracts\Settings as SettingsContract;

class AnlutroSettings implements SettingsContract
{
....

Then in my serviceprovider - app\Providers\AppServiceProvider.php, I have the bind command

public function register()
    {
        $this->app->bind('App\Contracts\Settings', 'App\Services\AnlutroSettings');
    }

Now finally, I want to use it. I'm currently just new'ing it up with$settings = new Settings(); I have use App\Contracts\Settings; at the top of that class

But when I try to run my database seeder, which calls the above code to new up the settings class, I'm getting an error

PHP Fatal error:  Cannot instantiate interface App\Contracts\Settings in /home/vagrant/Git/invoicingzen/app/Invoice.php on line 70

line 70 is that new statement.

What am I doing wrong here? Note I'm using Laravel 5.2

0 likes
4 replies
moharrum's avatar

You have to use the IoC container to inject the class,

In your seeder:

    private $settings;

    public function __construct(Settings $settings) {
        $this->settings = $settings;
    }
dezgo's avatar

I'm still getting the same error.

It did then instantiate my concrete Settings implementation class because it brought up a couple of errors in there, but once I corrected those, I got back to the same old 'Cannot instantiate interface' error.

It got instantiated fine when I injected it into the seederclass constructor as you suggested, so I don't understand why it doesn't instantiate when I use new to create an instance.

Tangente's avatar

I may be wrong, but I don't think you can do $settings = new Settings(); Settings class is interface, you cannot create an object of interface. You can however do $settings = new AnlutroSettings(); because it implements Settings interface.

dezgo's avatar
dezgo
OP
Best Answer
Level 1

OK yep got it, thanks @daniyum21 . I didn't want to directly create AnlutroSettings - that would defeat the purpose of using the interface as I'd then still have to change code in a lot of places if I start using a new settings class. However this also works:

$settings = \App::make('App\Contracts\Settings');
3 likes

Please or to participate in this conversation.