Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Penjadualan tugas dalam Laravel

Penjadualan tugas dalam Laravel

PHPz
PHPzasal
2023-09-01 09:05:061498semak imbas

Penjadualan tugas dalam Laravel

Dalam artikel ini, kami akan memperkenalkan ciri menarik rangka kerja web Laravel - penjadualan tugas. Kami akan melihat bagaimana Laravel membenarkan anda mengurus tugasan yang dijadualkan dalam aplikasi anda. Selain itu, kami akhirnya akan membuat tugas tersuai berjadual kami sendiri untuk tujuan demonstrasi.

Rangka kerja Laravel membolehkan anda menyediakan tugas berjadual supaya anda tidak perlu risau tentang menyediakannya pada peringkat sistem. Anda boleh lari daripada sintaks cron yang kompleks apabila menyediakan tugas yang dijadualkan kerana Laravel membolehkan anda mentakrifkannya dengan cara yang mesra pengguna.

Kami mula-mula akan membincangkan cara menyediakan tugas cron tradisional, dan kemudian kami akan meneroka cara Laravel melaksanakannya. Pada separuh kedua artikel ini, kami akan mencubanya dengan membuat beberapa tugasan berjadual tersuai yang sepatutnya memberikan cerapan praktikal tentang topik tersebut.

Tetapan tugas berjadual tradisional

Dalam pembangunan aplikasi harian, anda selalunya perlu melaksanakan skrip atau arahan tertentu dengan kerap. Jika anda menggunakan sistem *nix, anda mungkin tahu bahawa tugas cron mengendalikan arahan ini. Sebaliknya, ia dipanggil tugas berjadual pada sistem berasaskan Windows.

Mari kita lihat contoh mudah kerja cron berasaskan *nix.

*/5 * * * * /web/statistics.sh

Sangat mudah - ia menjalankan fail statistics.sh setiap lima minit!

Walaupun ini adalah contoh yang sangat mudah, anda selalunya perlu melaksanakan kes penggunaan yang lebih kompleks. Sistem yang kompleks memerlukan anda untuk menentukan berbilang kerja cron yang dijalankan pada selang masa yang berbeza.

Mari kita lihat beberapa tugas yang mesti dilakukan oleh aplikasi web kompleks secara kerap di bahagian belakang.

  • Bersihkan data yang tidak diperlukan dalam bahagian belakang pangkalan data.
  • Kemas kini indeks cache bahagian hadapan untuk kekal terkini.
  • Kira statistik laman web.
  • Hantar e-mel.
  • Sandarkan elemen tapak web yang berbeza.
  • Jana laporan.
  • Ada lagi.

Seperti yang anda lihat, terdapat banyak perkara yang menunggu untuk dijalankan dengan kerap dan pada selang masa yang berbeza. Jika anda seorang pentadbir sistem yang berpengalaman, anda boleh mentakrifkan tugas cron dengan mudah untuk semua tugasan ini, tetapi kadangkala kami sebagai pembangun menginginkan cara yang lebih mudah.

Nasib baik, Laravel dilengkapi dengan API penjadualan tugas terbina dalam yang membolehkan anda menentukan tugas berjadual seperti tidak pernah berlaku sebelum ini. Ya, bahagian seterusnya adalah mengenai asas penjadualan tugas Laravel.

Cara Laravel

Dalam bahagian sebelumnya, kami membincangkan cara tradisional untuk menyediakan kerja cron. Dalam bahagian ini, kami akan memperkenalkan Laravel secara terperinci dalam konteks API penjadualan tugas.

Sebelum kita meneruskan, perkara penting untuk difahami ialah fungsi penjadualan yang disediakan oleh Laravel adalah sama seperti fungsi lain dan tidak dipanggil secara automatik. Jadi jika anda fikir anda tidak perlu melakukan apa-apa di peringkat sistem, saya akan katakan anda kurang bernasib baik.

Malah, jika anda ingin menggunakan sistem penjadualan Laravel, perkara pertama yang perlu anda lakukan ialah menyediakan tugas cron yang berjalan setiap minit dan panggil perintah artisan yang ditunjukkan dalam coretan kod berikut. artisan 命令。

* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1

