OSS Gate Workshop: php-kagawa: 2024-05-12: akinoriakatsuka: laravel/framework: Work log
akinoriakatsuka opened this issue · 31 comments
This is a work log of a "OSS Gate workshop".
"OSS Gate workshop" is an activity to increase OSS developers.
Here's been discussed in Japanese. Thanks.
作業ログ作成時の説明
以下のテンプレートを埋めてタイトルに設定します。埋め方例はスクロールすると見えてきます。
OSS Gate Workshop: ${LOCATION}: ${YEAR}-${MONTH}-${DAY}: ${ACCOUNT_NAME}: ${OSS_NAME}: Work log
タイトル例↓:
OSS Gate Workshop: Tokyo: 2017-01-16: kou: Rabbit: Work log
OSS Gateワークショップ関連情報
- スライド:ワークショップの進行に使っているスライドがあります。
- チャット:OSS開発に関することならなんでも相談できます。ワークショップが終わった後もオンラインで相談しながら継続的にOSSの開発に参加しましょう!
- シナリオ:ワークショップの目的・内容・進め方の詳細が書いています。
- 過去のビギナーの作業ログ:他の人の作業ログから学べることがいろいろあるはずです。
laravel/framework#50670
これに取り組む
再現を試みる
composer create-project laravel/laravel example-app
インストールはOK
php artisan serve
ローカルホストでアクセスできるようになった
routes/console.php
デフォルトでconsole.phpに記載があった。ので、listを表示してみた。
$ php artisan schedule:list
0 * * * * php artisan inspire ............................................................................................................................ Next Due: 31 minutes from now
これってどこに書くのかな?調べてみる。
$schedule->command('emails:send')
->hourly()
->between('7:00', '22:00');
Scheduleファサードでconsole.phpに書いたらよさそう
Schedule::command('inspire')
->hourly()
->between('7:00', '22:00');
再現した
$ php artisan schedule:list
0 * * * * php artisan inspire Next Due: 19 minutes from now
0 * * * * php artisan inspire Next Due: 19 minutes from now
Schedule::command('inspire')
->hourly()
->between('7:00', '22:00');
Schedule::command('inspire2')
->hourly()
->cron('0 7-22 * * *');
cronの形式で渡してやればちゃんと出る
0 * * * * php artisan inspire ......................................................................................................................... Next Due: 58 minutes from now
0 7-22 * * * php artisan inspire2 ........................................................................................................................... Next Due: 3 hours from now
次は、どこで実装されているかみる
laravel/frameworkをクローンしてきた
とりあえず、実装見る前にテスト流してみる
Time: 01:24.133, Memory: 316.00 MB
OK, but some tests were skipped!
Tests: 10019, Assertions: 27333, Skipped: 530.
artisanってどこ?
php artisanで実行できるってことは、example-appの直下のartisanがそれ?
example-app/artisan
// Bootstrap Laravel and handle the command...
$status = (require_once __DIR__.'/bootstrap/app.php')
->handleCommand(new ArgvInput);
それっぽい
handleCommandを見る
require_once __DIR__.'/bootstrap/app.php'
の戻り値のインスタンスのhandleCommand。
app.phpの戻り値はApplicationクラスのインスタンス
use Illuminate\Foundation\Application;
これのhandleCommand
example-app/vendor/laravel/framework/src/Illuminate/Foundation/Application.php
/**
* Handle the incoming Artisan command.
*
* @param \Symfony\Component\Console\Input\InputInterface $input
* @return int
*/
public function handleCommand(InputInterface $input)
{
$kernel = $this->make(ConsoleKernelContract::class);
$status = $kernel->handle(
$input,
new ConsoleOutput
);
$kernel->terminate($input, $status);
return $status;
}
kernelのhandleなので、handleを見てみる
kernelは$this->makeでできる
$kernel = $this->make(ConsoleKernelContract::class);
var_dump($kernel);
メンターさんのアドバイスでこちらで該当箇所を探してみた。
grep -lr schedule:list ./
.//src/Illuminate/Console/Scheduling/ScheduleListCommand.php
このファイルであることがわかった
framework/src/Illuminate/Console/Scheduling/ScheduleListCommand.php
var_dumpで、$eventsを見てみる
object(Illuminate\Support\Collection)#556 (2) {
["items":protected]=>
array(1) {
[0]=>
object(Illuminate\Console\Scheduling\Event)#460 (22) {
["command"]=>
string(55) "'/usr/local/Cellar/php/8.3.6/bin/php' 'artisan' inspire"
["expression"]=>
string(9) "0 * * * *"
["repeatSeconds"]=>
NULL
expressionが怪しい?
src/Illuminate/Console/Scheduling/Event.php
に見にいく
40行目にpublic $expressionがある!
$expression に代入しているところ見つからない…
おつかれさまでした!
ワークショップの終了にともないissueを閉じますが、このまま作業メモとして使っても構いません 👌
ワークショップの感想を集めています!
ブログなどに書かれた際は、このページへリンクの追加をお願いします 🙏
またの参加をお待ちしています!
$eventsを吐かせてみて、中の情報がどうなっているか調べる
["expression"]=>
string(9) "0 * * * *"
["startTime"]=>
object(Illuminate\Support\Carbon)#462 (20) {
["date"]=>
string(26) "2024-05-12 07:00:00.000000"
["endTime"]=>
object(Illuminate\Support\Carbon)#466 (20) {
["date"]=>
string(26) "2024-05-12 22:00:00.000000"
上記から、終了時間と開始時間は取れてるっぽいが、expressionの計算がうまく行ってないっぽい
issueで問題になっているbetweenメソッドについてはtestケースがない!
Eventのexpressionがどうやって計算されているかを確認する
$expressionを代入する部分ない。traitかな?
traitビンゴ!
src/Illuminate/Console/Scheduling/ManagesFrequencies.php
以下の実装見る限り
$event->cron($expression)
の形で外から与えられるっぽい。
/**
* The Cron expression representing the event's frequency.
*
* @param string $expression
* @return $this
*/
public function cron($expression)
{
$this->expression = $expression;
return $this;
}
ので、次は ->cron( を探す。
twiceDailyはうまくcron出せてるので、この実装をまねしてみよう
tests/Console/Scheduling/FrequencyTest.php
こちらにもbetweenのテストはない
メソッド追っかけ
/**
* Schedule the event to run twice daily.
*
* @param int $first
* @param int $second
* @return $this
*/
public function twiceDaily($first = 1, $second = 13)
{
return $this->twiceDailyAt($first, $second, 0);
}
/**
* Schedule the event to run twice daily at a given offset.
*
* @param int $first
* @param int $second
* @param int $offset
* @return $this
*/
public function twiceDailyAt($first = 1, $second = 13, $offset = 0)
{
$hours = $first.','.$second;
return $this->hourBasedSchedule($offset, $hours);
}
/**
* Schedule the event to run at the given minutes and hours.
*
* @param array|string|int $minutes
* @param array|string|int $hours
* @return $this
*/
protected function hourBasedSchedule($minutes, $hours)
{
$minutes = is_array($minutes) ? implode(',', $minutes) : $minutes;
$hours = is_array($hours) ? implode(',', $hours) : $hours;
return $this->spliceIntoPosition(1, $minutes)
->spliceIntoPosition(2, $hours);
}
ここまできてやっとcronあった。
* Splice the given value into the given position of the expression.
*
* @param int $position
* @param string $value
* @return $this
*/
protected function spliceIntoPosition($position, $value)
{
$segments = preg_split("/\s+/", $this->expression);
$segments[$position - 1] = $value;
return $this->cron(implode(' ', $segments));
}
明日はbetween掘ってみてcronに辿り着くかやってみる