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

bcncommerce/stream-wrapper

Laravel package providing a custom PHP stream wrapper to transparently read/write resources via non-standard URIs. Useful for integrating external storage or services behind fopen/file_get_contents with a familiar filesystem-like API.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require bcncommerce/stream-wrapper
    

    Add to composer.json if not using Composer:

    "require": {
        "bcncommerce/stream-wrapper": "^1.0"
    }
    
  2. Basic Usage: Register the wrapper in your application’s bootstrap (e.g., bootstrap/app.php or AppServiceProvider):

    use BCNCommerce\StreamWrapper\StreamWrapper;
    
    StreamWrapper::register('mywrapper', function ($path) {
        return new MyCustomStream($path);
    });
    
  3. First Use Case: Redirect file operations (e.g., fopen(), file_get_contents()) to a custom stream:

    $file = fopen('mywrapper://example.txt', 'r');
    // Handle file operations...
    fclose($file);
    

Implementation Patterns

Core Workflows

  1. Stream Redirection:

    • Replace filesystem operations (e.g., file_get_contents(), file_put_contents()) with custom logic.
    • Example: Proxy remote files via HTTP or database blobs.
    $content = file_get_contents('mywrapper://remote/file.txt');
    
  2. Integration with Laravel:

    • Use with Laravel’s Storage facade or Filesystem contracts:
    use Illuminate\Support\Facades\Storage;
    
    Storage::disk('custom')->put('file.txt', 'Hello');
    // Register wrapper for 'custom' disk in `config/filesystems.php`.
    
  3. Dynamic Path Handling:

    • Parse paths in the wrapper’s closure to implement logic (e.g., split user://123/data into userId=123 and file=data).
    StreamWrapper::register('user', function ($path) {
        [$userId, $file] = explode('/', ltrim($path, '/'), 2);
        return new UserFileStream($userId, $file);
    });
    
  4. Context-Aware Streams:

    • Pass additional context (e.g., user ID, request data) via wrapper arguments:
    StreamWrapper::register('request', function ($path, $context) {
        return new RequestFileStream($path, $context['user']);
    });
    

Gotchas and Tips

Pitfalls

  1. Stream Context Conflicts:

    • PHP’s stream_context_create() may override wrapper behavior. Explicitly set context:
    $context = stream_context_create(['mywrapper' => ['option' => 'value']]);
    file_get_contents('mywrapper://file.txt', false, $context);
    
  2. Case Sensitivity:

    • Wrapper names are case-sensitive (mywrapper://MyWrapper://).
  3. Resource Leaks:

    • Always call fclose() or use try-finally blocks to avoid memory leaks with custom streams.
  4. Laravel Caching:

    • If using with Laravel’s Storage, clear cached disks after registering new wrappers:
    Storage::disk('custom')->clear();
    

Debugging

  • Check Registration:
    var_dump(stream_get_wrappers()); // Verify 'mywrapper' appears.
    
  • Log Stream Errors:
    set_error_handler(function ($errno, $errstr) {
        if (strpos($errstr, 'mywrapper') !== false) {
            Log::error($errstr);
        }
    });
    

Extension Points

  1. Custom Stream Classes:

    • Implement StreamWrapperInterface for advanced features (e.g., locking, seeking):
    class MyStream implements StreamWrapperInterface {
        public function stream_open($path, $mode, $options, &$opened_path) { ... }
        // Implement other required methods.
    }
    
  2. Wrapper Chaining:

    • Combine wrappers (e.g., mywrapper://http://example.com/file):
    StreamWrapper::register('mywrapper', function ($path) {
        return fopen('http://' . $path, 'r');
    });
    
  3. Performance:

    • For high-throughput apps, cache stream instances or use stream_wrapper_restore() to reset state between requests.
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