digitalcz / streams
Opinionated abstraction around PHP streams implementing PSR-7 StreamInterface
Requires
- php: ^8.2
- psr/http-message: ^2.0
Requires (Dev)
- digitalcz/coding-standard: ^0.5.0 || ^0.6.0 || ^0.7.0
- ergebnis/composer-normalize: ^2.50
- php-http/psr7-integration-tests: ^1.5
- phpstan/extension-installer: ^1.4.3
- phpstan/phpstan: ^2.1.39
- phpstan/phpstan-phpunit: ^2.0.16
- phpstan/phpstan-strict-rules: ^2.0.10
- phpunit/phpunit: ^11.5 || ^12.4
- slevomat/coding-standard: ^8.27
- squizlabs/php_codesniffer: ^4.0
- symfony/var-dumper: ^6.4 || ^7.4 || ^8.0
Suggests
- ext-fileinfo: Required to detect MIME type with StreamInfo::mimeType()
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-20 07:20:10 UTC
README
Opinionated abstraction around PHP streams implementing PSR-7 StreamInterface. It aims to improve working with files or remote streams in unified way.
Heavily inspired by guzzle/psr7.
Install
Via Composer
$ composer require digitalcz/streams
Usage
All streams implement DigitalCz\Streams\StreamInterface, which extends PSR-7
Psr\Http\Message\StreamInterface and adds a few convenience methods
(copy(), void-returning close()/seek(), …).
Stream
A wrapper around any PHP stream resource. Use Stream::from() to build one from
a string, a resource or another PSR-7 stream — the data is held in php://temp.
use DigitalCz\Streams\Stream; // From a string $stream = Stream::from('Hello world'); echo $stream->getContents(); // "Hello world" // From an existing resource $stream = Stream::from(fopen('php://memory', 'rb+')); // From another PSR-7 stream $stream = Stream::from($psrStream); // Wrapping a resource directly (optionally with a known size) $stream = new Stream(fopen('data.bin', 'rb')); // Copy another stream into this one (returns bytes written) $bytes = $stream->copy($otherStream);
File
A stream backed by a real file on disk. Adds getPath() and delete().
use DigitalCz\Streams\File; $file = new File('/path/to/file.txt'); // opened with mode "rb+" by default echo $file->getPath(); // Build a file from a string / resource / PSR-7 stream. // Write a string to a new temp file (the string is never treated as a path). $file = File::fromString('contents written to a temp file'); // File::from() also accepts a string, but an existing path opens that file, // otherwise it is the content. Never pass untrusted input to it. $file = File::from($psrStreamOrResource); $temp = File::temp(); // empty file in the system temp dir $file->delete(); // close and unlink
TempFile
Like File, but backed by tmpfile() — the underlying file is removed
automatically once the stream handle is closed.
use DigitalCz\Streams\TempFile; $temp = TempFile::from('temporary content'); echo $temp->getPath(); $temp->close(); // file is deleted on close
BufferedStream
Wraps a non-seekable / one-shot source stream and buffers what it reads into
php://temp, so the source can be re-read and seeked. It is read-only.
use DigitalCz\Streams\BufferedStream; $buffered = new BufferedStream($nonSeekableSource); $head = $buffered->read(1024); $buffered->rewind(); // works even if the source could not seek $all = $buffered->getContents();
LimitStream
Read-only view of a window of another stream: at most $limit bytes starting
at $offset. Size, position and seeking are relative to the window.
use DigitalCz\Streams\LimitStream; $window = new LimitStream($stream, limit: 100, offset: 50); $chunk = $window->getContents(); // bytes 50–149 of $stream
AppendStream
Reads several streams one after another as if they were one (seekable parts are read from the start). It is read-only, seekable only if all parts are, and its size is unknown if any part's size is.
use DigitalCz\Streams\AppendStream; use DigitalCz\Streams\Stream; $stream = new AppendStream(Stream::from('header'), $body, Stream::from('footer')); $all = $stream->getContents();
StreamWrapper
Turns a StreamInterface back into a native PHP stream resource, usable with
any function that expects one (fread, fgets, stream_copy_to_stream, …).
use DigitalCz\Streams\StreamWrapper; $resource = StreamWrapper::from($stream); $line = fgets($resource);
StreamInfo
Hashes or detects the MIME type of any PSR-7 stream without loading it all into
memory. Seekable streams are read from the start and their position is restored.
Non-seekable streams are read from the current position and the bytes read are
consumed — wrap them in BufferedStream if you need them again.
use DigitalCz\Streams\StreamInfo; $sha256 = StreamInfo::hash($stream, 'sha256'); // any algorithm from hash_algos() $mimeType = StreamInfo::mimeType($stream); // e.g. "application/pdf", requires ext-fileinfo
Change log
Please see CHANGELOG for more information on what has changed recently.
Testing
$ composer csfix # fix codestyle $ composer checks # run all checks # or separately $ composer tests # run phpunit $ composer phpstan # run phpstan $ composer cs # run codesniffer
Contributing
Please see CONTRIBUTING for details.
Security
If you discover any security related issues, please email devs@digital.cz instead of using the issue tracker.
Credits
License
The MIT License (MIT). Please see License File for more information.