This is an old revision of the document!
PHP RFC: Add is_cacheable() stream-wrapper operation
- Version: 1.0
- Date: 2015-01-04 (Happy new year !)
- Author: François Laupretre, francois@tekwire.net
- Status: Under discussion
- First Published at: http://wiki.php.net/rfc/streams-is-cacheable
Introduction
The RFC proposes a generic way for opcode caches to determine if a given URI is cacheable or not.
Proposal
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 nothing more than a quick-and-dirty workaround and we now need 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
None
Proposed PHP Version(s)
5.7, if released. Otherwise, PHP 7.
RFC Impact
To SAPIs
None
To Existing Extensions
Phar needs to implement an is_cacheable() function. This function always returns 1.
The same for the plain files wrapper.
To Opcache
Opcode caches will 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
The C-level PHP_STREAMS_SUPPORT_IS_CACHEABLE is defined. This allows conditional code using '#ifdef' stanza.
Open Issues
None
Unaffected PHP Functionality
Stream wrappers that don't require their scripts to be cacheable are not modified in any way.
Proposed Voting Choices
2/3 or 50%+1 majority ? Not clear for me :)
Patches and Tests
A pull request is available at :
https://github.com/php/php-src/pull/976
This patch includes every modification described in this RFC, including phar and plain files is_cacheable() handler. It also contains tests.
PHP manual changes not written yet.
Implementation
References
Pull request: https://github.com/php/php-src/pull/976