Table of Contents

Dedicated StreamBucket class

Introduction

When using user filters for stream processing, one of the fundamental concepts is stream buckets. A stream bucket is effectively a chunk of stream which can be extracted from bucket brigades. Most probably, this metaphor comes from firefighting bucket brigades who pass buckets of water to each other, standing in a chain.

Back to our original topic, here is an example of a very basic stream filter:

class simple_filter extends php_user_filter {
    function filter($in, $out, &$consumed, $closing) {
        while ($bucket = stream_bucket_make_writeable($in)) {
            $consumed += $bucket->datalen;
            stream_bucket_append($out, $bucket);
        }
        return PSFS_PASS_ON;
    }
}
 
stream_filter_register("simple", "simple_filter")

Disclaimer: the example is copy-pasted from https://stackoverflow.com/questions/27103269/what-is-a-bucket-brigade. Courtesy of Bob for providing such an exceptional answer to explain the behavior of user stream filters.

$in and $out are the two sides of the stream bucket brigade: items come from the former one, which have to be passed to the latter one. The stream_bucket_make_writeable() function can be used to get the bucket from the brigade, while the stream_bucket_new() function is used to create a new bucket.

Discussion

There are a few slightly unfortunate issues how stream buckets are handled which are discussed in the following sections.

Lack of a dedicated class

The original problem why this RFC is submitted is that there is no dedicated class for stream buckets: stream_bucket_make_writeable() and stream_bucket_new() create stdClass instances and fill in their $bucket, $data, as well as $datalen properties on the fly.

$bucket = stream_bucket_new(fopen('php://temp', 'w+'), '');
var_dump($bucket);
 
/*
object(stdClass)#1 (3) {
  ["bucket"]=>
  resource(7) of type (userfilter.bucket)
  ["data"]=>
  string(0) ""
  ["datalen"]=>
  int(0)
}
*/

As a consequence, their return type is no more specific than object. Similarly, the second parameters of the stream_bucket_append() and the stream_bucket_prepend() functions (which expect stream buckets) accept any kind of objects by checking the existence of the necessary properties.

If we had a dedicated class for stream buckets then the advantages were the usual: better feedback could be provided by static analysis tools, while autocomplete in IDEs worked out of the box. Additionally, by having typed properties for the $data and the $datalen properties, we could get additional safeguards.

The $bucket property

The $bucket property is a stream bucket resource which is about to be migrated to an object in a major PHP version as per Resource to object conversion. However, this property won't be useful anymore as soon as it becomes an object, since it can be inlined directly into the containing stream bucket class. Therefore, this RFC proposes to emit a deprecation notice as soon as the resource to object migration happens (in a major PHP version). The consequent major version should then get rid of the property altogether.

The $datalen property

The name of this property doesn't conform to the currently used naming conventions: we usually try to avoid abbreviations whenever possible (e.g. when the full name is not too verbose, and the abbreviation is not an extremely common term - like $id). Since the difference between len and length is just 3 characters, I don't think that using this abbreviation is really worth it. Therefore, this RFC proposes to add a $dataLength property.

Additionally, the $datalen property would become deprecated in favor of $dataLength in the subsequent minor or major version after the target version (possibly PHP 8.5 or PHP 9.0), and would be removed in the next to next major version (possibly PHP 10).

The proposed class

The final form of the proposed class is the following:

final class StreamBucket
{
    /**
     * @var resource
     * @deprecated after resource to object conversion happens
     */
    public $bucket;
    public string $data;
    /** @deprecated in PHP 8.5 or PHP 9.0 whichever comes next */
    public int $datalen;
    public int $dataLength;
}

Vote

The vote requires 2/3 majority in order to be accepted. The vote is going to be closed on 2024-04-11 10:00 UTC.

Primary vote

Add the StreamBucket class as proposed?
Real name yes no
alcaeus (alcaeus)  
asgrim (asgrim)  
brzuchal (brzuchal)  
crell (crell)  
dams (dams)  
derick (derick)  
devnexen (devnexen)  
ericmann (ericmann)  
galvao (galvao)  
gasolwu (gasolwu)  
kocsismate (kocsismate)  
mbeccati (mbeccati)  
mcmic (mcmic)  
nicolasgrekas (nicolasgrekas)  
nielsdos (nielsdos)  
petk (petk)  
reywob (reywob)  
saki (saki)  
sergey (sergey)  
svpernova09 (svpernova09)  
Final result: 20 0
This poll has been closed.