Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Arguement passed to constructor must be an instance of interface, instance of decorator given

I am having an issue trying to debug my code, as far as I can see looking at the various bits of code, it all links up correctly, but there must be something obvious I am missing here.

I am sorry about the amount of code I've pasted in to the question here, but unfortunately there are a lot of files in play for a single entity of the application, and I thought it better to provide more rather than less.

First of all the error message:

Argument 1 passed to Raid\Composers\PreferenceDataComposer::__construct() must be an instance of Raid\Repo\User\PreferenceInterface, instance of Raid\Repo\Preference\CacheDecorator given, called in C:\wamp\www\raid\app\Raid\Composers\ComposerServiceProvider.php on line 34 and defined

So first of all, my view composer which is where this error is being generated:

<?php namespace Raid\Composers;

use Raid\Repo\User\PreferenceInterface;

class PreferenceDataComposer {

    protected $preference;

    public function __construct(PreferenceInterface $preference)
    {
        $this->preference = $preference;
    }

    public function compose($view)
    {       
        $view->with('preferences', $this->preference->getActive());
    }

}

and then the service provider for the composer:

<?php namespace Raid\Composers;

use Illuminate\Support\ServiceProvider;

class ComposerServiceProvider extends ServiceProvider {

    public function register()
    {
        $this->app->bind('Raid\Composers\PreferenceDataComposer', function($app)
        {
            return new PreferenceDataComposer(
                $this->app->make('Raid\Repo\Preference\PreferenceInterface')
            );
        });
    }

    public function boot()
    {
        $this->app->view->composer('account.preferences', 'Raid\Composers\PreferenceDataComposer');
    }

}

Next up is the interface:

<?php namespace Raid\Repo\Preference;

interface PreferenceInterface {

    public function getActive();

}

And the CacheDecorator:

<?php namespace Raid\Repo\Preference;

use Raid\Service\Cache\CacheInterface;

class CacheDecorator extends AbstractPreferenceDecorator implements PreferenceInterface {

    protected $cache;

    public function __construct(PreferenceInterface $preference, CacheInterface $cache)
    {
        parent::__construct($preference);
        $this->cache = $cache;
    }

    public function getActive()
    {
        $key = md5('active');

        if ($this->cache->has($key)) {
            return $this->cache->get($key);
        }

        $preferences = $this->preference->getActive();

        $this->cache->put($key, $preferences);

        return $preferences;
    }
}

and the abstract decorator:

<?php namespace Raid\Repo\Preference;

abstract class AbstractPreferenceDecorator implements PreferenceInterface {

    protected $preference;

    public function __construct(PreferenceInterface $preference)
    {
        $this->preference = $preference;
    }

}

then we have the repository:

<?php namespace Raid\Repo\Preference;

use Raid\Repo\AbstractRepo;
use Illuminate\Database\Eloquent\Model;
use Raid\Service\Log\LogInterface;
use Raid\Service\Email\EmailInterface;

class EloquentPreference extends AbstractRepo implements PreferenceInterface {

    protected $preference;
    protected $preferenceType;
    protected $log;
    protected $email;

    public function __construct(Model $preference, Model $preferenceType, LogInterface $log, EmailInterface $email)
    {
        $this->preference = $preference;
        $this->preferenceType = $preferenceType;
        $this->log = $log;
        $this->email = $email;
    }

    public function getActive()
    {
        return $this->preference->whereActive()->get();
    }

}

and then the eloquent Model itself:

<?php

class Preference extends Eloquent {

    protected $table = 'preferences';
    protected $guarded = array('id');
    protected $softDelete = true;

    public function scopeWhereActive($query)
    {
        return $query->where('active', '=', '1');
    }

}

and then the service provider that binds the interface and the repo:

<?php namespace Raid\Repo;

use Preference;
use PreferenceType;
use Raid\Service\Cache\FileCache;
use Raid\Repo\Preference\CacheDecorator as PreferenceCacheDecorator;
use Raid\Repo\Preference\EloquentPreference;
use Illuminate\Support\ServiceProvider;

class RepoServiceProvider extends ServiceProvider {

    public function register()
    {
        $app = $this->app;

        $app->bind('Raid\Repo\Preference\PreferenceInterface', function($app)
        {
            $preference = new EloquentPreference(
                new Preference, 
                new PreferenceType,
                $app->make('Raid\Service\Log\LogInterface'),
                $app->make('Raid\Service\Email\EmailInterface')
            );

            return new PreferenceCacheDecorator(
                $preference, 
                new FileCache($app['cache'], 'preferences', 1440)
            );
        });
    }

}

In the code above, you can see in the Composer, that I ask for an instance of the Interface, and in the composer's service provider, I resolve an instance of it out of the IoC.

In the repo service provider I bind the interface by making a instance of the repo (passing in its dependencies), and then return the repo wrapped with a cache decorator. All of the repo, the decorator, the abstract decorator implement the interface, so I'm not sure how it is being resolved as not being an instance of the interface?

Any help you are able to give with debugging would be me wonderful.

If you need further code, please shout.

like image 235
Mortelugo Avatar asked Sep 30 '22 22:09

Mortelugo


1 Answers

Your problem might be in Raid\Repo\User\PreferenceInterface, which should be Raid\Repo\Preference\PreferenceInterface.

