Laravel依赖注入 - 绑定

时间:2015-03-27 11:58:27

标签: php laravel dependency-injection inversion-of-control

我今天早上只是composer update我的项目,这反过来又更新了我的Laravel项目中的一些依赖项。自从这次更新以来,我注意到有一件事特别停止了工作。

在我的一个命令处理程序中,我注入一个Filesystem依赖项并以下列方式使用它:

use Illuminate\Contracts\Filesystem\Filesystem; // NOTE: This is an interface
...
class MyCommandHandler {
    protected $filesystem;

    public function __construct(Filesystem $filesystem)
    {
        $this->filesystem = $filesystem;
    }

    public function handle()
    {
        if ($this->filesystem->exists('/directory/that/does/not/exist'))
        {
            // Do something
        }
    }
}

我注意到当在注入的exists对象上调用$filesystem方法并且目录不存在时,条件就会传递,就像目录确实存在一样,我最终得到了在我的代码中进一步的问题。

我使用get_class()输出$filesystem对象的类,最终成为Illuminate\Filesystem\FilesystemAdapter。进一步调查我发现我的文件系统操作最终由League\Flysystem包处理,之前它们由Illuminate\Filesystem\Filesystem处理。

我不完全确定为什么对Flysystem的更改破坏了我的代码,但我对Laravel中的依赖注入有几个问题。

  1. 是否更好地输入接口并让Laravel从IoC容器中解析它(就像我在这里完成的那样) OR 最好是输入一个具体的类(所以在我的情况下注入Illuminate\Filesystem\Filesystem)?

  2. 接口的绑定在哪里 - >实施定义?此外,它们可以在不更改核心代码的情况下进行修改吗?

  3. 干杯

    修改

    控制器中的一些测试代码。输出yes|no

    use Illuminate\Contracts\Filesystem\Filesystem;
    ...
    
    public function index(Filesystem $fs)
    {
        $testPath = '/path/that/does/not/exist';
        echo $fs->exists($testPath) ? 'yes' : 'no';
        echo '|' . (file_exists($testPath) ? 'yes' : 'no');
    

    编辑2 - 部分回答

    我已经做了很多挖掘,并找出了我为什么遇到Flysystem包实施问题:

    Flysystem包使用磁盘(在 config / filesystems.php 中定义),默认为本地磁盘。事实证明,此软件包使用此处为每个磁盘定义的配置,在我的情况下是本地磁盘。默认情况下,本地磁盘根植于应用程序的存储路径,然后将所有路径视为相对于该路径。

    因此,当我执行$fs->exists('/does/not/exist')时,实际上将路径视为/var/www/myproject/storage/app/does/not/exist

    可以根据需要定义任意数量的磁盘,并使用Illuminate\Contracts\Filesystem\Factory包执行相对于该路径的操作,如下所示:

    配置/ filesystems.php

    'disks' => [
    
        'local' => [
            'driver' => 'local',
            'root'   => storage_path().'/app',
        ],
    
        'public' => [
            'driver' => 'local',
            'root'   => public_path()
        ],
    

    任何控制器/命令/其他任何东西

    use Illuminate\Contracts\Filesystem\Factory as Filesystem;
    ...
    class ClassName {
        protected $filesystem;
    
        public function __construct(Filesystem $fs)
        {
            $this->filesystem = $fs->disk('public'); // Refers to public disk in config/filesystems.php
        }
    
        public function method()
        {
            $this->filesystem->exists('path'); // /var/www/myproject/public/path
        }
    }
    

0 个答案:

没有答案