Weave 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.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel