其他

localhost 配置

不要忘记将 .env 文件中的 app_urlhttp://localhost 中改为真实的 URL,因为它将是你的电子邮件通知和任何其他链接的基础。

APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:9PHz3TL5C4YrdV6Gg/Xkkmx9btaE93j7rQTUZWm2MqU=
APP_DEBUG=true
APP_URL=http://localhost

何时运行或不运行 composer-update

Laravel不是很相关,但是… 永远不要在生产服务器上运行 composer update ,它很慢,会 “破坏” 存储库。始终在你电脑上本地运行 composer update ,将新的 composer.lock 提交到存储库,然后再在生产服务器运行 composer install

Composer 检查新版本

如果你想找出 composer.json 包中已经发布的较新版本,直接运行 composer outdated。你会得到一个包含所有信息的完整列表,如下所示。

phpdocumentor/type-resolver 0.4.0 0.7.1
phpunit/php-code-coverage   6.1.4 7.0.3 Library that provides collection, processing, and rende...
phpunit/phpunit             7.5.9 8.1.3 The PHP Unit Testing framework.
ralouphie/getallheaders     2.0.5 3.0.3 A polyfill for getallheaders.
sebastian/global-state      2.0.0 3.0.0 Snapshotting of global state

自动大写翻译

在翻译文件中 (resources/lang) ,你不仅可以指定变量为 :variable ,也可以指定大写为 :VARIABLE:Variable,然后你传递的值也会自动大写。

// resources/lang/en/messages.php
'welcome' => 'Welcome, :Name'

// Result: "Welcome, Taylor"
echo __('messages.welcome', ['name' => 'taylor']);

仅含小时的 Carbon

如果你想有当前日期不包含秒或者分钟,用 Carbon 的方法比如: setSeconds(0) 或者 setMinutes(0)

// 2020-04-20 08:12:34
echo now();

// 2020-04-20 08:12:00
echo now()->setSeconds(0);

// 2020-04-20 08:00:00
echo now()->setSeconds(0)->setMinutes(0);

// Another way - even shorter
echo now()->startOfHour();

单动作控制器

如果你想创建一个只有一个动作的控制器,你可以使用 __invoke() 方法创建「可调用(invokable)」控制器。 路由:

Route::get('user/{id}', 'ShowProfile');

Artisan 命令:

php artisan make:controller ShowProfile --invokable

控制器

class ShowProfile extends Controller
{
    public function __invoke($id)
    {
        return view('user.profile', [
            'user' => User::findOrFail($id)
        ]);
    }
}

重定向到特定的控制器方法

你不仅可以 redirect()URL 或特定的路由,而且可以跳转到一个特定的控制器里的特定方法,甚至向其传递参数。像这样:

return redirect()->action('SomeController@method', ['param' => $value]);

使用旧版本的 Laravel

如果你想用旧版本而非新版本的 Laravel,使用这个命令:

composer create-project --prefer-dist laravel/laravel project "7.*"

7.* 更改为任何你想要的版本。

为分页链接添加参数

在默认的分页链接中,你可以传递其他参数,保留原始的查询字符串,甚至指向一个特定的 #xxxxx 锚点。

{{ $users->appends(['sort' => 'votes'])->links() }}

{{ $users->withQueryString()->links() }}

{{ $users->fragment('foo')->links() }}

可重复回调函数

如果你又一个需要多次重复调用的回调函数,你可以将其声明在一个变量中,然后反复使用它。

$userCondition = function ($query) {
    $query->where('user_id', auth()->id());
};

// Get articles that have comments from this user
// And return only those comments from this user
$articles = Article::with(['comments' => $userCondition])
    ->whereHas('comments', $userCondition)
    ->get();

$request->hasAny

你不仅可以使用 $request->has() 方法来查看一个参数,而且可以使用 $request->hasAny() 来查看传入的多个参数。

public function store(Request $request) 
{
    if ($request->hasAny(['api_key', 'token'])) {
        echo 'We have API key passed';
    } else {
        echo 'No authorization parameter';
    }
}

简单分页组件

在分页组件中,如果你只需要「上一页 / 下一页」的链接,而不是需要所有页码,也因此可以使用更少的数据库查询,你只需要将 simplePaginate() 更改为 paginate()

