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 Util Laravel Package

twistor/stream-util

Lightweight PHP helper for working with streams. Copy/clone streams, inspect size and metadata, check readability/writability/seekability/appendability, and safely rewind/seek. Includes mode and URI utilities for fopen-compatible streams.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require twistor/stream-util
    

    Add to composer.json under require or via Laravel's require command:

    php artisan vendor:publish --provider="Twistor\StreamUtil\StreamUtilServiceProvider"
    
  2. First Use Case: Check stream capabilities in a Laravel controller or service:

    use Twistor\StreamUtil;
    
    $stream = fopen(storage_path('app/test.txt'), 'r+');
    $isReadable = StreamUtil::isReadable($stream); // true
    $size = StreamUtil::getSize($stream); // Returns file size in bytes
    fclose($stream);
    
  3. Key Classes:

    • StreamUtil (main facade)
    • Underlying \Twistor\StreamUtil\StreamUtil class (for direct usage)

Implementation Patterns

Common Workflows

1. Stream Validation & Metadata

// Validate stream capabilities before operations
if (StreamUtil::isReadable($stream) && StreamUtil::isWritable($stream)) {
    $size = StreamUtil::getSize($stream);
    $meta = StreamUtil::getMetaDataKey($stream, 'blocked');
}

2. Stream Cloning & Copying

// Clone a stream (useful for parallel processing)
$original = fopen('file.txt', 'r');
$cloned = StreamUtil::copy($original, false); // false = don't close original

3. Mode-Based Logic

// Check file modes before operations
if (StreamUtil::modeIsReadable('r+')) {
    // Safe to read
}

4. Laravel Integration

// Use in Laravel Filesystem
use Illuminate\Support\Facades\Storage;

$stream = Storage::disk('local')->readStream('file.txt');
$isSeekable = StreamUtil::isSeekable($stream);

5. Temporary Stream Handling

// Create and validate temp streams
$temp = fopen('php://temp', 'w+b');
if (StreamUtil::isWritable($temp)) {
    fwrite($temp, 'data');
    StreamUtil::tryRewind($temp);
}

Advanced Patterns

Stream Wrapper Validation

// Check if a URI is usable (e.g., for fopen)
$uri = 's3://bucket/file.txt';
$usableUri = StreamUtil::getUsableUri($uri); // Returns false if invalid

Batch Processing with Stream Checks

// Process files in batches with stream validation
foreach ($files as $file) {
    $stream = fopen($file, 'r');
    if (StreamUtil::isReadable($stream) && StreamUtil::getSize($stream) > 0) {
        // Process stream
    }
    fclose($stream);
}

Custom Stream Utilities

Extend the package for Laravel-specific needs:

// app/Extensions/StreamUtil.php
namespace App\Extensions;

use Twistor\StreamUtil;

class LaravelStreamUtil extends StreamUtil
{
    public static function isLaravelStorageStream($stream)
    {
        return is_resource($stream) && strpos(StreamUtil::getUri($stream), 'laravel-storage:') === 0;
    }
}

Gotchas and Tips

Pitfalls

  1. Resource Leaks:

    • StreamUtil::copy($stream, true) closes the original stream. Use cautiously in loops or pipelines.
    • Always fclose() or let Laravel's Storage handle cleanup.
  2. False Positives in Mode Checks:

    • modeIsReadOnly('r+') returns false (correct), but modeIsReadable('r+') returns true. Double-check logic.
  3. Non-Seekable Streams:

    • trySeek() may fail on non-seekable streams (e.g., php://stdin). Handle exceptions:
      try {
          StreamUtil::trySeek($stream, 0, SEEK_SET);
      } catch (\RuntimeException $e) {
          // Fallback logic
      }
      
  4. Metadata Limitations:

    • getMetaDataKey() may return null for unsupported stream types (e.g., php://memory).
  5. URI Handling:

    • getUsableUri() returns false for non-fopen-compatible URIs (e.g., php://temp). Validate before use.

Debugging Tips

  1. Stream State Inspection:

    $stream = fopen('file.txt', 'r');
    debug([
        'readable' => StreamUtil::isReadable($stream),
        'writable' => StreamUtil::isWritable($stream),
        'seekable' => StreamUtil::isSeekable($stream),
        'uri' => StreamUtil::getUri($stream),
    ]);
    
  2. Common Errors:

    • "Stream not seekable": Use StreamUtil::isSeekable() first.
    • "Invalid argument": Check if the stream is closed or invalid with is_resource($stream).
  3. Performance:

    • Avoid repeated getSize() calls on large streams. Cache results if needed.

Extension Points

  1. Custom Stream Types: Override StreamUtil to support Laravel-specific streams:

    class CustomStreamUtil extends \Twistor\StreamUtil\StreamUtil
    {
        public static function isLaravelStream($stream)
        {
            return strpos(self::getUri($stream), 'laravel-storage:') !== false;
        }
    }
    
  2. Event-Based Validation: Hook into Laravel events to validate streams pre-operation:

    // In EventServiceProvider
    public function boot()
    {
        Storage::preventAccess(function ($path) {
            $stream = fopen($path, 'r');
            return !StreamUtil::isReadable($stream);
        });
    }
    
  3. Testing: Mock StreamUtil in PHPUnit:

    $mockStream = $this->getMockBuilder(\stdClass::class)
        ->disableOriginalConstructor()
        ->getMock();
    
    StreamUtil::shouldReceive('isReadable')
        ->with($mockStream)
        ->andReturn(true);
    

Laravel-Specific Quirks

  1. Storage Facade Integration:

    • Use Storage::readStream()/writeStream() with StreamUtil for metadata checks:
      $stream = Storage::disk('s3')->readStream('file.txt');
      if (StreamUtil::isReadable($stream)) {
          // Process
      }
      Storage::disk('s3')->close($stream);
      
  2. Filesystem Events: Combine with Laravel's filesystem events for stream-aware logic:

    Storage::disk('local')->addListener('reading', function ($event) {
        if (!StreamUtil::isReadable($event->stream)) {
            Log::warning('Unreadable stream accessed');
        }
    });
    
  3. Queue Jobs: Validate streams in job payloads:

    public function handle()
    {
        $stream = fopen($this->streamPath, 'r');
        if (!StreamUtil::isReadable($stream)) {
            throw new \RuntimeException('Invalid stream');
        }
        // Process
    }
    
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.
terminal42/code-quality-tools
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