Current Location: Home> Latest Articles> Type matching problem and avoidance method in apcu_cas function operation

Type matching problem and avoidance method in apcu_cas function operation

gitbox 2025-06-03

What is apcu_cas?

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.


Common type matching problems

1. The comparison of string values ​​and integers failed

 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);
}

2. Use float and int do not match

 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);
}

3. Error operation when the key does not exist

 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);
}

How to effectively avoid these errors?

1. Unified type control

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);
}

2. Pre-CAS type detection

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);
}

3. Value initialization strategy

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);
}

Practical example: Safe self-increase counter

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>";