PHP RFC: Add is_cacheable() stream-wrapper operation


The RFC proposes a generic way for opcode caches to determine if a given URI is cacheable or not.


When stream wrappers were introduced in PHP, their relationship with opcode caches was not a problem, as they were mostly used to access remote data. The need for a better interaction arose with package systems, like phar and phk, as these stream wrappers manage a virtual PHP source tree through stream URIs. If the scripts provided by such a system cannot be opcode-cached, the system looses a great part of its value.

Historically, the issue was addressed using different workarounds : either every URI is considered as opcode-cacheable (APC), whatever wrapper it is coming from, or a list of 'cacheable' protocols is declared explicitely in the cache code. For instance, opcache is using the second solution : 'file' and 'phar' are explicitely declared as the only 'cacheable' stream wrappers. This is a quick-and-dirty workaround and there is real need for a reliable and generic way of determining whether an URI is cacheable.

What I am proposing :

* An element named 'stream_is_cacheable' is added at the end of the php_stream_wrapper_ops structure. This is an optional pointer to a function able to determine if a given URI is cacheable or not. This function receives an URI, an options bitfield, and an optional context. It returns a value different of 0 if the URI is cacheable. If the 'stream_is_cacheable' element is null, every URI for this wrapper are considered as non-cacheable.

* A new C function named php_stream_is_cacheable(const char *path, int options, php_stream_context *context) is defined. It determines the right wrapper from the path it receives and forwards the request to the corresponding stream_is_cacheable() function, if it exists. If the stream_is_cacheable() element is not defined, 0 is returned.

* Userspace stream wrappers can define a method named is_cacheable(path [,options]). This method determines if the input path is cacheable and returns true or false. If the method is not defined, every path for this wrapper are non-cacheable.

* For completeness, a new PHP function named file_is_cacheable(path [, options [, context]]) is defined. It allows to determine from a PHP script whether a path is cacheable.

Backward Incompatible Changes


Proposed PHP Version(s)

PHP 7.

RFC Impact



To Existing Extensions

Phar needs to implement an is_cacheable() function, returning always 1.

The same for the plain files wrapper.

To Opcache

Opcode caches must implement the following logic :

If the received path is a 'stream' path, call php_stream_is_cacheable(path, 0, NULL).

If the returned value is non null, the path is cacheable. If it is null, the path is not cacheable.

New Constants


Open Issues

Discussion is under way to define how the cache can compute the key corresponding to a stream-wrapped path.

Unaffected PHP Functionality

Stream wrappers that don't require their scripts to be cacheable are not modified in any way.

Proposed Voting Choices

Required majority: 50%+1

Patches and Tests

Pull Request: https://github.com/php/php-src/pull/976

This PR includes every modification described in this RFC, including phar and plain files is_cacheable() handler. It also contains tests.

PHP documentation additions (file_is_cacheable(), streamWrapper::is_cacheable()) not written yet.



Rejected Features

rfc/streams-is-cacheable.txt · Last modified: 2017/09/22 13:28 by