【问题标题】:Why Laravel keeps calling schedule() with every Artisan Command?为什么 Laravel 总是在每个 Artisan 命令中调用 schedule()?
【发布时间】:2017-12-06 06:00:56
【问题描述】:

我有一张名为dc_user_meta 的表,我创建了一个工匠命令并将其安排在kernel.php 中。克隆存储库后,当我尝试运行 PHP artisan migrate 时,我收到此错误。

  [Illuminate\Database\QueryException]                                                                                                              
  SQLSTATE[42S02]: Base table or view not found: 1146 Table 'database.dc_user_meta' doesn't exist (SQL: select * from `dc_user_met  
  a` where `meta_key` = usage_in_days)

不仅php artisan migrate,而且我根本无法运行任何工匠命令!我不知道为什么 PHP 每次尝试执行任何工匠命令时都会调用 schedule 方法。

在这种情况下,我可以做些什么来解决这个错误,就像这样在schedule 方法中覆盖我的逻辑。

if(Schema::hasTable('dc_user_meta')){
    // Code here
}

但从长远来看,我认为这并不好。解决此错误的正确方法是什么?


更新: 我只是尝试像这样覆盖kernel.php中的命令调用,但仍然没有成功!

if(Schema::hasTable('dc_user_meta')){
    $schedule->command('usage:update')->daily();
}

更新: 我得到了解决方案。但我不认为这是问题的答案。它解决了我的问题,但我认为这不是标准解决方案。我只是像这样被Command login覆盖。

if(Schema::hasTable('dc_user_meta')){
    // Command Logic
}

关于为什么 Laravel 使用每个 artisan 命令调用 schedule() 的任何具体答案,以及如果发生这种情况如何以标准方式解决错误!

【问题讨论】:

  • 我无法重现它(L5.4)我做了一个命令调用一个不存在的表,但调用它时只得到一个错误。
  • @cbaconnier 在数据库中创建表,然后尝试运行“php artisan migrate:refresh”
  • 你使用的是哪个版本的 Laravel?
  • 我使用的是 laravel5.4

标签: php laravel laravel-5 cron


【解决方案1】:

你的错误是表dc_user_meta,而你的逻辑是表user_meta,你需要做Schema::hasTable('dc_user_meta')

【讨论】:

    【解决方案2】:

    我确信数据库中不存在表 dc_user_meta。

    【讨论】:

    • 如果您的代码没有任何错误,它应该可以工作。在您的代码中某处存在导致迁移失败的错误。执行:php artisan migrate -vvv 以查看完整堆栈并在此处发布
    • 正在尝试。会告诉你会发生什么!
    【解决方案3】:

    据我了解,您的表是“user_meta”而不是“dc_user_meta”,但您已经编写了使用表“dc_user_meta”的代码,因此出现错误提示“dc_user_meta”表未找到。

    【讨论】:

    • 它是dc_user_metadc_ 是前缀。只是为了给你看表的名字,我写了user_meta。实际表名是dc_user_meta,我为dc_user_meta编写了代码。
    【解决方案4】:

    从技术上讲,调度方法是通过 Illuminate\Foundation\Console\Kernel 的构造函数调用的(这是 app\Console\Kernel.php 的父类)

    因此,每次实例化控制台内核时,都会执行 schedule() 方法。

    让我们看看在哪种情况下执行了什么($schedule->call() 可以替换为 $schedule->command() 或 $schedule->exec()):

    protected function schedule(Schedule $schedule)
    {
        // everything that is inside the schedule function is executed everytime the console kernel is booted.
    
        // gets exectuted every time
        \App\User::where('foo', 1)->get();
    
    
        $schedule->call(function() {
            // gets executed for every call to php artisan schedule:run
            \App\User::where('foo', 1)->get();
        });
    
        $schedule->call(function() {
            // gets executed for every call to php artisan schedule:run
            // IF the closure in the when() function is true;
    
            \App\User::where('foo', 1)->get();
        })->when(function() {
             // if true is returned the scheduled command or closure is executed otherwise it is skipped
             \Schema::hasColumn('user', 'foo');
        });
    
    }
    

    但是为什么每个命令都要执行 schedule 命令呢?

    嗯,显然 php artisan schedule:run 本身就是一个控制台命令。所以它肯定需要有关预定命令的信息。

    其他命令也可能需要有关计划命令的信息...例如,如果您想编写一个工匠命令 list:scheduledTasks。此命令将要求所有计划的命令都已添加到控制台计划列表中。

    也许还有其他几个(内部)参数为什么调度函数必须每次都运行。 (我没有对源代码挖掘太深...)
    不过...有关预定命令的信息可能对各种用例都有用。

    【讨论】:

    • 那么,编写与数据库一起使用的命令逻辑的最佳方法是什么,我们可以运行php artisan migratephp artisan migrate:refresh
    • 我会将最后一个示例与 when() 方法一起使用。因此,仅在满足要求(在您的情况下存在特定表)时才执行该命令。如果您将代码封装在 $schedule->command() 或 $schedule->call() 中,则 php artisan migrate 和 php artisan migrate:refresh 完全不受影响
    • 所以,这是摆脱这个错误的标准方法。在执行确切的命令逻辑之前检查表是否存在。对吗?
    • 这是避免错误的唯一可能方法....但是如果您不使用示例中的 when() 函数。然后命令根本没有被调度(所以没有其他命令或进程有关于调度命令的信息)。如果您根本不需要,您的示例将起作用。
    • 那么酷!这就是我想知道的!
    【解决方案5】:

    如果还有人关心这个……

    <?php
    # This is your app/Console/Kernel.php
    use ...;
    
    class Kernel extends ConsoleKernel {
    
        # Other stuff...
    
        protected function schedule(Schedule $schedule) {
            if( in_array('schedule:run', $_SERVER['argv']) ){
                # Your scheduler commands here...
            }
        }
    
    }
    

    【讨论】:

      猜你喜欢
      • 2020-09-18
      • 1970-01-01
      • 2016-02-07
      • 1970-01-01
      • 2017-07-07
      • 2016-05-14
      • 2019-04-02
      • 2015-02-21
      • 2022-12-15
      相关资源
      最近更新 更多