传递给构造函数的参数必须是接口的实例,给定的decorator实例

时间:2014-04-30 08:30:15

标签: php laravel laravel-4

我在尝试调试代码时遇到了问题,只要我看到代码的各个部分,它们都能正确链接,但必须有一些显而易见的东西在这里。

我很抱歉我已经粘贴到这个问题的代码数量,但不幸的是,有很多文件正在为应用程序的单个实体发挥作用,我认为更好地提供更多而不是更少。

首先是错误信息:

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

首先,我的视图编辑器是生成此错误的地方:

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

}

然后是作曲家的服务提供者:

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

}

接下来是界面:

<?php namespace Raid\Repo\Preference;

interface PreferenceInterface {

    public function getActive();

}

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

和抽象装饰者:

<?php namespace Raid\Repo\Preference;

abstract class AbstractPreferenceDecorator implements PreferenceInterface {

    protected $preference;

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

}

然后我们有了存储库:

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

}

然后是雄辩的模特本身:

<?php

class Preference extends Eloquent {

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

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

}

然后绑定接口和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)
            );
        });
    }

}

在上面的代码中,您可以在Composer中看到我要求接口的实例,并且在作曲家的服务提供商中,我解决了IoC的实例。

在repo服务提供程序中,我通过创建repo的实例(传入其依赖项)来绑定接口,然后返回包含缓存装饰器的repo。所有的repo,装饰器,抽象装饰器都实现了接口,所以我不确定它是如何被解析为不是接口的实例?

你能通过调试给予的任何帮助都很棒。

如果您需要更多代码,请大声说。

2 个答案:

答案 0 :(得分:2)

终于找到了这个问题 - 感谢@rizi在#laravel,在我的视图作曲家上,我使用了错误的命名空间:

use Raid\Repo\User\PreferenceInterface;

应该是

use Raid\Repo\Preference\PreferenceInterface;

答案 1 :(得分:2)

你的问题可能在Raid \ Repo \ User \ PreferenceInterface中,它应该是Raid \ Repo \ Preference \ PreferenceInterface。

除此之外,我无法在代码中看到问题,测试我创建了一些名称空间,接口和类,但PreferenceDataComposer实例化对我没有任何问题。

在我的routes.php我创建了一个实例化它的路由,创建基于雄辩的类,一些需要的绑定,手动注册服务提供者并加载命名空间文件:

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

});

我创建了一个包含所有命名空间的Mortelugo.php文件,但我必须创建一些缺少的文件并更改其中一个名称不正确的文件:

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

    }

}