Other than that I can't really see a problem in your code, to test I created some namespaces, interfaces and classes but PreferenceDataComposer instantiated with no problems for me.

In my routes.php I created one route to instantiate it, create eloquent based classes, some needed bindings, manually register Service Providers and load the namespaced file:

<?php

class Preference extends Eloquent {

    protected $table = 'preferences';
    protected $guarded = array('id');
    protected $softDelete = true;

    public function scopeWhereActive($query)
    {
        return $query->where('active', '=', '1');
    }

}

class PreferenceType extends Eloquent {

    protected $table = 'preferences';
    protected $guarded = array('id');
    protected $softDelete = true;

    public function scopeWhereActive($query)
    {
        return $query->where('active', '=', '1');
    }

}

App::bind('Raid\Service\Log\LogInterface', 'Raid\Service\Log\Log');
App::bind('Raid\Service\Email\EmailInterface', 'Raid\Service\Email\Email');
App::bind('Raid\Service\Cache\CacheInterface', 'Raid\Service\Cache\FileCache');

require app_path().'/Mortelugo.php';

Route::any('test', function() {

    $repo = new Raid\Repo\RepoServiceProvider(App::make('app'));
    $repo->register();

    $composer = new Raid\Composers\ComposerServiceProvider(App::make('app'));
    $composer->register();

    $preference = App::make('Raid\Composers\PreferenceDataComposer');

    // This is it instantiated

    dd($preference);

});

I created a Mortelugo.php file with all your namespaces, but I had to create some missing ones and change one of them that was named incorrectly:

<?php

namespace Raid\Composers {

    use Raid\Repo\Preference\PreferenceInterface;

    class PreferenceDataComposer {

        protected $preference;

        public function __construct(PreferenceInterface $preference)
        {
            $this->preference = $preference;
        }

        public function compose($view)
        {       
            $view->with('preferences', $this->preference->getActive());
        }

    }

}

namespace Raid\Composers {

    use Illuminate\Support\ServiceProvider;

    class ComposerServiceProvider extends ServiceProvider {

        public function register()
        {
            $this->app->bind('Raid\Composers\PreferenceDataComposer', function($app)
            {
                return new PreferenceDataComposer(
                    $this->app->make('Raid\Repo\Preference\PreferenceInterface')
                );
            });
        }

        public function boot()
        {
            $this->app->view->composer('account.preferences', 'Raid\Composers\PreferenceDataComposer');
        }

    }

}

namespace Raid\Repo {

    use Preference;
    use PreferenceType;
    use Raid\Service\Cache\FileCache;
    use Raid\Repo\Preference\CacheDecorator as PreferenceCacheDecorator;
    use Raid\Repo\Preference\EloquentPreference;
    use Illuminate\Support\ServiceProvider;

    abstract class AbstractRepo {

    }

    class RepoServiceProvider extends ServiceProvider {

        public function register()
        {
            $app = $this->app;

            $app->bind('Raid\Repo\Preference\PreferenceInterface', function($app)
            {
                $preference = new EloquentPreference(
                    new Preference, 
                    new PreferenceType,
                    $app->make('Raid\Service\Log\LogInterface'),
                    $app->make('Raid\Service\Email\EmailInterface')
                );

                return new PreferenceCacheDecorator(
                    $preference, 
                    new FileCache($app['cache'], 'preferences', 1440)
                );
            });
        }

    }

}

namespace Raid\Repo\Preference {

    interface PreferenceInterface {

        public function getActive();

    }

    use Raid\Service\Cache\CacheInterface;

    abstract class AbstractPreferenceDecorator implements PreferenceInterface {

        protected $preference;

        public function __construct(PreferenceInterface $preference)
        {
            $this->preference = $preference;
        }

    }


    class CacheDecorator extends AbstractPreferenceDecorator implements PreferenceInterface {

        protected $cache;

        public function __construct(PreferenceInterface $preference, CacheInterface $cache)
        {
            parent::__construct($preference);
            $this->cache = $cache;
        }

        public function getActive()
        {
            $key = md5('active');

            if ($this->cache->has($key)) {
                return $this->cache->get($key);
            }

            $preferences = $this->preference->getActive();

            $this->cache->put($key, $preferences);

            return $preferences;
        }
    }

    use Raid\Repo\AbstractRepo;
    use Illuminate\Database\Eloquent\Model;
    use Raid\Service\Log\LogInterface;
    use Raid\Service\Email\EmailInterface;

    class EloquentPreference extends AbstractRepo implements PreferenceInterface {

        protected $preference;
        protected $preferenceType;
        protected $log;
        protected $email;

        public function __construct(Model $preference, Model $preferenceType, LogInterface $log, EmailInterface $email)
        {
            $this->preference = $preference;
            $this->preferenceType = $preferenceType;
            $this->log = $log;
            $this->email = $email;
        }

        public function getActive()
        {
            return $this->preference->whereActive()->get();
        }

    }

}

namespace Raid\Service\Log {

    interface LogInterface {

    }

    class Log implements LogInterface {

    }

}

namespace Raid\Service\Email {

    interface EmailInterface {

    }

    class Email implements EmailInterface {

    }

}

namespace Raid\Service\Cache {

    interface CacheInterface {

    }

    class FileCache implements CacheInterface {

    }

}
like image 152
Antonio Carlos Ribeiro Avatar answered Oct 04 '22 19:10

Antonio Carlos Ribeiro