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

File Laravel Package

bengor-file/file

Lightweight PHP file management library built with Domain-Driven Design. Provides common operations like upload (default or by hash), overwrite, remove, and rename, with a tested, documented codebase and flexible storage integration.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require bengor-file/file
    

    Add to composer.json if using Laravel’s vendor directory:

    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "BenGor\\File\\": "vendor/bengor-file/file/src/"
        }
    }
    

    Run composer dump-autoload.

  2. First Use Case: Handle a file upload in a Laravel controller:

    use BenGor\File\FileManager;
    use BenGor\File\Storage\LocalStorage;
    
    // Configure storage (e.g., local filesystem)
    $storage = new LocalStorage(storage_path('app/uploads'));
    $fileManager = new FileManager($storage);
    
    // Handle upload
    $request->file('file')->store('uploads');
    $file = $fileManager->upload($request->file('file'));
    
  3. Key Classes:

    • FileManager: Core class for file operations.
    • Storage\LocalStorage: Default storage adapter (extend for S3, etc.).
    • File: Represents a file entity with metadata (name, hash, size, etc.).

Implementation Patterns

Core Workflows

  1. File Uploads:

    • Default Upload:
      $file = $fileManager->upload($request->file('file'));
      // Returns File entity with path, hash, and metadata.
      
    • Upload by Hash (avoid duplicates):
      $file = $fileManager->uploadByHash($request->file('file'));
      
  2. File Management:

    • Overwrite Existing File:
      $fileManager->overwrite($existingFile, $newFile);
      
    • Rename File:
      $fileManager->rename($file, 'new-name.ext');
      
    • Delete File:
      $fileManager->remove($file);
      
  3. Storage Adapters:

    • Extend Storage\StorageInterface for custom storage (e.g., AWS S3):
      class S3Storage implements StorageInterface {
          public function save(File $file, $content) { /* ... */ }
          public function exists($path) { /* ... */ }
          // ...
      }
      
    • Inject into FileManager:
      $fileManager = new FileManager(new S3Storage());
      
  4. Laravel Integration:

    • Service Provider: Bind FileManager to the container in AppServiceProvider:
      $this->app->singleton(FileManager::class, function ($app) {
          return new FileManager(new LocalStorage(storage_path('app/uploads')));
      });
      
    • Facade (Optional): Create a facade for cleaner syntax:
      // FileManagerFacade.php
      namespace App\Facades;
      use Illuminate\Support\Facades\Facade;
      class FileManagerFacade extends Facade {
          protected static function getFacadeAccessor() { return 'file-manager'; }
      }
      
      Register in AppServiceProvider:
      Facade::alias(FileManagerFacade::class, 'FileManager');
      
      Usage:
      use App\Facades\FileManager;
      $file = FileManager::upload($request->file('file'));
      
  5. Domain-Driven Design (DDD) Patterns:

    • Value Objects: Use File entities to encapsulate file logic (e.g., validation, metadata).
    • Repositories: Create a repository to abstract storage:
      class FileRepository {
          protected $fileManager;
          public function __construct(FileManager $fileManager) {
              $this->fileManager = $fileManager;
          }
          public function save(File $file) {
              return $this->fileManager->upload($file->getFile());
          }
      }
      

Gotchas and Tips

Common Pitfalls

  1. Deprecated Package:

    • Last release in 2018; test thoroughly for compatibility with PHP 7.4/8.x and Laravel 8/9.
    • Check for breaking changes in File entity methods (e.g., getPath() vs. getStoragePath()).
  2. Storage Adapter Quirks:

    • LocalStorage assumes Unix-like paths. For Windows, normalize paths:
      $path = str_replace('\\', '/', $path);
      
    • Custom adapters must implement all StorageInterface methods (e.g., delete(), getUrl()).
  3. File Hashing:

    • uploadByHash() uses md5_file() by default. For consistency, override hashing logic:
      $fileManager->setHashAlgorithm(function ($file) {
          return hash_file('sha256', $file->getPathname());
      });
      
  4. Laravel Filesystem Integration:

    • Avoid mixing Laravel’s Storage facade with BenGorFile. Use one consistently:
      // Bad: Mixing approaches
      $path = $request->file('file')->store('uploads');
      $file = $fileManager->upload($path); // Fails: expects UploadedFile, not path.
      
    • Prefer BenGorFile for DDD-centric projects; use Laravel’s Storage for simplicity.
  5. Error Handling:

    • Wrap operations in try-catch:
      try {
          $file = $fileManager->upload($request->file('file'));
      } catch (\BenGor\File\Exception\FileException $e) {
          return back()->withError($e->getMessage());
      }
      
    • Custom exceptions extend BenGor\File\Exception\FileException.

Debugging Tips

  1. Log File Metadata:

    $file = $fileManager->upload($request->file('file'));
    \Log::debug('Uploaded file', [
        'name' => $file->getName(),
        'hash' => $file->getHash(),
        'path' => $file->getStoragePath(),
    ]);
    
  2. Verify Storage Paths:

    • Ensure LocalStorage paths are correct:
      $storage = new LocalStorage(storage_path('app/uploads'));
      \Log::info('Storage base path:', [$storage->getBasePath()]);
      
  3. Test Hash Collisions:

    • Manually trigger hash collisions to test uploadByHash:
      $file1 = $fileManager->upload(fopen('file1.txt', 'r'));
      $file2 = $fileManager->upload(fopen('file1.txt', 'r')); // Should reuse hash.
      

Extension Points

  1. Custom File Validation:

    • Extend File entity or use a validator:
      $validator = Validator::make([
          'file' => $request->file('file'),
      ], [
          'file' => 'required|mimes:jpg,png|max:2048',
      ]);
      if ($validator->fails()) { /* ... */ }
      
  2. Post-Upload Actions:

    • Hook into events (e.g., after upload):
      $fileManager->upload($request->file('file'), function ($file) {
          // Generate thumbnail, update DB, etc.
          \Log::info('Post-upload action for:', [$file->getName()]);
      });
      
  3. File Metadata:

    • Access extended metadata via File entity:
      $file->setMetadata(['user_id' => auth()->id(), 'original_name' => $request->file('file')->getClientOriginalName()]);
      $file->getMetadata('user_id');
      
  4. Testing:

    • Mock StorageInterface for unit tests:
      $mockStorage = Mockery::mock(StorageInterface::class);
      $mockStorage->shouldReceive('save')->andReturn(true);
      $fileManager = new FileManager($mockStorage);
      
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
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