如何在 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");
好的,所以我基本上需要使用 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");