上面的 artisan 命令调用 Laravel 调度程序,然后执行应用程序中定义的所有待处理的 cron 作业。

当然,我们还没有看到如何在 Laravel 应用程序中定义计划任务,这就是我们接下来要深入讨论的内容。

这是 AppConsoleKernel 类的 schedule 方法,如果您希望定义特定于应用程序的计划任务,则需要使用该方法。

继续获取 app/Console/Kernel.php 文件的内容。

<?php

namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{
    /**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
    protected $commands = [
        //
    ];

    /**
     * Define the application's command schedule.
     *
     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
     * @return void
     */
    protected function schedule(Schedule $schedule)
    {
        // $schedule->command('inspire')->hourly();
    }

    /**
     * Register the commands for the application.
     *
     * @return void
     */
    protected function commands()
    {
        $this->load(__DIR__.'/Commands');

        require base_path('routes/console.php');
    }
}

正如您所看到的,核心代码本身提供了一个有用的示例。在上面的示例中,Laravel 每小时运行 inspire artisan 命令。您不觉得语法一开始就很直观吗?

事实上,Laravel 允许您通过多种不同的方式定义计划任务:

  • 使用闭包/可调用。
  • 调用 artisan 命令。
  • 执行 shell 命令。

此外,还有大量内置的调度频率可供您选择:

  • 每分钟/每五分钟
  • 每小时/每天/每周/每季度/每年
  • 一天中的特定时间
  • 还有更多

事实上,我想说它提供了一套完整的例程,因此您无需接触 shell 即可创建自定义 cron 作业!

是的,我看得出您很想知道如何实现您的自定义计划任务,这也是我在文章开头所承诺的。

在 Laravel 中创建您的第一个计划任务

正如我们所讨论的,Laravel 允许您通过不同的方式定义计划任务。让我们逐一了解其工作原理。

闭包/可调用方法

调度 API 提供了 call

<?php

namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use Illuminate\Support\Facades\DB;

class Kernel extends ConsoleKernel
{
    /**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
    protected $commands = [
        //
    ];

    /**
     * Define the application's command schedule.
     *
     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
     * @return void
     */
    protected function schedule(Schedule $schedule)
    {
        // the call method
        $schedule->call(function () {
          $posts = DB::table('posts')
            ->select('user_id', DB::raw('count(*) as total_posts'))
            ->groupBy('user_id')
            ->get();
     
          foreach($posts as $post)
          {
            DB::table('users_statistics')
              ->where('user_id', $post->user_id)
              ->update(['total_posts' => $post->total_posts]);
          }
        })->everyThirtyMinutes();
    }

    /**
     * Register the commands for the application.
     *
     * @return void
     */
    protected function commands()
    {
        $this->load(__DIR__.'/Commands');

        require base_path('routes/console.php');
    }
}
Arahan artisan di atas memanggil penjadual Laravel dan kemudian melaksanakan semua kerja cron belum selesai yang ditakrifkan dalam aplikasi.

Sudah tentu, kami tidak melihat cara mentakrifkan tugas berjadual dalam aplikasi Laravel, yang akan kami bincangkan secara mendalam seterusnya. 🎜 🎜Ini ialah kaedah jadual kelas AppConsoleKernel, yang anda perlu gunakan jika anda ingin mentakrifkan tugas berjadual khusus aplikasi . 🎜 🎜Teruskan untuk mendapatkan kandungan fail 🎜app/Console/Kernel.php🎜. 🎜
<?php

namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use Illuminate\Support\Facades\DB;

class Kernel extends ConsoleKernel
{
    /**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
    protected $commands = [
        'App\Console\Commands\UserStatistics'
    ];

    /**
     * Define the application's command schedule.
     *
     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
     * @return void
     */
    protected function schedule(Schedule $schedule)
    {
        $schedule->command('statistics:user')->everyThirtyMinutes();
    }

