如何在 Laravel 5.5 中将数据从调度程序发送到 artisan 命令

How to send data from the scheduler to the artisan command in Laravel 5.5

好的,所以我基本上需要使用 Laravel 的调度程序和自定义 artisan 命令生成一个 json 文件(所说的列表实际上是我们应用程序中热门城市的列表)。所以我继续这样做了。这是我的 Artisan 命令的定义:

namespace App\Console\Commands;

use Illuminate\Console\Command;
use App\Services\PlaceService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Log;

class CitySearch extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'city:search {--locale=}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Generates the list of the most popular cities to be used across the application when we need it.';

    private $placesService;

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct(PlaceService $placesService)
    {
        $this->placesService = $placesService;
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        App::setLocale( $this->option('locale') );


        $request = Request::create(route('api.search-places'), 'GET', ['maxResults' => 3000, 'isArtisan' => true]);

        $request->headers->set('Accept', 'application/json');
        $request->headers->set('Api-Key', 'aaaaaaaaaaaa');
        // $request->headers->set('Api-Key', '43JSOSH333KSOH555WHO99');
        $request->headers->set('App-client', 'web');

        $response = app()->handle($request);
        $content = json_decode($response->getContent());

        $results = array_map(function($element){

            if($element->type == "City")
                $context = ['an', 'se', 'me'];
            else
                $context = ['se'];



            return ['displayName' => $element->displayName, 'context' => $context];
        }, $content->data);

        print(json_encode($results));



    }
}

然后我进入调度程序并添加以下内容以使命令 运行 每周一次:

namespace App\Console;

use App\Console\Commands\Admin\RedFalcon\PendingTransactionNotificator;
use App\Console\Commands\Admin\RedFalcon\FraudTransactionNotificator;
use App\Console\Commands\CardGenerate;
use App\Console\Commands\Communauto\Stats;
use App\Console\Commands\CPS\Archiver;
use App\Console\Commands\CPS\AutoCasher;
use App\Console\Commands\CPS\Autofixer;
use App\Console\Commands\CPS\Beta\Testers;
use App\Console\Commands\CPS\BNC\EmailFailedBankTransaction;
use App\Console\Commands\CPS\BNC\FeedComposer;
use App\Console\Commands\CPS\BNC\Feeder;
use App\Console\Commands\CPS\BNC\FeedMediator;
use App\Console\Commands\CPS\BNC\FeedReporter;
use App\Console\Commands\CPS\BNC\Parametrizer;
use App\Console\Commands\CPS\Captor;
use App\Console\Commands\CPS\ConfirmationFix;
use App\Console\Commands\CPS\ConfirmationCodeRemoval;
use App\Console\Commands\CPS\DB\RideArchiver;
use App\Console\Commands\CPS\DB\RideFixer;
use App\Console\Commands\CPS\Rider;
use App\Console\Commands\CPS\Test\Resetter;
use App\Console\Commands\CPS\Transactor;
use App\Console\Commands\CPS\Troubleshooting\Experiment1;
use App\Console\Commands\Notifications\ApnFeedbackService;
use App\Console\Commands\RelavelTester;
use App\Console\Commands\UpdateCityPopularity;
use App\Console\Commands\Util\FixBankTransactionTable;
use App\Console\Commands\Util\FixPreauthorizationTable;
use App\Console\Commands\Util\ResetPassword;
use App\Console\Commands\CitySearch;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use Illuminate\Support\Facades\Log;

class Kernel extends ConsoleKernel
{

    protected $list;
    /**
     * The Artisan commands provided by your application.
     *
     * @var array
     */
    protected $commands = [
        CardGenerate::class,
        Rider::class,
        Autofixer::class,
        Captor::class,
        Transactor::class,
        Archiver::class,
        FeedComposer::class,
        FeedMediator::class,
        Feeder::class,
        Parametrizer::class,
        RideFixer::class,
        RideArchiver::class,
        RelavelTester::class,
        FixPreauthorizationTable::class,
        PendingTransactionNotificator::class,
        FraudTransactionNotificator::class,
        FixBankTransactionTable::class,
        Resetter::class,
        Testers::class,
        Stats::class,
        Experiment1::class,
        FeedReporter::class,
        ResetPassword::class,
        AutoCasher::class,
        ConfirmationFix::class,
        ConfirmationCodeRemoval::class,
        CitySearch::class,
        UpdateCityPopularity::class,
        EmailFailedBankTransaction::class,
        ApnFeedbackService::class
    ];

    /**
     * Define the application's command schedule.
     *
     * @param  \Illuminate\Console\Scheduling\Schedule  $schedule
     * @return void
     */
    protected function schedule(Schedule $schedule)
    {
        $schedule->command('city:search --locale=fr')
            ->mondays()
            ->at('14:40')
            ->sendOutputTo(storage_path() . "/app/city-fr.json");

        $schedule->command('city:search --locale=en')
            ->mondays()
            ->at('14:40')
            ->sendOutputTo(storage_path() . "/app/city-en.json");
    }

    /**
     * Register the Closure based commands for the application.
     *
     * @return void
     */
    protected function commands()
    {
        require base_path('routes/console.php');
    }
}

现在,这个工作得很好......除了有时会崩溃。发生这种情况时,两个 json 文件将充满错误消息而不是实际数据。我想做的基本上是在命令执行之前保存原始列表,以防万一失败,我想将该列表输出到文件中并记录错误。现在,一切都进入了文件,当然,我的应用程序中出现了一大堆错误,因为城市列表无效。

因为我在 Laravel 5.5 我尝试使用 "before" 和 "after" 钩子(onFailure 和 onSuccess 在我的框架版本中不可用)并想出了这个:

$schedule->command('city:search --locale=fr')
->everyMinute()
->before( function(){ 
    $this->list = json_decode(file_get_contents(storage_path() . "/app/city-fr.json"));
})
->after(function(){
    $test = json_decode(file_get_contents(storage_path() . "/app/city-fr.json"));
    Log::debug($test);
})
->sendOutputTo(storage_path() . "/app/city-fr.json");

所以,虽然我可以在进程开始之前从文件中成功获取原始列表,但在 "after" 挂钩中,文件仍然是空的,所以我无法知道进程是否失败或不是。

有人知道我应该怎么做吗?感觉解决方案就在我面前,但我只是想念它。

好的,这对我来说是一个整容时刻。结果在 'after' 挂钩中,我确实可以访问该文件,但我的输出为空的原因是 json_decode 方法返回 false,因为文件内容无效 json(这是我从一开始就试图测试的)。不管怎样,一旦我把我散乱的大脑碎片捡起来,下面的结果就完美地工作了:

$schedule->command('city:search --locale=fr')
            ->everyMinute()
            ->before( function(){ 
                $this->list = file_get_contents(storage_path() . "/app/city-fr.json");
            })
            ->after(function(){
                if(!json_decode(file_get_contents(storage_path() . "/app/city-fr.json")))
                {
                    $fp = fopen(storage_path() . "/app/city-fr.json", 'w');
                    fwrite($fp, $this->list);
                    fclose($fp);
                }
            })
            ->sendOutputTo(storage_path() . "/app/city-fr.json");