端的にいうと処理中のパラメーターを永続化し、永続化を自身のソースコードの一部分にしただけです。これだけで何かを探すプログラムを楽に作れて管理できるので割と便利です。ソースコードと解説が次です。
<?php
/**
* 乱数のシード値。これを動かしてお目当ての乱数になる値を探す。
* この初期値をプログラムが終了、中断される度に書き変える。
* 誤って他の部分も書き変えない様に目印となるコメントで囲む
*/
/* replacement */ $seed = PHP_INT_MIN; /* replacement */
/** @var callable $updateSrcAboutSeedInit 処理終了時に呼び出されるソースコード書き変え関数 */
$updateSrcAboutSeedInit = static function () {
// 自身の内容を取得
$src = file_get_contents(__FILE__);
// 現在のパラメータを取得して、初期値を置き換え
global $seed;
// 正規表現の中自身が置き換え対象にならない様に注意
$src = preg_replace(
'#(/\* replacement \*/ \$seed = )[^;]+(; /\* replacement \*/)#',
'$1'.$seed.'$2',
$src
);
// 初期値を置き換えたソースコードを保存
file_put_contents(__FILE__, $src);
};
// スクリプト処理が完了したとき、あるいは exit() がコールされたときに実行するコールバック関数として
// $shutdownHandler を登録
register_shutdown_function($updateSrcAboutSeedInit);
// 終了シグナルが送られてきた時に事項するコールバックとして exit を実行する関数を登録
// これにより Ctrl+C などでも ↑ の register_shutdown_function が発火します
pcntl_signal(SIGTERM, static fn () =>exit(0));
pcntl_signal(SIGHUP, static fn () =>exit(0));
// ここから下は探索プログラム例です。いい感じのシード値を探します。
$i = 0;
while (true) {// break されるまで無限ループ
mt_srand($seed); // 乱数のシード値をセット。
// str_shuffle で文字列をランダムに並び替え
// substr で文字列を欲しい文字列の長さまで切り詰める。strlen('アーロン') === 12
$res = substr(str_shuffle('アローラロコン'), 0, 12);
if ($res === 'アーロン') {
// 操作した結果の文字列が期待した結果と同じならループ終了
break;
}
++$seed; // ループ続行ならばシード値
++$i;
if ($i % 1_000_000 === 0) {
echo $i."\n";
// 1_000_000ループの度に進んだところまでをソースコードを更新することでセーブします
$updateSrcAboutSeedInit();
}
}
// 目標の結果になったならばループから抜けて結果を echo
echo 'seed: '.$seed."\n";
echo ' res: '.$res."\n";
この例の中では探索プログラムにしていますが、もっと実務的にバッチ処理の中断にも応用ができます。もっともその場合はソースコードよりも jobs や job_processes や job_logs の様なバッチ処理とその進捗を示すデータベース中のテーブルなどより信頼できる外部領域に保存をするべきです。