EC-CUBEのバッチをcronで動かしていて、ログにこう出ているのに、コマンドが本来出すはずの出力が1行も残っていない。この場合、処理は最後まで走り終わっています。途中で落ちたわけではありません。
Return value of "Eccube\Command\XxxCommand::execute()" must be of the type int, "null" returned.
原因はexecute()が戻り値を返していないことです。4.0系(Symfony 3.4〜4.x)で書かれたコマンドを4.3系に持っていくと、この形で全滅します。
出力が消えていたら戻り値を疑う
Symfonyのコマンドはexecute()を抜けた直後に戻り値の型を検査します。ここで例外になると、それまでにwriteln()したものはバッファごと破棄されます。
中身が同じコマンドを2つ用意して確かめました。最終行に$output->writeln('処理は最後まで走った')を置いた状態で、return 0;があるほうは期待どおりその1行を出力して終了コード0。returnを書かないほうは出力が1行も出ないままTypeErrorです。処理が到達しなかったのではなく、到達した後に例外で捨てられています。
リトライする前にDBを見る
この挙動で実務上いちばん危ないのは、失敗に見えるので再実行してしまうことです。ログにはTypeErrorしか残らず、コマンド自身の進捗表示は消えているため、外からは「途中で死んだ」ようにしか見えません。
しかし処理は完走しているので、DB更新・メール送信・外部API呼び出しといった副作用はすでに起きています。再実行する前に、対象データが更新済みでないか確認してください。
返すのは int だけ。「0のようなもの」は通らない
判定は!is_int($statusCode)です。4パターン試した結果です。
| 返した値 | 結果 |
|---|---|
return 0; |
終了コード0で正常 |
return "0"; |
TypeError(string) |
return true; |
TypeError(bool) |
| 返さない | TypeError(null) |
正常終了はreturn 0;、異常終了はreturn 1;です。Command::SUCCESS/Command::FAILUREという定数もありますが(中身は0と1)、EC-CUBE本体のコマンドはreturn 0;で書かれているので、既存コードに合わせるならこちらでかまいません。
途中の return; は末尾の修正では直らない
見落としやすいのがメソッド途中のreturn;です。「対象が見つからないので抜ける」といったガード節がこれになっていると、その条件を踏んだ時だけ落ちます。末尾にreturn 0;を足しても直りません。
これはIDEの正規表現検索で洗い出せます。PhpStormなら「Find in Files」で正規表現をオンにして、次のパターンをCommandディレクトリに対してかけてください。
^\s*return\s*;
ただしヒットした全部を直してはいけません。このパターンはexecute()以外のメソッドも拾います。実際に手元のプロジェクトでかけたところ5件ヒットしましたが、内訳はinteract()が3件、独自メソッドが2件で、修正が必要なものは1件もありませんでした。
interact()は戻り値がvoidなのでreturn;で正しく、独自メソッドも同様です。型検査がかかるのはexecute()だけなので、ヒットした行がどのメソッドの中かを確認してから直してください。
戻り値が1つも無いコマンドを探す
もう一方の「returnを1行も書いていないコマンド」は、検索では見つけにくいパターンです。無いものは検索できないためで、こちらはexecute()の定義箇所を一覧して目視するのが早いです。
protected function execute\(
ヒットした各execute()の末尾を見て、returnで終わっていなければ対象です。バージョンアップ作業でこれをやったところ13件見つかりました。
そのうち1件は「対象商品が見つからないので中断する」箇所があり、そこはreturn 1;(異常終了)にしています。単に処理する対象が無かっただけならreturn 0;、続行できない事情があるならreturn 1;と使い分けてください。
バッチは画面と違って、壊れていても誰も気づきません。バージョンアップの動作確認では画面の巡回に目が行きがちですが、上の2つの検索を先にかけておけば、cronが一巡するのを待たずに洗い出せます。
EC-CUBEに関するお問い合わせ
[重要]現在公式にセキュリティサポートが切れていないPHPは8.1以上、MySQLは8.0以上で、対応しているEC-CUBEバージョンは4.2以上です。古いEC-CUBEを使っている方は適切なタイミングでバージョンアップをご検討ください。