Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Stream Laravel Package

guzzle/stream

Lightweight stream abstraction for PHP and Guzzle, offering common stream utilities and decorators to read, write, and transform data consistently. Useful for building HTTP clients, middleware, and I/O workflows that need simple, testable stream handling.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation Add to composer.json:

    "require": {
        "guzzle/stream": "^3.0"
    }
    

    Run composer update.

  2. First Use Case Stream a large file (e.g., from S3 or a remote server) without loading it entirely into memory:

    use Guzzle\Stream\Stream;
    
    $stream = Stream::fromFile('large_file.zip');
    $chunkSize = 1024; // 1KB chunks
    $stream->rewind();
    
    while (!$stream->eof()) {
        $chunk = $stream->read($chunkSize);
        // Process chunk (e.g., upload to another service)
    }
    
  3. Key Classes to Know

    • Guzzle\Stream\Stream: Core stream abstraction.
    • Guzzle\Stream\StreamInterface: Contract for streams.
    • Guzzle\Stream\StreamDecorator: Wrap existing streams (e.g., for logging).
    • Guzzle\Stream\PhpStream: PHP-native stream wrapper.

Implementation Patterns

1. Streaming Large Files

Pattern: Use Stream::fromFile() or Stream::fromResource() to avoid memory overload.

$stream = Stream::fromFile(storage_path('logs/large.log'));
$stream->rewind();
while (!$stream->eof()) {
    $data = $stream->read(8192); // 8KB chunks
    // Process $data incrementally
}

2. Wrapping Streams for Custom Logic

Pattern: Decorate streams to add behavior (e.g., compression, logging).

use Guzzle\Stream\StreamDecorator;

$originalStream = Stream::fromFile('input.txt');
$decoratedStream = new StreamDecorator($originalStream, function ($chunk) {
    return strtoupper($chunk); // Example: Convert to uppercase
});

3. Integration with HTTP Clients

Pattern: Use streams with Guzzle HTTP client for chunked uploads/downloads.

$client = new \GuzzleHttp\Client();
$response = $client->get('https://example.com/large-file.zip', [
    'sink' => 'downloads/large-file.zip',
    'stream' => true,
]);

4. Reading/Writing to Remote Streams

Pattern: Stream directly from/to remote URLs or resources.

$remoteStream = Stream::fromCurl('https://example.com/stream-data');
$localStream = Stream::toFile('local-copy.txt');
stream_copy_to_stream($remoteStream, $localStream);

5. Memory-Mapped Files

Pattern: Use Stream::fromFile() with memory_map for zero-copy reads.

$stream = Stream::fromFile('huge-dataset.bin', ['memory_map' => true]);
// Access data via $stream->read() without loading entire file

Gotchas and Tips

Pitfalls

  1. Resource Leaks

    • Always call $stream->close() when done to free resources.
    • Use finally blocks or context managers (e.g., Laravel’s Storage facade) to ensure cleanup.
  2. Stream Positioning

    • rewind() resets the stream pointer. Forgetting this can cause skipped data.
    • tell() returns the current position; useful for resuming interrupted transfers.
  3. Chunk Size Trade-offs

    • Too small: High overhead from frequent I/O.
    • Too large: Memory spikes or timeouts.
    • Rule of thumb: 8KB–64KB for most use cases.
  4. PHP Stream Wrappers

    • Some wrappers (e.g., php://temp) require explicit closing.
    • Avoid mixing guzzle/stream with native PHP streams (e.g., fopen) unless necessary.
  5. Error Handling

    • Streams may fail silently. Wrap operations in try-catch:
      try {
          $stream->read(1024);
      } catch (\RuntimeException $e) {
          // Handle stream errors (e.g., disk full)
      }
      

Debugging Tips

  • Check Stream Metadata:
    $stream->meta(); // Returns array of stream properties (e.g., size, mode)
    
  • Log Stream Contents: Use StreamDecorator to log chunks:
    $stream = new StreamDecorator($originalStream, function ($chunk) {
        \Log::debug('Chunk:', ['size' => strlen($chunk)]);
        return $chunk;
    });
    
  • Validate Stream State:
    if (!$stream->isReadable()) {
        throw new \RuntimeException('Stream is not readable');
    }
    

Extension Points

  1. Custom Stream Sources Implement StreamInterface for new stream types (e.g., database blobs):

    class DatabaseStream implements StreamInterface {
        // Implement read(), write(), etc.
    }
    
  2. Stream Filters Chain decorators for complex transformations:

    $stream
        ->pipe(new StreamDecorator($stream, fn($c) => gzdecode($c))) // Decompress
        ->pipe(new StreamDecorator($stream, fn($c) => str_replace('foo', 'bar', $c))); // Replace text
    
  3. Laravel Integration

    • Use with Storage facade for disk streams:
      $stream = Stream::fromResource(fopen(storage_path('file.txt'), 'r'));
      Storage::disk('s3')->writeStream('remote-file.txt', $stream);
      
    • Combine with Http client for chunked uploads:
      $client->post('https://api.example.com/upload', [
          'body' => Stream::fromFile('large-file.zip'),
      ]);
      

Config Quirks

  • Memory Mapping: Enable with ['memory_map' => true] for large files, but ensure PHP has sufficient memory_map limits.
  • Timeouts: Streams don’t support timeouts directly. Use StreamDecorator to wrap with a timeout:
    $stream = new StreamDecorator($originalStream, function () use (&$timeout) {
        if ($timeout-- <= 0) throw new \RuntimeException('Timeout');
        return $this->stream->read(1024);
    }, 100); // 100ms timeout per chunk
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky
spatie/mailcoach-vapor