0%

其实官方文档有说,只是没看仔细。

正常情况下,修改 php 代码是不用重启什么东西的,

但是 Laravel 中的 job 不一样,

如果不用 php artisan queue:restart,新 dispatchjob 跑的还会是原来的代码。

也就是说,如果发现 jobbug,改了之后可能不会生效,除非有重启过队列。

如果使用 supervisor,可以使用 supervisor restart xxx 来进行重启。

个人觉得原因是,运行 php artisan queue:workphp artisan queue:listen 之后,

内存中的代码是运行时候的代码,是常驻内存的,

job 的保存是序列化保存的,在 队列运行到对应的 job 的时候,反序列化出来的还是旧驻留内存的 job

所以,队列有些奇怪的 bug 发生的时候,或者修改过代码之后,需要重启一下队列。

输出进度条

有时候我们想在命令行执行一些耗时的命令,我们可以利用 symfony 提供的进度条相关的类,来输出一个进度条,显示当前的处理进度。

参考:Symfony ProgressBar

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php

namespace App\Commands;

use Illuminate\Console\Command;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Output\ConsoleOutput;

class Test extends Command
{
protected $signature = 'test';

/**
* Execute the command.
*
* @return void
*/
public function handle()
{
//
$output = new ConsoleOutput();
$progressBar = new ProgressBar($output, 1000);
$progressBar->setFormat(" %elapsed:6s%/%estimated:-6s% 内存消耗: %memory:6s%\n%current%/%max% [%bar%] %percent:3s%%");

foreach (range(1, 1000) as $_) {
usleep(5000);
$progressBar->advance();
}

$progressBar->finish();
echo "\n";
}
}

效果:

x

输出多个进度条:

1
2
3
$progressBar->start();
print "\n";
$progressBar->start();

中间需要打印一个换行符

输出动态变化的变量

有时候我们想在命令执行过程中显示一个动态变化的数,同时又想输出的格式保持不变,我们可以使用 setMessage 方法

1
2
$progressBar->setFormat("已处理数量: %count%");  // 这里是一个占位符,可以和进度条写在一起
$progressBar->setMessage($count, 'count'); // 使用 `$count` 替换输出内容中的 "%$count%"

具体效果类似:

1
已处理数量: 1 (这里的 1 会变更,而不是另起一行输出)

有可能是配置缓存导致的,

运行:

1
php artisan config:clear

可清除配置缓存,配置缓存保存在 bootstrap/cache/config.php,可以直接去那文件夹看看是不是缓存导致的。

还有另外一个缓存文件 bootstrap/cache/services.json,上面的命令只是清除配置,下面的命令可以同时清除这两个缓存文件。

1
php artisan clear-compiled
1
2
3
php artisan config:clear
php artisan clear-compiled // 还不行再运行下面的
php artisan optimize

使用 MacroableBuilder 添加自定义方法

Laravel 中提供了 Macroabletrait,之前一直没有想过可以用上这个东西。

最近才想到可以这么做,源码看这里:https://github.com/laravel/framework/blob/5.6/src/Illuminate/Support/Traits/Macroable.php

目前用的是 5.1 版本,应该 5.1 版本以后的都有这个特性。

当然,你也可以在 Model 基类里面添加自定义方法,但是这样添加的方法 DB 类是用不了的。

但是使用 macro 定义到 Builder 的方法可以同时在 DB 类和 Eloquent Model 中使用(具体不赘述,自己看源码,就是利用 __call__callStatic 这些魔术方法)。

定义

使用方法:调用 Macroablemacro 方法,绑定一个自定义方法到 Builder 类中,如:

1
2
3
4
\Illuminate\Database\Query\Builder\Builder::macro('active', function () {
return $this->where('status', 1);
});

使用

调用方法是(使用 DB 类):

1
DB::table(xxx)->active()->get();

或者(使用 Eloquent Model):

1
\App\Model\User::active()->first();

放在哪里?

至于我们应该把上面那几行放哪里?

个人觉得一个比较好的地方是 Providers 中,在 app/Providers 下面新建一个 Provider,把 macro 调用放到 Providerregister 方法中。如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

namespace App\Providers;

use Illuminate\Database\Query\Builder;
use Illuminate\Support\ServiceProvider;

/** @mixin \Illuminate\Database\Eloquent\Builder */
class DatabaseServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
Builder::macro('active', function () {
return $this->where('status', 1);
});
}
}

当然,加了 Providers 之后还要在 config/app.php 中配置这个 Provider

就这样。

还有个问题是,这样添加的方法 ide 无法识别,我们这时候就可以使用 @method 了,如:

1
@method $this active()

可以使用命令把这些 @method 写入到 Builder 头部。