Laravel创建服务提供者时,第一个参数必须实现服务提供者。

4

你好,我正在创建一个自定义缓存服务类,它将抽象出我的存储库中的缓存层。然而,我遇到了一些问题,因为我得到了这个错误:

Argument 1 passed to Task::__construct() must implement interface MyApp\Cache\CacheInterface, none given, called in /var/www/app/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php on line 792 and defined

我的类如下所示:

<?php namespace MyApp\Cache;

use Illuminate\Cache\CacheManager;

class CacheService {

 /**
  * @var Illuminate\Cache\CacheManager
  */
  protected $cache;

  /**
   * @var integer
   */
  protected $minutes;

  /**
   * Construct
   *
   * @param Illuminate\Cache\CacheManager $cache
   * @param string $tag
   * @param integer $minutes
   */
  public function __construct(CacheManager $cache, $minutes = 60)
  {
    $this->cache = $cache;
    $this->tag = $tag;
    $this->minutes = $minutes;
  }

  /**
   * Get
   *
   * @param string $key
   * @return mixed
   */
  public function get($key)
  {
    return $this->cache->tags($this->tag)->get($key);
  }

  /**
   * Put
   *
   * @param string $key
   * @param mixed $value
   * @param integer $minutes
   * @return mixed
   */
  public function put($key, $value, $minutes = null)
  {
    if( is_null($minutes) )
    {
      $minutes = $this->minutes;
    }

    return $this->cache->tags($this->tag)->put($key, $value, $minutes);
  }

  /**
   * Has
   *
   * @param string $key
   * @return bool
   */
  public function has($key)
  {
    return $this->cache->tags($this->tag)->has($key);
  }

}

在我的模型中,我有以下内容;
<?php
use Abstracts\Model as AbstractModel;
use Illuminate\Support\Collection;
use CMS\APIv2\Objects\Entity;
use MyApp/Cache\CacheInterface;

class SprintTask extends AbstractModel
{


    /**
     * @var CacheInterface
     */
    protected $cache;

    public function __construct(CacheInterface $cache)
    {
        $this->cache = $cache;
    }


public static function scopegetAssignedSprint($id) {
    $key = md5('id.'.$id.get_class());

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

    $user = static::where('uid', $id)->lists('sprint_id');

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

    return $user;
}

我有一个缓存服务提供者,如下所示:

<?php
namespace MyApp\Cache;

use MyApp\Cache\CacheInterface;
use Illuminate\Support\ServiceProvider;

class CacheServiceProvider extends ServiceProvider
{

    /**
     * Indicates if loading of the provider is deferred.
     *
     * @var bool
     */
    protected $defer = false;

    /**
     * Register
     */
    public function register()
    {

        $this->app->bind
        ('MyApp\Cache\CacheInterface',
            'MyApp\Cache\CacheService');

    }


}

有没有什么想法可以正确设置这个服务提供商,以便在任何模式/控制器/存储库等中使用?
4个回答

1

你尝试过像这样做吗:

<?php
namespace MyApp\Cache;

use MyApp\Cache\CacheInterface;
use Illuminate\Support\ServiceProvider;
use Illuminate\Cache\CacheManager;

class CacheServiceProvider extends ServiceProvider
{

    /**
     * Indicates if loading of the provider is deferred.
     *
     * @var bool
     */
    protected $defer = false;

    /**
     * Register
     */
    public function register()
    {

        $this->app->bind('MyApp\Cache\CacheInterface',function(){
            return new CacheService(CacheManager $cache);
        });

    }
}

我只是根据Trip的评论进行了更新。

我仍然遇到这个错误 Class 'MyApp\Cache\MyApp\Services\Cache\CacheService' not found,并且不得不在CacheManager和$cache之间添加逗号。有任何想法出了什么问题吗?我现在正在使用这段代码; $this->app->bind('MyApp\Cache\CacheInterface',function(){ return new MyApp\Cache\CacheService(CacheManager, $cache); }); - user0129e021939232
你是否已经通过运行 composer dump 来卸载你的数据,以便它们可以再次生成加载器?还有一件事是你不应该在 CacheManage$cache 之间添加逗号,最后你应该检查你的代码,因为在 CacheService 构造函数中缺少了 $tag 参数。 - Zaher
如果在返回语句类引用中加上了前导反斜杠:“return new \MyApp\Cache\CacheService(CacheManager $cache);”或者简单地写成“return new CacheService(CacheManager $cache);”,因为你已经在\MyApp\Cache命名空间下,这可能会起作用。缺少前导反斜杠导致PHP在错误的位置查找你的类(“MyApp\Cache\MyAppCache...”)。 - Trip
谢谢@Trip,我根据你的注释刚刚更新了代码,你是正确的。谢谢。 - Zaher

1
当服务容器尝试实例化 TaskRepository 时,它发现其中一个构造函数参数是 CacheService 类的对象。因此,它首先尝试实例化此对象,以便稍后将其传递给 TaskRepository 构造函数。
您的 CacheService 定义了两个必需参数。当容器尝试实例化 CacheService 时,它需要为两个属性提供值并将它们传递给构造函数。服务容器通常使用构造函数参数的类型提示来确定应该注入哪个服务。在您的情况下,您需要传递 $tag 变量,但是由于构造函数签名中没有类型提示,因此服务容器不知道应该传递什么给构造函数。
这就是为什么会出现错误的原因 - 它只是说服务容器无法解析 CacheService 类的一个所需依赖关系。
有多种解决方案可解决该问题。
首先,您需要向 $tags 参数添加类型提示。
如果 $tags 是某个服务容器能够实例化的类的对象,请在 CacheService 构造函数签名中添加类型提示。
如果您想要自己处理实例化$tags对象,可以在其中一个服务提供程序中创建对象,并使用容器的bind()方法进行绑定。
如果$tags无法由容器管理和注入,则需要自行实例化CacheService并使用bind()进行绑定。
如果$tags是无法由服务容器管理的内容,例如数组,则需要自行实例化TaskRepository,而不是通过服务容器。
您可以在此处阅读有关Laravel依赖注入的更多信息:http://laravel.com/docs/5.0/container

有 Laravel4 的文档吗? - user0129e021939232

1
简而言之,您不能在Eloquent模型上使用依赖注入。IoC魔法不能在它们上面工作,由于AbstractModel扩展了Eloquent Model类,所以IoC魔法在这里也不起作用。(由Taylor Otwell部分解释 - https://github.com/laravel/framework/issues/3862#issuecomment-37364543
有几种方法可以使这个基本想法起作用:
(1)为模型使用存储库,并将CacheService注入其中。由于Eloquent是类似存储库的ORM,这可能会令人困惑和繁琐。

(2) 通过新的 Facade 注册您的 CacheService,并像 Laravel 内置的 Cache facade 一样直接在模型中使用它,而不需要注入 -- MyCache::has($key)。如果您永远不需要连接到两个不同的缓存,则可以将其设置为单例模式。(L4: http://laravel.com/docs/4.2/facades, L5: http://laravel.com/docs/5.1/facades)

(3) 使用 #1 和 #2 的组合,如此处所述:http://dfg.gd/blog/decoupling-your-code-in-laravel-using-repositiories-and-services


-1
你试图将一个实现了 CacheInterface 接口的类注入到 SprintTask 中,但在你的服务提供者中,你提供的是一个没有实现 CacheInterfaceCacheService 实例。

你需要在 CashService 中实现该接口,以便能够将其传递给 SpringTask

class CacheService implements CacheInterface

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接