我今天早上只是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中的依赖注入有几个问题。
是否更好地输入接口并让Laravel从IoC容器中解析它(就像我在这里完成的那样) OR 最好是输入一个具体的类(所以在我的情况下注入Illuminate\Filesystem\Filesystem
)?
接口的绑定在哪里 - >实施定义?此外,它们可以在不更改核心代码的情况下进行修改吗?
干杯
修改
控制器中的一些测试代码。输出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
}
}