    /**
     * Register the commands for the application.
     *
     * @return void
     */
    protected function commands()
    {
        $this->load(__DIR__.'/Commands');

        require base_path('routes/console.php');
    }
}
🎜Seperti yang anda lihat, kod teras itu sendiri memberikan contoh yang berguna. Dalam contoh di atas, Laravel menjalankan perintah inspire artisan setiap jam. Tidakkah anda fikir sintaks adalah intuitif untuk bermula? 🎜 🎜Malah, Laravel membolehkan anda menentukan tugas berjadual dalam pelbagai cara: 🎜 🎜 🎜Gunakan penutup/boleh panggil. 🎜 🎜Panggil perintah artisan. 🎜 🎜 Laksanakan arahan shell. 🎜 🎜 🎜Selain itu, terdapat banyak frekuensi penjadualan terbina dalam untuk dipilih: 🎜 🎜 🎜Setiap minit/setiap lima minit🎜 🎜Setiap Jam/Harian/Mingguan/Suku Tahun/Tahunan🎜 🎜Masa tertentu dalam sehari🎜 🎜Ada lagi🎜 🎜 🎜Malah, saya katakan ia menyediakan satu set rutin yang lengkap supaya anda boleh membuat kerja cron tersuai tanpa menyentuh cangkerang! 🎜 🎜Ya, saya dapat melihat bahawa anda tertanya-tanya bagaimana untuk melaksanakan tugas berjadual tersuai anda, itulah yang saya janjikan pada permulaan artikel. 🎜 🎜Buat tugas berjadual pertama anda dalam Laravel🎜 🎜Seperti yang kita bincangkan, Laravel membolehkan anda mentakrifkan tugas berjadual dengan cara yang berbeza. Mari lihat bagaimana ia berfungsi satu persatu. 🎜

Kaedah penutupan/boleh dipanggil

🎜API penjadualan menyediakan kaedah panggilan, yang membolehkan anda melaksanakan fungsi boleh panggil atau fungsi penutupan. Mari ubah suai fail 🎜app/Console/Kernel.php🎜 menggunakan kod berikut. 🎜
<?php

namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use Illuminate\Support\Facades\DB;

class Kernel extends ConsoleKernel
{
    /**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
    protected $commands = [
        //
    ];

    /**
     * Define the application's command schedule.
     *
     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
     * @return void
     */
    protected function schedule(Schedule $schedule)
    {
        // the call method
        $schedule->call(function () {
          $posts = DB::table('posts')
            ->select('user_id', DB::raw('count(*) as total_posts'))
            ->groupBy('user_id')
            ->get();
     
          foreach($posts as $post)
          {
            DB::table('users_statistics')
              ->where('user_id', $post->user_id)
              ->update(['total_posts' => $post->total_posts]);
          }
        })->everyThirtyMinutes();
    }

    /**
     * Register the commands for the application.
     *
     * @return void
     */
    protected function commands()
    {
        $this->load(__DIR__.'/Commands');

        require base_path('routes/console.php');
    }
}

如您所见,我们将闭包函数作为 call 方法的第一个参数传递。另外,我们将频率设置为每 30 分钟一次,因此它将每 30 分钟执行一次关闭函数!

在我们的示例中,我们计算每个用户的帖子总数并相应地更新 statistics 表。

artisan 命令

除了闭包或可调用之外,您还可以安排一个 artisan 命令,该命令将按一定的时间间隔执行。事实上,它应该是优于闭包的首选方法,因为它同时提供了更好的代码组织和可重用性。

继续使用以下内容修改 app/Console/Kernel.php 文件的内容。

<?php

namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use Illuminate\Support\Facades\DB;

class Kernel extends ConsoleKernel
{
    /**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
    protected $commands = [
        'App\Console\Commands\UserStatistics'
    ];

    /**
     * Define the application's command schedule.
     *
     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
     * @return void
     */
    protected function schedule(Schedule $schedule)
    {
        $schedule->command('statistics:user')->everyThirtyMinutes();
    }

    /**
     * Register the commands for the application.
     *
     * @return void
     */
    protected function commands()
    {
        $this->load(__DIR__.'/Commands');

        require base_path('routes/console.php');
    }
}

这是 command 方法,如果您希望安排 artisan 命令,如上面的代码片段所示,您可以使用该方法。您需要传递 artisan 命令签名作为 command 方法的第一个参数。

当然,你还需要在app/Console/Commands/UserStatistics.php处定义相应的artisan命令。

<?php
namespace App\Console\Commands;
 
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
 