// Instead of 
$users = User::paginate(10);

// You can do this
$users = User::simplePaginate(10);

获取数据的方法

如果你有一个具有复杂数据结构的数组,例如带对象嵌套的数组,你可以使用 data_get() 助手函数配合通配符和「点」符号,来从嵌套数组或对象中检索值。

// We have an array
[ 
  0 => 
	['user_id' =>'some user id', 'created_at' => 'some timestamp', 'product' => {object Product}, etc], 
  1 =>  
  	['user_id' =>'some user id', 'created_at' => 'some timestamp', 'product' => {object Product}, etc],  
  2 =>  etc
]

// Now we want to get all products ids. We can do like this:

data_get($yourArray,  '*.product.id');

// Now we have all products ids [1, 2, 3, 4, 5, etc...]

Blade 指令增加真假条件

Laravel 8.51 新增 @class 指令,用于添加控制 CSS 类的真 / 假条件。

可以在 文档 中了解更多

之前:

<div class="@if ($active) underline @endif">`

现在:

<div @class(['underline' => $active])>
@php
    $isActive = false;
    $hasError = true;
@endphp

<span @class([
    'p-4',
    'font-bold' => $isActive,
    'text-gray-500' => ! $isActive,
    'bg-red' => $hasError,
])></span>

<span class="p-4 text-gray-500 bg-red"></span>

@Teacoders 提供

任务允许脱离队列

在文档中,任务是在队列章节进行讨论的,但是你可以脱离队列来使用 job ,就像传统的委托任务的类一样。只需在控制器中调用 $this->dispatchNow() 即可。

public function approve(Article $article)
{
    //
    $this->dispatchNow(new ApproveArticle($article));
    //
}

在工厂类或 seeders 外部使用 Faker

如果你想要生成一些假数据,你可以在模型工厂或 Seeds 中,甚至任何类的外部使用 Faker。

注意:要在生产模式 production 中使用它的话,你需要在 composer.json 中,将 faker 从 "require-dev" 移动到 "require" 中。

use Faker;

class WhateverController extends Controller
{
    public function whatever_method()
    {
        $faker = Faker\Factory::create();
        $address = $faker->streetAddress;
    }
}

可以定时执行的事情

你可以让一些事情以每小时、每天,或是其他时间模式执行。

你可以安排 artisan 命令、作业类、可调用类、回调函数、甚至是 shell 脚本去定时执行。

use App\Jobs\Heartbeat;

$schedule->job(new Heartbeat)->everyFiveMinutes();
$schedule->exec('node /home/forge/script.js')->daily();
use App\Console\Commands\SendEmailsCommand;

$schedule->command('emails:send Taylor --force')->daily();

$schedule->command(SendEmailsCommand::class, ['Taylor', '--force'])->daily();
protected function schedule(Schedule $schedule)
{
    $schedule->call(function () {
        DB::table('recent_users')->delete();
    })->daily();
}

检索 Laravel 文档

如果你想使用一些关键词来检索 Laravel 文档,默认情况下只会给出 5 个结果。或许还能给出更多结果。

如果你想要看全部的结果,你可以前往 Laravel 文档的 Github 仓库 直接搜索。

过滤 route-list

Laravel 8.34 新增: php artisan route:list 获得了新的参数 --except-path,你可以把一些你不想看见的路由过滤掉。

原始PR

自定义 Blade 指令

如果你在不同的 Blade 文件中格式化数据,可以尝试创建自己的 Blade 指令。 下面这一段是来自 Laravel Cashier 包的例子:

"require": {
        "laravel/cashier": "^12.9",
}
public function boot()
{
    Blade::directive('money', function ($expression) {
        return "<?php echo Laravel\Cashier\Cashier::formatAmount($expression, config('cashier.currency')); ?>";
    });
}
<div>Price: @money($book->price)</div>
@if($book->discount_price)
    <div>Discounted price: @money($book->dicount_price)</div>
@endif

Artisan 命令帮助

如果您不确定某些 Artisan 命令的参数,或者您想知道可用的参数,只需键入 php artisan help [command]

当运行测试时禁用懒加载

当运行测试时如果你想排除掉懒加载 你可以禁用掉懒加载

Model::preventLazyLoading(!$this->app->isProduction() && !$this->app->runningUnitTests());

@djgeisi 提供

使用两个很好用的辅助函数会带来魔法效果

在这个例子中 服务将会被调用并重试。如果仍然失败 将会被报告。但是请求不会失败。(rescue)

rescue(function () {
    retry(5, function () {
        $this->service->callSomething();
    }, 200);
});

@JuanDMeGon 提供

请求参数的默认值

以下是我们检测我们使用的 per_page 值是否存在 否则我们用默认值

// Isteand of this
$perPage = request()->per_page ? request()->per_page : 20;

// You can do this
$perPage = request('per_page', 20);

@devThaer 提供

在路由中直接传入中间件而不是注册它

Route::get('posts', PostController::class)
    ->middleware(['auth', CustomMiddleware::class])

@sky_0xs 提供

将数组转化成 css 类

use Illuminate\Support\Arr;

$array = ['p-4', 'font-bold' => $isActive, 'bg-red' => $hasError];

$isActive = false;
$hasError = true;

$classes = Arr::toCssClasses($array);

/*
 * 'p-4 bg-red'
 */

@dietsedev 提供

Laravel-Cashier 中的 upcomingInvoice 方法

您可以显示客户将在下一个计费周期支付的金额。

Laravel Cashier(Stripe) 中有一个 “upcomingInvoice” 方法来获取即将到来的发票详细信息。

Route::get('/profile/invoices', function (Request $request) {
    return view('/profile/invoices', [
        'upcomingInvoice' => $request->user()->upcomingInvoice(),
        'invoices' => $request-user()->invoices(),
    ]);
});

@oliverds_ 提供

$request->exists 与 has

// https://example.com?popular
$request->exists('popular') // true
$request->has('popular') // false 

// https://example.com?popular=foo
$request->exists('popular') // true
$request->has('popular') // true

@coderahuljat 提供

返回带变量视图的多种方法

// First way ->with()
return view('index')
    ->with('projects', $projects)
    ->with('tasks', $tasks)

// Second way - as an array
return view('index', [
        'projects' => $projects,
        'tasks' => $tasks
    ]);

// Third way - the same as second, but with variable
$data = [
    'projects' => $projects,
    'tasks' => $tasks
];
return view('index', $data);

// Fourth way - the shortest - compact()
return view('index', compact('projects', 'tasks'));

调度标准 shell 命令

我们可以使用 scheduled command 调度标准 shell 命令

// app/Console/Kernel.php

class Kernel extends ConsoleKernel
{
    protected function shedule(Schedule $shedule)
    {
        $shedule->exec('node /home/forge/script.js')->daily();
    }
}

由y @anwar_nairi 提供

无需 SSL 验证的 HTTP 请求

有时候你可能会在本地发送一个无需 SSL 验证的 HTTP 请求 可以如下这么干:

return Http::withoutVerifying()->post('https://example.com');

如果想设置一些选项 可以使用 withOptions

return Http::withOptions([
    'verify' => false,
    'allow_redirects' => true
])->post('https://example.com');

@raditzfarhan 提供

不断言任何内容的测试

不断言任何内容的测试,只需启动一些可能引发或不引发异常的内容

class MigrationsTest extends TestCase
{
    public function test_successful_foreign_key_in_migrations()
    {
        // We just test if the migrations succeeds or throws an exception
        $this->expectNotToPerformAssertions();
    }
}

Str 的 mask 方法

Laravel 8.69发布了 Str::mask()方法,该方法使用重复字符屏蔽字符串的一部分.

class PasswordResetLinkController extends Controller
{
    public function sendResetLinkResponse(Request $request)
    {
        $userEmail = User::where('email', $request->email)->value('email'); // username@domain.com
        
        $maskedEmail = Str::mask($userEmail, '*', 4); // user***************
        
        // If needed, you provide a negative number as the third argument to the mask method,
        // which will instruct the method to begin masking at the given distance from the end of the string
        
        $maskedEmail = Str::mask($userEmail, '*', -16, 6); // use******domain.com
    }
}

@Teacoders 提供

扩展 Laravel 类

在许多内置的 Laravel 类上有一个名为 macro 的方法。例如,集合、Str、Arr、请求、缓存、文件等

您可以在这些类上定义自己的方法,如下所示:

Str::macro('lowerSnake', function (string $str) {
    return Str::lower(Str::snake($str));
});
// Will return: "my-string"
Str::lowerSnake('MyString');

@mmartin_joo 提供

Can 特性

Laravel v8.70中, 你可以链式调用 can() 方法替代 middleware('can:..')

// instead of
Route::get('users/{user}/edit', function (User $user) {
    ...
})->middleware('can:edit,user');
// you can do this
Route::get('users/{user}/edit', function (User $user) {
    ...
})->can('edit' 'user');
// PS: you must write UserPolicy to be able to do this in both cases

@sky_0xs 提供

临时下载 url

您可以使用云存储资源的临时下载URL来防止不必要的访问。例如,当一个用户想要下载一个文件时,我们重定向到一个 s3 资源,但是 URL 在 5 秒内过期。

public function download(File $file)
{
    // Initiate file download by redirecting to a temporary s3 URL that expires in 5 seconds
    return redirect()->to(
        Storage::disk('s3')->temporaryUrl($file->name, now()->addSeconds(5))
    );
}

@Philo01 提供

处理深度嵌套数组

处理深度嵌套数组可能会导致缺少键/值异常。幸运的是,Laravel 的data_get()助手使这一点很容易避免。它还支持深度嵌套的对象

深度嵌套的数组可能缺少所需的属性,这是一场噩梦

在下面的示例中,如果缺少 'request','user' 或 'name',则会出现错误。

$value = $payload['request']['user']['name']

相反,使用 data_get() 助手来访问一个使用点符号的深度嵌套的数组项。

$value = data_get($payload, 'request.user.name');

我们还可以通过提供一个默认值来避免任何由缺失属性引起的错误。

$value = data_get($payload, 'request.user.name', 'John');

@mattkingshott 提供

自定义异常的呈现方式

abstract class BaseException extends Exception
{
    public function render(Request $request)
    {
        if ($request->expectsJson()) {
            return response()->json([
                'meta' => [
                    'valid'   => false,
                    'status'  => static::ID,
                    'message' => $this->getMessage(),
                ],
            ], $this->getCode());
        }
        
        return response()->view('errors.' . $this->getCode(), ['exception' => $this], $this->getCode());
    }
}
class LicenseExpiredException extends BaseException
{
    public const ID = 'EXPIRED';
    protected $code = 401;
    protected $message = 'Given license has expired.'
}

@Philo01 提供

tap 助手函数

tap 助手是在对对象调用方法后删除单独的 return 语句的好方法。使事物变得美好和干净。

// without tap
$user->update(['name' => 'John Doe']);
return $user;
// with tap()
return tap($user)->update(['name' => 'John Doe']);

@mattkingshott 提供

重置所有剩余的时间单位

您可以在 DateTime::createFromFormat 方法中插入感叹号以重置所有剩余的时间单位

// 2021-10-12 21:48:07.0
DateTime::createFromFormat('Y-m-d', '2021-10-12');
// 2021-10-12 00:00:00.0
DateTime::createFromFormat('!Y-m-d', '2021-10-12');
2021-10-12 21:00:00.0
DateTime::createFromFormat('!Y-m-d H', '2021-10-12');

@SteveTheBauman 提供

控制台内核中的计划命令问题可以自动通过电子邮件发送其输出

您知道吗,如果出现问题,您在控制台内核中调度的任何命令都可以自动通过电子邮件发送其输出

$schedule
    ->command(PruneOrganizationsCOmmand::class)
    ->hourly()
    ->emailOutputOnFailure(config('mail.support'));

@mattkingshott 提供

使用 GET 参数构造自定义筛选查询时要小心

if (request()->has('since')) {
    // example.org/?since=
    // fails with illegal operator and value combination
    $query->whereDate('created_at', '<=', request('since'));
}
if (request()->input('name')) {
    // example.org/?name=0
    // fails to apply query filter because evaluates to false
    $query->where('name', request('name'));
}
if (request()->filled('key')) {
    // correct way to check if get parameter has value
}

@mc0de 提供

清理你臃肿的路由文件

清掉臃肿的路由文件,并将其拆分以保持组织有序

class RouteServiceProvider extends ServiceProvider
{
    public function boot()
    {
        $this->routes(function () {
            Route::prefix('api/v1')
                ->middleware('api')
                ->namespace($this->namespace)
                ->group(base_path('routes/api.php'));
                
            Route::prefix('webhooks')
                ->namespace($this->namespace)
                ->group(base_path('routes/webhooks.php'));
    
            Route::middleware('web')
                ->namespace($this->namespace)
                ->group(base_path('routes/web.php'));
                
            if ($this->app->environment('local')) {
                Route::middleware('web')
                    ->namespace($this->namespace)
                    ->group(base_path('routes/local.php'));
            }
        });
    }
}

@Philo01 提供

自定义邮件日志存储位置

你可以自定义日志存储位置.

通过设置环境变量如下

MAIL_MAILER=log
MAIL_LOG_CHANNEL=mail

也可以设置日志渠道

'mail' => [
    'driver' => 'single',
    'path' => storage_path('logs/mails.log'),
    'level' => env('LOG_LEVEL', 'debug'),
],

@mmartin_joo 提供

markdown 简单创建

Laravel提供了一个接口来转换HTML中的即时标记,而无需安装新的composer软件包。

$html = Str::markdown('# Changelogfy')

Output:

<h1>Changelogfy</h1>

@paulocastellano 提供

给中间件传参数

您可以通过在值后面附加 “:” 向中间件传递特定路由的参数。例如,我使用一个中间件基于路由实施不同的身份验证方法。

Route::get('...')->middleware('auth.license');
Route::get('...')->middleware('auth.license:bearer');
Route::get('...')->middleware('auth.license:basic');
class VerifyLicense
{
    public function  handle(Request $request, Closure $next, $type = null)
    {
        $licenseKey  = match ($type) {
            'basic'  => $request->getPassword(),
            'bearer' => $request->bearerToken(),
            default  => $request->get('key')
        };
        
        // Verify license and return response based on the authentication type
    }
}

@Philo01 提供

获取并删除session

如果您需要从Laravel会话中获取一些东西,并立即忘记它,考虑使用 Session()->pull(value)。它为您完成了这两个步骤。

// Before
$path = session()->get('before-github-redirect', '/components');
session()->forget('before-github-redirect');
return redirect($path);
// After
return redirect(session()->pull('before-github-redirect', '/components'))

@jasonlbeggs 提供

request 的 date 方法

Laravel v8.77: $request->date() 方法

现在您不需要手动调用 Carbon,您可以执行以下操作:$post->publish_at = $request->date('publish_at')->addHour()->startOfHour()

Link to full pr by @DarkGhostHunter

使用分页时请使用 through 而不是 map

当您想要映射分页数据并只返回字段的子集时,请使用 through 而不是mapmap 会打断分页对象并更改其标识。而,through 作用于分页数据本身

// Don't: Mapping paginated data
$employees = Employee::paginate(10)->map(fn ($employee) => [
    'id' => $employee->id,
    'name' => $employee->name
])
// Do: Mapping paginated data
$employees = Employee::paginate(10)->through(fn ($employee) => [
    'id' => $employee->id,
    'name' => $employee->name
])

@bhaidar 提供

在 HTTP 请求中快速添加一个 Bearer 令牌

withToken' 方法可以将 Authorization' 头附加到一个请求上。

// Booo!
Http::withHreader([
    'Authorization' => 'Bearer dQw4w9WgXcq'
])

// YES!
Http::withToken('dQw4w9WgXcq');

@p3ym4n 提供

从文件夹中复制一个文件或所有文件

你可以使用 "readStream" 和 "writeStream" 将一个文件(或一个文件夹中的所有文件)从一个磁盘复制到另一个磁盘,保持较低的内存使用率。

// List all the files from a folder
$files = Storage::disk('origin')->allFiles('/from-folder-name');

// Using normal get and put (the whole file string at once)
foreach($files as $file) {
    Storage::disk('destination')->put(
        "optional-folder-name" . basename($file),
        Storage::disk('origin')->get($file)
    );
}

// Best: using Streams to keep memory usage low (good for large files)
foreach ($files as $file) {
    Storage::disk('destination')->writeStream(
        "optional-folder-name" . basename($file),
        Storage::disk('origin')->readStream($file)
    );
}

@alanrezende 提供

Sessions has() vs exists() vs missing()

你知道 Laravel 会话中的 hasexistsmissing 方法吗?

// The has method returns true if the item is present & not null.
$request->session()->has('key');

// THe exists method returns true if the item ir present, event if its value is null
$request->session()->exists('key');

// THe missing method returns true if the item is not present or if the item is null
$request->session()->missing('key');

@iamharis010 提供

测试你是否向视图传递了正确的数据

需要测试你传递给视图的数据是否正确?你可以在你的响应上使用 viewData 方法。这里有一些例子:

/** @test */
public function it_has_the_correct_value()
{
    // ...
    $response = $this->get('/some-route');
    $this->assertEquals('John Doe', $response->viewData('name'));
}

/** @test */
public function it_contains_a_given_record()
{
    // ...
    $response = $this->get('/some-route');
    $this->assertTrue($response->viewData('users')->contains($userA));
}

/** @test */
public function it_returns_the_correct_amount_of_records()
{
    // ...
    $response = $this->get('/some-route');
    $this->assertCount(10, $response->viewData('users'));
}

@JuanRangelTX 提供

使用 Redis 来统计页面浏览量

在处理高流量时,用 MySQL 统计像页面浏览量这样的东西可能会对性能造成相当大的影响。Redis 在这方面要好得多。你可以使用 Redis 和一个预定命令来保持与 MySQL 在一个固定的时间间隔内同步。

Route::get('{project:slug', function (Project $project) {
    // Instead of $project->increment('views') we use Redis
    // We group the views by the project id
    Redis::hincrby('project-views', $project->id, 1);
})
// Console/Kernel.php
$schedule->command(UpdateProjectViews::class)->daily();

// Console/Commands/UpdateProjectViews.php
// Get all views from our Redis instance
$views = Redis::hgetall('project-views');

/*
[
    (id) => (views)
    1 => 213,
    2 => 100,
    3 => 341
]
 */

// Loop through all project views
foreach ($views as $projectId => $projectViews) {
    // Increment the project views on our MySQL table
    Project::find($projectId)->increment('views', $projectViews);
}

// Delete all the views from our Redis instance
Redis::del('project-views');

@Philo01 提供

to_route() 辅助函数

Laravel 9 提供了更短的 response()->route() 的版本, 看看下面的代码吧:

// Old way
Route::get('redirectRoute', function() {
    return redirect()->route('home');
});

// Post Laravel 9
Route::get('redirectRoute', function() {
    return to_route('home');
});

这个助手的工作方式与 redirect()->route('home') 相同,但它比老方法更简洁。

@CatS0up 提供

当队列任务关闭时,暂停一项执行时间较长的队列

当执行时间较长的队列,如果你使用以下方法退出队列任务:

  • 直接关闭任务;

  • 发送信号 SIGTERM (SIGINT for Horizon);

  • 按键 CTRL + C (Linux/Windows)。

那么工作进程在做某事时可能会被中止。

通过检查 app('queue.worker')->shouldQuit,我们可以判断 worker 是否正在关闭。这样,我们就可以保存当前的进程并重新发出队列,这样当队列任务者再次运行时,就可以从它退出的地方继续运行。

这在容器化世界(Kubernetes、Docker等)中非常有用,因为容器会随时被销毁和重新创建。

<?php
namespace App\Jobs;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
class MyLongJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    public $timeout = 3600;
    private const CACHE_KEY = 'user.last-process-id';
    public function handle()
    {
        $processedUserId = Cache::get(self::CACHE_KEY, 0); // Get last processed item id
        $maxId = Users::max('id');
        if ($processedUserId >= $maxId) {
            Log::info("All users have already been processed!");
            return;
        }
        while ($user = User::where('id', '>', $processedUserId)->first()) {
            Log::info("Processing User ID: {$user->id}");
            // Your long work here to process user
            // Ex. Calling Billing API, Preparing Invoice for User etc.
            $processedUserId = $user->id;
            Cache::put(self::CACHE_KEY, $processedUserId, now()->addSeconds(3600)); // Updating last processed item id
            if (app('queue.worker')->shouldQuit) {
                $this->job->release(60); // Requeue the job with delay of 60 seconds
                break;
            }
        }
        Log::info("All users have processed successfully!");
    }
}

@a-h-abid 提供

最后更新于