The definition of apcu_cas is as follows:
bool apcu_cas(string $key, int|float $old, int|float $new)
The function of this function is: if the current value of the key $key is equal to $old , then its value is set to $new and returns true ; otherwise, it returns false .
It is worth noting that it can only be used for values of numerical types ( int or float ) or the operation will fail.
apcu_store('counter', '5');
$result = apcu_cas('counter', 5, 10);
Question description:
While '5' looks like a number, inside apcu_cas , type checking is strict. The string '5' is not equal to the integer 5 , so the cas operation will fail.
Solution:
Make sure to use the numeric type when storing:
apcu_store('counter', 5);
Or cast before comparison:
$value = apcu_fetch('counter');
if (is_numeric($value)) {
apcu_store('counter', (int)$value);
}
apcu_store('rate', 1.0);
apcu_cas('rate', 1, 2.0);
Question description:
Although 1 and 1.0 are mathematically equal, apcu_cas will also take the type into account when comparing, and inconsistent int and float lead to the comparison failure.
Solution:
Using a consistent numerical type, it is recommended to pass parameters according to the type of the original value:
$value = apcu_fetch('rate');
if (is_float($value)) {
apcu_cas('rate', 1.0, 2.0);
}
apcu_delete('score');
$result = apcu_cas('score', 0, 1);
Question description:
If the key does not exist, apcu_cas will directly return false and no new key value will be created. This may cause developers to mistakenly believe that the operation failure is due to different values, rather than the non-existence of the key.
Solution:
Before calling apcu_cas , use apcu_exists or apcu_fetch to confirm whether the key exists:
if (apcu_exists('score')) {
apcu_cas('score', 0, 1);
} else {
apcu_store('score', 1);
}
Always use int or float to store numeric values, avoiding using numbers represented by strings. One layer of data writing logic can be encapsulated:
function set_numeric_apcu(string $key, int|float $value): void {
apcu_store($key, $value);
}
Create a safe wrapper function to ensure the same type and then execute 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);
}
In a concurrent environment, the process of initializing values should be clear and clear. You can ensure that the key exists and the type is correct by the following methods:
$key = 'counter';
if (!apcu_exists($key)) {
apcu_add($key, 0);
}
Here is a complete example showing how to use apcu_cas to safely auto-increment:
$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 "Current visits have been updated。Please visit for details: <a href=\"$url\">$url</a>";