APCU_CASの定義は次のとおりです。
bool apcu_cas(string $key, int|float $old, int|float $new)
この関数の関数は次のとおりです。キー$キーの現在の値が$ oldに等しい場合、その値は$ newに設定され、 trueを返します。それ以外の場合、それはfalseを返します。
数値型( intまたはfloat )の値にのみ使用できるか、操作が失敗することは注目に値します。
apcu_store('counter', '5');
$result = apcu_cas('counter', 5, 10);
質問の説明:
「5」は数字のように見えますが、 APCU_CAS内では、タイプチェックは厳密です。文字列「5」は整数5に等しくないため、 CAS操作は失敗します。
解決:
保存するときは、必ず数値タイプを使用してください。
apcu_store('counter', 5);
または比較前にキャストします:
$value = apcu_fetch('counter');
if (is_numeric($value)) {
apcu_store('counter', (int)$value);
}
apcu_store('rate', 1.0);
apcu_cas('rate', 1, 2.0);
質問の説明:
1と1.0は数学的に等しくなりますが、 APCU_CASは比較時にタイプを考慮し、一貫性のないINTとFLOATは比較障害につながります。
解決:
一貫した数値タイプを使用すると、元の値のタイプに従ってパラメーターを渡すことをお勧めします。
$value = apcu_fetch('rate');
if (is_float($value)) {
apcu_cas('rate', 1.0, 2.0);
}
apcu_delete('score');
$result = apcu_cas('score', 0, 1);
質問の説明:
キーが存在しない場合、 APCU_CASはfalseを直接返し、新しいキー値は作成されません。これにより、開発者は、キーの存在ではなく、操作の障害が異なる値によるものであると誤って信じる可能性があります。
解決:
APCU_CASを呼び出す前に、 apcu_existsまたはapcu_fetchを使用して、キーが存在するかどうかを確認します。
if (apcu_exists('score')) {
apcu_cas('score', 0, 1);
} else {
apcu_store('score', 1);
}
intまたはfloatを常に使用して数値を保存し、文字列デノーテッド数を使用しないようにします。データ作成ロジックの1つのレイヤーをカプセル化できます。
function set_numeric_apcu(string $key, int|float $value): void {
apcu_store($key, $value);
}
安全なラッパー関数を作成して、同じタイプを確保し、 APCU_CASを実行します。
function safe_apcu_cas(string $key, int|float $old, int|float $new): bool {
$current = apcu_fetch($key);
if (gettype($current) !== gettype($old)) {
return false;
}
return apcu_cas($key, $old, $new);
}
同時環境では、値を初期化するプロセスは明確かつ明確でなければなりません。キーが存在し、次の方法でタイプが正しいことを確認できます。
$key = 'counter';
if (!apcu_exists($key)) {
apcu_add($key, 0);
}
以下は、 APCU_CASを使用して安全に自動化する方法を示す完全な例を示します。
$key = 'visit_counter';
do {
$old = apcu_fetch($key);
if ($old === false) {
if (apcu_add($key, 1)) {
break;
} else {
continue;
}
}
$new = $old + 1;
} while (!apcu_cas($key, $old, $new));
$url = 'https://gitbox.net/stats';
echo "現在の訪問が更新されました。詳細については、ご覧ください: <a href=\"$url\">$url</a>";