mirror of
https://gitee.com/hyperf/hyperf.git
synced 2024-11-29 18:27:44 +08:00
Added ScanFileDriver
to watch file changes (#2042)
Co-authored-by: hanicc <hanicc.qq.com> Co-authored-by: 李铭昕 <715557344@qq.com>
This commit is contained in:
parent
05d4cab611
commit
66ce4ae3e6
@ -2,7 +2,11 @@
|
||||
|
||||
## Fixed
|
||||
|
||||
[#2037](https://github.com/hyperf/hyperf/pull/2037) Fixed bug that tcp server running in only one coroutine.
|
||||
- [#2037](https://github.com/hyperf/hyperf/pull/2037) Fixed bug that tcp server running in only one coroutine.
|
||||
|
||||
## Added
|
||||
|
||||
- [#2042](https://github.com/hyperf/hyperf/pull/2042) Added `ScanFileDriver` to watch file changes for `hyperf/watcher`.
|
||||
|
||||
# v2.0.1 - 2020-07-02
|
||||
|
||||
|
@ -123,7 +123,7 @@
|
||||
|
||||
- [donjan-deng/hyperf-permission](https://github.com/donjan-deng/hyperf-permission) 基于 [spatie/laravel-permission](https://github.com/spatie/laravel-permission) 开发的适配 Hyperf 的权限组件
|
||||
- [fx/hyperf-http-auth](https://github.com/nfangxu/hyperf-http-auth) 根据 laravel 中的 auth 组件改写的, 适配 hyperf 框架
|
||||
- [96qbhy/hyperf-auth](https://github.com/qbhy/hyperf-auth) 参考 laravel 的 auth 组件设计,支持 jwt 和 session驱动,更轻巧更好用
|
||||
- [96qbhy/hyperf-auth](https://github.com/qbhy/hyperf-auth) 参考 laravel 的 auth 组件设计,支持 jwt 和 session 驱动,更轻巧更好用
|
||||
|
||||
## 第三方 SDK
|
||||
|
||||
|
@ -9,16 +9,16 @@
|
||||
|
||||
## Fixed
|
||||
|
||||
- [#1952](https://github.com/hyperf/hyperf/pull/1952) 修复数据库迁移类存在时,也会生成同类名类,导致类名冲突的BUG。
|
||||
- [#1960](https://github.com/hyperf/hyperf/pull/1960) 修复 `Hyperf\HttpServer\ResponseEmitter::isMethodsExists()` 判断错误的BUG。
|
||||
- [#1961](https://github.com/hyperf/hyperf/pull/1961) 修复因文件 `config/autoload/aspects.php` 不存在导致服务无法启动的BUG。
|
||||
- [#1964](https://github.com/hyperf/hyperf/pull/1964) 修复接口请求时,数据体为空会导致 `500` 错误的BUG。
|
||||
- [#1965](https://github.com/hyperf/hyperf/pull/1965) 修复 `initRequestAndResponse` 失败后,会导致请求状态码与实际不符的BUG。
|
||||
- [#1968](https://github.com/hyperf/hyperf/pull/1968) 修复当修改 `aspects.php` 文件后,`Aspect` 无法安装修改后的结果运行的BUG。
|
||||
- [#1985](https://github.com/hyperf/hyperf/pull/1985) 修复注解全局配置不全为小写时,会导致 `global_imports` 失败的BUG。
|
||||
- [#1990](https://github.com/hyperf/hyperf/pull/1990) 修复当父类存在与子类一样的成员变量时, `@Inject` 无法正常使用的BUG。
|
||||
- [#2019](https://github.com/hyperf/hyperf/pull/2019) 修复脚本 `gen:model` 因为使用了 `morphTo` 或 `where` 导致生成对应的 `@property` 失败的BUG。
|
||||
- [#2026](https://github.com/hyperf/hyperf/pull/2026) 修复当使用了魔术方法时,LazyLoad 代理生成有误的BUG。
|
||||
- [#1952](https://github.com/hyperf/hyperf/pull/1952) 修复数据库迁移类存在时,也会生成同类名类,导致类名冲突的 BUG。
|
||||
- [#1960](https://github.com/hyperf/hyperf/pull/1960) 修复 `Hyperf\HttpServer\ResponseEmitter::isMethodsExists()` 判断错误的 BUG。
|
||||
- [#1961](https://github.com/hyperf/hyperf/pull/1961) 修复因文件 `config/autoload/aspects.php` 不存在导致服务无法启动的 BUG。
|
||||
- [#1964](https://github.com/hyperf/hyperf/pull/1964) 修复接口请求时,数据体为空会导致 `500` 错误的 BUG。
|
||||
- [#1965](https://github.com/hyperf/hyperf/pull/1965) 修复 `initRequestAndResponse` 失败后,会导致请求状态码与实际不符的 BUG。
|
||||
- [#1968](https://github.com/hyperf/hyperf/pull/1968) 修复当修改 `aspects.php` 文件后,`Aspect` 无法安装修改后的结果运行的 BUG。
|
||||
- [#1985](https://github.com/hyperf/hyperf/pull/1985) 修复注解全局配置不全为小写时,会导致 `global_imports` 失败的 BUG。
|
||||
- [#1990](https://github.com/hyperf/hyperf/pull/1990) 修复当父类存在与子类一样的成员变量时, `@Inject` 无法正常使用的 BUG。
|
||||
- [#2019](https://github.com/hyperf/hyperf/pull/2019) 修复脚本 `gen:model` 因为使用了 `morphTo` 或 `where` 导致生成对应的 `@property` 失败的 BUG。
|
||||
- [#2026](https://github.com/hyperf/hyperf/pull/2026) 修复当使用了魔术方法时,LazyLoad 代理生成有误的 BUG。
|
||||
|
||||
## Changed
|
||||
|
||||
@ -165,12 +165,12 @@ return [
|
||||
|
||||
## 修复
|
||||
|
||||
- [#1696](https://github.com/hyperf/hyperf/pull/1696) 修复方法 `Context::copy` 传入字段 `keys` 后无法正常使用的BUG。
|
||||
- [#1708](https://github.com/hyperf/hyperf/pull/1708) [#1718](https://github.com/hyperf/hyperf/pull/1718) 修复 `hyperf/socketio-server` 组件内存溢出等BUG。
|
||||
- [#1696](https://github.com/hyperf/hyperf/pull/1696) 修复方法 `Context::copy` 传入字段 `keys` 后无法正常使用的 BUG。
|
||||
- [#1708](https://github.com/hyperf/hyperf/pull/1708) [#1718](https://github.com/hyperf/hyperf/pull/1718) 修复 `hyperf/socketio-server` 组件内存溢出等 BUG。
|
||||
|
||||
## 优化
|
||||
|
||||
- [#1710](https://github.com/hyperf/hyperf/pull/1710) MAC系统下不再使用 `cli_set_process_title` 方法设置进程名。
|
||||
- [#1710](https://github.com/hyperf/hyperf/pull/1710) MAC 系统下不再使用 `cli_set_process_title` 方法设置进程名。
|
||||
|
||||
# v1.1.30 - 2020-05-07
|
||||
|
||||
@ -199,11 +199,11 @@ return [
|
||||
|
||||
## 修复
|
||||
|
||||
- [#1639](https://github.com/hyperf/hyperf/pull/1639) 修复 `rpc-client` 会从 `consul` 中获取到不健康节点的BUG。
|
||||
- [#1641](https://github.com/hyperf/hyperf/pull/1641) 修复 `rpc-client` 获取到的结果为 `null` 时,会抛出 `RequestException` 的BUG。
|
||||
- [#1641](https://github.com/hyperf/hyperf/pull/1641) 修复 `rpc-server` 中 `jsonrpc-tcp-length-check` 协议,无法在 `consul` 中添加心跳检查的BUG。
|
||||
- [#1650](https://github.com/hyperf/hyperf/pull/1650) 修复脚本 `describe:routes` 列表展示有误的BUG。
|
||||
- [#1655](https://github.com/hyperf/hyperf/pull/1655) 修复 `MysqlProcessor::processColumns` 无法在 `MySQL Server 8.0` 版本中正常工作的BUG。
|
||||
- [#1639](https://github.com/hyperf/hyperf/pull/1639) 修复 `rpc-client` 会从 `consul` 中获取到不健康节点的 BUG。
|
||||
- [#1641](https://github.com/hyperf/hyperf/pull/1641) 修复 `rpc-client` 获取到的结果为 `null` 时,会抛出 `RequestException` 的 BUG。
|
||||
- [#1641](https://github.com/hyperf/hyperf/pull/1641) 修复 `rpc-server` 中 `jsonrpc-tcp-length-check` 协议,无法在 `consul` 中添加心跳检查的 BUG。
|
||||
- [#1650](https://github.com/hyperf/hyperf/pull/1650) 修复脚本 `describe:routes` 列表展示有误的 BUG。
|
||||
- [#1655](https://github.com/hyperf/hyperf/pull/1655) 修复 `MysqlProcessor::processColumns` 无法在 `MySQL Server 8.0` 版本中正常工作的 BUG。
|
||||
|
||||
## 优化
|
||||
|
||||
|
@ -132,7 +132,7 @@ class FooTask
|
||||
|
||||
#### 更改调度分发策略
|
||||
|
||||
通过在 `config/autoload/dependencies.php` 更改 `Hyperf\Crontab\Strategy\StrategyInterface` 接口类所对应的实例来更改目前所使用的策略,默认情况下使用 `Worker进程执行策略`,对应的类为 `Hyperf\Crontab\Strategy\WorkerStrategy`,如我们希望更改策略为一个新的策略,比如为 `App\Crontab\Strategy\FooStrategy`,那么如下:
|
||||
通过在 `config/autoload/dependencies.php` 更改 `Hyperf\Crontab\Strategy\StrategyInterface` 接口类所对应的实例来更改目前所使用的策略,默认情况下使用 `Worker 进程执行策略`,对应的类为 `Hyperf\Crontab\Strategy\WorkerStrategy`,如我们希望更改策略为一个新的策略,比如为 `App\Crontab\Strategy\FooStrategy`,那么如下:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
@ -473,7 +473,7 @@ $images = Image::query()->with([
|
||||
])->get();
|
||||
```
|
||||
|
||||
对应的SQL查询如下:
|
||||
对应的 SQL 查询如下:
|
||||
|
||||
```sql
|
||||
// 查询所有图片
|
||||
|
@ -1,4 +1,4 @@
|
||||
Socket.io是一款非常流行的应用层实时通讯协议和框架,可以轻松实现应答、分组、广播。hyperf/socketio-server支持了Socket.io的WebSocket传输协议。
|
||||
Socket.io 是一款非常流行的应用层实时通讯协议和框架,可以轻松实现应答、分组、广播。hyperf/socketio-server 支持了 Socket.io 的 WebSocket 传输协议。
|
||||
|
||||
## 安装
|
||||
|
||||
@ -149,9 +149,9 @@ function onSomeEvent(\Hyperf\SocketIOServer\Socket $socket){
|
||||
$socket->compress(false)->emit('uncompressed', "that's rough");
|
||||
}
|
||||
```
|
||||
### 全局API
|
||||
### 全局 API
|
||||
|
||||
直接从容器中获取SocketIO单例。这个单例可向全局广播或指定房间、个人通讯。未指定命名空间时,默认使用'/'空间。
|
||||
直接从容器中获取 SocketIO 单例。这个单例可向全局广播或指定房间、个人通讯。未指定命名空间时,默认使用 '/' 空间。
|
||||
|
||||
```php
|
||||
<?php
|
||||
@ -182,9 +182,9 @@ $io->local->emit('hi', 'my lovely babies');
|
||||
$io->emit('an event sent to all connected clients');
|
||||
```
|
||||
|
||||
### 命名空间API
|
||||
### 命名空间 API
|
||||
|
||||
和全局API一样,只不过已经限制了命名空间。
|
||||
和全局 API 一样,只不过已经限制了命名空间。
|
||||
```php
|
||||
// 以下伪码等价
|
||||
$foo->emit();
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Watcher
|
||||
# 热更新 Watcher
|
||||
|
||||
自从 `2.0` 版本使用了 `BetterReflection` 来收集扫描目录内的 `语法树` 和 `反射数据`,导致扫描速度相较 `1.1` 慢了不少。
|
||||
|
||||
@ -14,27 +14,39 @@ composer require hyperf/watcher --dev
|
||||
|
||||
## 配置
|
||||
|
||||
### 发布配置
|
||||
|
||||
```bash
|
||||
php bin/hyperf.php vendor:publish hyperf/watcher
|
||||
```
|
||||
|
||||
| 配置 | 默认值 | 备注 |
|
||||
| :--------: | :-------------: | :-------------------------------------------------------: |
|
||||
| driver | `FswatchDriver` | fswatch驱动 |
|
||||
| bin | `php` | 用于启动服务的脚本 例如 `php -d swoole.use_shortname=Off` |
|
||||
| watch.dir | 'app', 'config' | 监听目录 |
|
||||
| watch.file | '.env' | 监听文件 |
|
||||
### 配置说明
|
||||
|
||||
## 安装驱动
|
||||
| 配置 | 默认值 | 备注 |
|
||||
| :------------: | :--------------: | :-------------------------------------------------------: |
|
||||
| driver | `ScanFileDriver` | 默认定时扫描文件驱动 |
|
||||
| bin | `php` | 用于启动服务的脚本 例如 `php -d swoole.use_shortname=Off` |
|
||||
| watch.dir | `app`, `config` | 监听目录 |
|
||||
| watch.file | `.env` | 监听文件 |
|
||||
| watch.interval | `2000` | 扫描间隔(毫秒) |
|
||||
|
||||
暂时只支持 `fswatch` 驱动。
|
||||
## 支持驱动
|
||||
|
||||
| 驱动 | 备注 |
|
||||
| :----------------------------------: | :--------------: |
|
||||
| Hyperf\Watcher\Driver\ScanFileDriver | 无需扩展 |
|
||||
| Hyperf\Watcher\Driver\FswatchDriver | 需要安装 fswatch |
|
||||
|
||||
### `fswatch` 安装
|
||||
|
||||
Mac
|
||||
|
||||
```bash
|
||||
brew install fswatch
|
||||
```
|
||||
|
||||
其他
|
||||
|
||||
```bash
|
||||
wget https://github.com/emcrisostomo/fswatch/releases/download/1.14.0/fswatch-1.14.0.tar.gz \
|
||||
&& tar -xf fswatch-1.14.0.tar.gz \
|
||||
@ -55,3 +67,4 @@ php bin/hyperf.php server:watch
|
||||
## 不足
|
||||
|
||||
- 暂时 Alpine Docker 环境下,稍微有点问题,后续会完善。
|
||||
- 删除文件需要手动重启才能生效。
|
||||
|
@ -9,13 +9,14 @@ declare(strict_types=1);
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
use Hyperf\Watcher\Driver\FswatchDriver;
|
||||
use Hyperf\Watcher\Driver\ScanFileDriver;
|
||||
|
||||
return [
|
||||
'driver' => FswatchDriver::class,
|
||||
'driver' => ScanFileDriver::class,
|
||||
'bin' => 'php',
|
||||
'watch' => [
|
||||
'dir' => ['app', 'config'],
|
||||
'file' => ['.env'],
|
||||
'scan_interval' => 2000,
|
||||
],
|
||||
];
|
||||
|
114
src/watcher/src/Driver/ScanFileDriver.php
Normal file
114
src/watcher/src/Driver/ScanFileDriver.php
Normal file
@ -0,0 +1,114 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://doc.hyperf.io
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
namespace Hyperf\Watcher\Driver;
|
||||
|
||||
use Hyperf\Contract\StdoutLoggerInterface;
|
||||
use Hyperf\Di\Annotation\Inject;
|
||||
use Hyperf\Utils\Filesystem\Filesystem;
|
||||
use Hyperf\Utils\Str;
|
||||
use Hyperf\Watcher\Option;
|
||||
use Swoole\Coroutine\Channel;
|
||||
use Swoole\Timer;
|
||||
use Symfony\Component\Finder\SplFileInfo;
|
||||
|
||||
class ScanFileDriver implements DriverInterface
|
||||
{
|
||||
/**
|
||||
* @var Option
|
||||
*/
|
||||
protected $option;
|
||||
|
||||
/**
|
||||
* @var Filesystem
|
||||
*/
|
||||
protected $filesystem;
|
||||
|
||||
/**
|
||||
* @Inject
|
||||
* @var StdoutLoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
public function __construct(Option $option)
|
||||
{
|
||||
$this->option = $option;
|
||||
$this->filesystem = new Filesystem();
|
||||
}
|
||||
|
||||
public function watch(Channel $channel): void
|
||||
{
|
||||
$ms = $this->option->getScanInterval() > 0 ? $this->option->getScanInterval() : 2000;
|
||||
Timer::tick($ms, function () use ($channel) {
|
||||
global $lastMD5;
|
||||
$files = [];
|
||||
$currentMD5 = $this->getWatchMD5($files);
|
||||
if ($lastMD5 && $lastMD5 !== $currentMD5) {
|
||||
$changeFilesMD5 = array_diff(array_values($lastMD5), array_values($currentMD5));
|
||||
$addFiles = array_diff(array_keys($currentMD5), array_keys($lastMD5));
|
||||
foreach ($addFiles as $file) {
|
||||
$channel->push($file);
|
||||
}
|
||||
$deleteFiles = array_diff(array_keys($lastMD5), array_keys($currentMD5));
|
||||
$deleteCount = count($deleteFiles);
|
||||
|
||||
$watchingLog = sprintf('%s Watching: Total:%d, Change:%d, Add:%d, Delete:%d.', __CLASS__, count($currentMD5), count($changeFilesMD5), count($addFiles), $deleteCount);
|
||||
$this->logger->debug($watchingLog);
|
||||
|
||||
if ($deleteCount == 0) {
|
||||
$changeFilesIdx = array_keys($changeFilesMD5);
|
||||
foreach ($changeFilesIdx as $idx) {
|
||||
isset($files[$idx]) && $channel->push($files[$idx]);
|
||||
}
|
||||
} else {
|
||||
$this->logger->warning('Delete files must be restarted manually to take effect.');
|
||||
}
|
||||
$lastMD5 = $currentMD5;
|
||||
} else {
|
||||
$lastMD5 = $currentMD5;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected function getWatchMD5(&$files): array
|
||||
{
|
||||
$filesMD5 = [];
|
||||
$filesObj = [];
|
||||
$dir = $this->option->getWatchDir();
|
||||
$ext = $this->option->getExt();
|
||||
// Scan all watch dirs.
|
||||
foreach ($dir as $d) {
|
||||
$filesObj = array_merge($filesObj, $this->filesystem->allFiles(BASE_PATH . '/' . $d));
|
||||
}
|
||||
/** @var SplFileInfo $obj */
|
||||
foreach ($filesObj as $obj) {
|
||||
$pathName = $obj->getPathName();
|
||||
if (Str::endsWith($pathName, $ext)) {
|
||||
$files[] = $pathName;
|
||||
$contents = file_get_contents($pathName);
|
||||
$filesMD5[$pathName] = md5($contents);
|
||||
}
|
||||
}
|
||||
// Scan all watch files.
|
||||
$file = $this->option->getWatchFile();
|
||||
$filesObj = $this->filesystem->files(BASE_PATH, true);
|
||||
/** @var SplFileInfo $obj */
|
||||
foreach ($filesObj as $obj) {
|
||||
$pathName = $obj->getPathName();
|
||||
if (Str::endsWith($pathName, $file)) {
|
||||
$files[] = $pathName;
|
||||
$contents = file_get_contents($pathName);
|
||||
$filesMD5[$pathName] = md5($contents);
|
||||
}
|
||||
}
|
||||
return $filesMD5;
|
||||
}
|
||||
}
|
@ -12,14 +12,14 @@ declare(strict_types=1);
|
||||
namespace Hyperf\Watcher;
|
||||
|
||||
use Hyperf\Contract\ConfigInterface;
|
||||
use Hyperf\Watcher\Driver\FswatchDriver;
|
||||
use Hyperf\Watcher\Driver\ScanFileDriver;
|
||||
|
||||
class Option
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $driver = FswatchDriver::class;
|
||||
protected $driver = ScanFileDriver::class;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
@ -41,6 +41,11 @@ class Option
|
||||
*/
|
||||
protected $ext = ['.php', '.env'];
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $scanInterval = 2000;
|
||||
|
||||
public function __construct(ConfigInterface $config, array $dir, array $file)
|
||||
{
|
||||
$options = $config->get('watcher', []);
|
||||
@ -49,6 +54,7 @@ class Option
|
||||
isset($options['bin']) && $this->bin = $options['bin'];
|
||||
isset($options['watch']['dir']) && $this->watchDir = (array) $options['watch']['dir'];
|
||||
isset($options['watch']['file']) && $this->watchFile = (array) $options['watch']['file'];
|
||||
isset($options['watch']['scan_interval']) && $this->scanInterval = (int) $options['watch']['scan_interval'];
|
||||
isset($options['ext']) && $this->ext = (array) $options['ext'];
|
||||
|
||||
$this->watchDir = array_unique(array_merge($this->watchDir, $dir));
|
||||
@ -79,4 +85,9 @@ class Option
|
||||
{
|
||||
return $this->ext;
|
||||
}
|
||||
|
||||
public function getScanInterval()
|
||||
{
|
||||
return $this->scanInterval;
|
||||
}
|
||||
}
|
||||
|
@ -82,6 +82,7 @@ class Process
|
||||
|
||||
require $this->file;
|
||||
|
||||
// Collect the annotations.
|
||||
$ref = $this->reflection->classReflector()->reflect($this->class);
|
||||
BetterReflectionManager::reflectClass($this->class, $ref);
|
||||
$this->collect($this->class, $ref);
|
||||
@ -97,7 +98,7 @@ class Process
|
||||
$this->putCache($this->path, serialize($data));
|
||||
}
|
||||
|
||||
// 重做代理类
|
||||
// Reload the proxy class.
|
||||
$manager = new ProxyManager([], [$this->class => $this->file], BASE_PATH . '/runtime/container/proxy/');
|
||||
$ref = new \ReflectionClass($manager);
|
||||
$method = $ref->getMethod('generateProxyFiles');
|
||||
|
@ -21,7 +21,6 @@ use Hyperf\Utils\Filesystem\Filesystem;
|
||||
use Hyperf\Watcher\Ast\Metadata;
|
||||
use Hyperf\Watcher\Ast\RewriteClassNameVisitor;
|
||||
use Hyperf\Watcher\Driver\DriverInterface;
|
||||
use Hyperf\Watcher\Driver\FswatchDriver;
|
||||
use PhpParser\NodeTraverser;
|
||||
use PhpParser\PrettyPrinter\Standard;
|
||||
use Psr\Container\ContainerInterface;
|
||||
@ -138,11 +137,9 @@ class Watcher
|
||||
if ($file === false) {
|
||||
if (count($result) > 0) {
|
||||
$result = [];
|
||||
// 重启服务
|
||||
$this->restart(false);
|
||||
}
|
||||
} else {
|
||||
// 重写缓存
|
||||
$meta = $this->getMetadata($file);
|
||||
if ($meta) {
|
||||
$ret = System::exec($this->option->getBin() . ' vendor/bin/collector-reload.php ' . $meta->path . ' ' . str_replace('\\', '\\\\', $meta->toClassName()));
|
||||
@ -212,7 +209,7 @@ class Watcher
|
||||
if ($ret['code']) {
|
||||
throw new \RuntimeException($ret['output']);
|
||||
}
|
||||
$this->output->writeln('Stop server success');
|
||||
$this->output->writeln('Stop server success.');
|
||||
$this->channel->push($ret);
|
||||
});
|
||||
}
|
||||
@ -237,7 +234,6 @@ class Watcher
|
||||
if (! class_exists($driver)) {
|
||||
throw new \InvalidArgumentException('Driver not support.');
|
||||
}
|
||||
|
||||
return make(FswatchDriver::class, ['option' => $this->option]);
|
||||
return make($driver, ['option' => $this->option]);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user