class UserStatistics extends Command
{
  /**
   * The name and signature of the console command.
   *
   * @var string
   */
  protected $signature = 'statistics:user';
 
  /**
   * The console command description.
   *
   * @var string
   */
  protected $description = 'Update user statistics';
 
  /**
   * Create a new command instance.
   *
   * @return void
   */
  public function __construct()
  {
    parent::__construct();
  }
 
  /**
   * Execute the console command.
   *
   * @return mixed
   */
  public function handle()
  {
    // calculate new statistics
    $posts = DB::table('posts')
      ->select('user_id', DB::raw('count(*) as total_posts'))
      ->groupBy('user_id')
      ->get();
     
    // update statistics table
    foreach($posts as $post)
    {
      DB::table('users_statistics')
      ->where('user_id', $post->user_id)
      ->update(['total_posts' => $post->total_posts]);
    }
  }
}

exec 命令

我们可以说到目前为止我们讨论的方法是特定于 Laravel 应用程序本身的。此外,Laravel 还允许您安排 shell 命令,以便您也可以运行外部应用程序。

让我们通过一个简单的示例来演示如何每天备份数据库。

<?php
namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
 
class Kernel extends ConsoleKernel
{
  /**
   * Define the application's command schedule.
   *
   * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
   * @return void
   */
  protected function schedule(Schedule $schedule)
  {
    // exec method
    $host = config('database.connections.mysql.host');
    $username = config('database.connections.mysql.username');
    $password = config('database.connections.mysql.password');
    $database = config('database.connections.mysql.database');
     
    $schedule->exec("mysqldump -h {$host} -u {$username} -p{$password} {$database}")
      ->daily()
      ->sendOutputTo('/backups/daily_backup.sql');
  }
}

从代码中可以明显看出,您需要使用调度程序的 exec 方法,并且需要将要运行的命令作为其第一个参数传递。

除此之外,我们还使用了 sendOutputTo 方法,它允许您收集命令的输出。另一方面,有一个方法,emailOutputTo,它允许您通过电子邮件发送输出内容!

如何防止任务重叠

在本节中,我们将了解如何防止任务重叠。假设您已经定义了一个任务,并且您想要确保如果它已经在运行,Laravel 不应该运行同一任务的另一个实例。默认情况下,Laravel 将始终开始运行计划任务,即使同一任务的前一个实例已经在运行但尚未完成。

那么让我们看看如何避免重叠计划任务。

$schedule->command('statistics:user')->everyThirtyMinutes()->withoutOverlapping();

正如你所看到的,你只需要使用 withoutOverlapping 方法来确保 Laravel 不会与已经运行的任务重叠。默认情况下,Laravel 重叠任务之前的锁定时间为 24 小时。如果您想覆盖它,可以按照以下代码片段所示进行操作。

$schedule->command('statistics:user')->everyThirtyMinutes()->withoutOverlapping(30);

在上面的示例中,Laravel 等待 30 分钟才清除重叠锁。

如何定义后台任务

如果您同时安排多个任务,Laravel 会按顺序运行它们。因此,如果您有一个需要很长时间才能执行的任务,则下一个计划任务将不得不等待很长时间。为了避免这种情况,您可以在后台执行此类任务。

让我们快速看一下下面的示例,了解如何定义后台任务。

$schedule->command('statistics:user')->daily()->runInBackground();

如您所见,您可以使用 runInBackground 方法来定义后台任务。

结论

今天,我们了解了 Laravel Web 框架中的任务调度 API。看到它如何轻松地管理需要定期运行的任务真是令人着迷。

在文章的开头,我们讨论了传统的设置计划任务的方式,接下来我们介绍了 Laravel 的设置方式。在本文的后半部分,我们通过几个实际示例来演示任务调度概念。

我希望您喜欢这篇文章,并且您应该对在 Laravel 中设置计划任务更有信心。对于那些刚刚开始使用 Laravel 或希望通过扩展来扩展您的知识、网站或应用程序的人,我们在 Envato Market 上提供了多种您可以学习的内容。

Atas ialah kandungan terperinci Penjadualan tugas dalam Laravel. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel sebelumnya:PHP FTPArtikel seterusnya:PHP FTP