[wp-trac] [WordPress Trac] #20004: Fix NULL and FALSE in WP_Object_Cache and make found/not-found unambiguous.
WordPress Trac
wp-trac at lists.automattic.com
Thu Feb 9 22:58:01 UTC 2012
#20004: Fix NULL and FALSE in WP_Object_Cache and make found/not-found unambiguous.
------------------------------------+------------------------------
Reporter: andy | Owner:
Type: defect (bug) | Status: new
Priority: normal | Milestone: Awaiting Review
Component: Cache | Version:
Severity: normal | Resolution:
Keywords: has-patch dev-feedback |
------------------------------------+------------------------------
Description changed by andy:
Old description:
> ```WP_Object_Cache``` mistreats ```NULL``` as a stored value by
> converting it to ```""```. To handle it correctly, the existence check
> must not use ```isset()```:
>
> {{{
> $cache[ $key ] = NULL;
> isset( $cache[ $key ] ); // false
> array_key_exists( $key, $cache ); // true
> }}}
>
> The attached patch corrects the treatment of ```NULL``` by storing it as-
> is and using ```array_key_exists()``` to test the existence of a key.
>
> As a value returned from ```wp_cache_get```, ```FALSE``` is ambiguous. It
> could mean that the value stored and retrieved was literally ```FALSE```
> or that the key was not found.
>
> The attached patch moves the found/not-found information to a pass-by-
> reference parameter, ```$found```, which is set to ```TRUE``` after a
> cache hit or ```FALSE``` after a cache miss. This allows storage and
> retrieval of ```FALSE``` without ambiguity and reduces the temptation to
> use confusing patterns such as ```!$value```, ```$value === false```, and
> ```empty( $value )```.
>
> The attached patch permits a clearer coding style:
>
> {{{
> $found = null;
> $value = wp_cache_get( $key, $group, false, $found );
> if ( ! $found ) {
> $value = $wpdb->get_results( $query );
> wp_cache_set( $key, $value, $group );
> }
> }}}
>
> (Assigning ```$found = null;``` prevents "Notice: Undefined variable".)
>
> However, because object cache drop-ins may lag behind core in adding
> support for the ```$found``` parameter, the following pattern may be
> preferred for backwards compatibility:
>
> {{{
> $found = null;
> $value = wp_cache_get( $key, $group, false, $found );
> if ( ! $value && ! $found ) {
> $value = $wpdb->get_results( $query );
> wp_cache_set( $key, $value, $group );
> }
> }}}
>
> I also added a function, ```wp_cache_found()```, to determine whether the
> previous retrieval was a hit or a miss.
>
> {{{
> $value = wp_cache_get( $key, $group );
> if ( ! wp_cache_found() ) {
> $value = $wpdb->get_results( $query );
> wp_cache_set( $key, $value, $group );
> }
> }}}
>
> Again, this function may not be present in drop-ins. Until such time as
> old drop-ins are forced into obsolescence, use ```function_exists```
> before calling ```wp_cache_found``` in core code.
>
> It would behoove us to devise a drop-in API versioning and update system
> to assist with this.
New description:
```WP_Object_Cache``` mistreats ```NULL``` as a stored value by converting
it to ```""```. To handle it correctly, the existence check must not use
```isset()```:
{{{
$cache[ $key ] = NULL;
isset( $cache[ $key ] ); // false
array_key_exists( $key, $cache ); // true
}}}
The attached patch corrects the treatment of ```NULL``` by storing it as-
is and using ```array_key_exists()``` to test the existence of a key.
As a value returned from ```wp_cache_get```, ```FALSE``` is ambiguous. It
could mean that the value stored and retrieved was literally ```FALSE```
or that the key was not found.
The attached patch moves the found/not-found information to a pass-by-
reference parameter, ```$found```, which is set to ```TRUE``` after a
cache hit or ```FALSE``` after a cache miss. This allows storage and
retrieval of ```FALSE``` without ambiguity and reduces the temptation to
use confusing patterns such as ```!$value```, ```$value === false```, and
```empty( $value )```.
The attached patch permits a clearer coding style:
{{{
$value = wp_cache_get( $key, $group, false, $found );
if ( ! $found ) {
$value = $wpdb->get_results( $query );
wp_cache_set( $key, $value, $group );
}
}}}
However, because object cache drop-ins may lag behind core in adding
support for the ```$found``` parameter, the following pattern may be
preferred for backwards compatibility:
{{{
$value = wp_cache_get( $key, $group, false, $found );
if ( ! $value && ! $found ) {
$value = $wpdb->get_results( $query );
wp_cache_set( $key, $value, $group );
}
}}}
I also added a function, ```wp_cache_found()```, to determine whether the
previous retrieval was a hit or a miss.
{{{
$value = wp_cache_get( $key, $group );
if ( ! wp_cache_found() ) {
$value = $wpdb->get_results( $query );
wp_cache_set( $key, $value, $group );
}
}}}
Again, this function may not be present in drop-ins. Until such time as
old drop-ins are forced into obsolescence, use ```function_exists```
before calling ```wp_cache_found``` in core code.
It would behoove us to devise a drop-in API versioning and update system
to assist with this.
--
--
Ticket URL: <http://core.trac.wordpress.org/ticket/20004#comment:5>
WordPress Trac <http://core.trac.wordpress.org/>
WordPress blogging software
More information about the wp-trac
mailing list