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

Google Cloud Storage Media Bundle Laravel Package

app-verk/google-cloud-storage-media-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the bundle:

    composer require app-verk/google-cloud-storage-media-bundle
    
  2. Enable the bundle in config/bundles.php:

    AppVerk\GoogleCloudStorageMediaBundle\GoogleCloudStorageMediaBundle::class => ['all' => true],
    
  3. Create a Media entity extending BaseMedia:

    // src/Entity/Media.php
    namespace App\Entity;
    use AppVerk\GoogleCloudStorageMediaBundle\Entity\Media as BaseMedia;
    use Doctrine\ORM\Mapping as ORM;
    
    #[ORM\Entity]
    class Media extends BaseMedia {}
    
  4. Configure the bundle in config/packages/google_cloud_storage_media.yaml:

    google_cloud_storage_media:
        namer: "AppVerk\\GoogleCloudStorageMediaBundle\\Namer\\DefaultNamer"
        filesystem: "default.storage"
        filesystem_url_retriever: 'AppVerk\GoogleCloudStorageMediaBundle\Flysystem\Retriever\GoogleObjectUrlRetriever'
        entities:
            media_class: App\Entity\Media
        gcs:
            project_id: "your-project-id"
            bucket_id: "your-bucket-name"
            key_file_path: "%kernel.project_dir%/path/to/keyfile.json"
        allowed_mime_types: ["image/jpeg", "image/png"]
    
  5. Configure Flysystem in config/packages/flysystem.yaml:

    flysystem:
        storages:
            default.storage:
                adapter: 'gcloud'
                public: true
                options:
                    client: 'gcloud_client_service'
                    bucket: 'your-bucket-name'
    
  6. Configure the GCS client in config/services.yaml:

    services:
        gcloud_client_service:
            class: Google\Cloud\Storage\StorageClient
            arguments:
                - projectId: "%google_cloud_storage_media.gcs.project_id%"
                - keyFilePath: "%google_cloud_storage_media.gcs.key_file_path%"
    
  7. Update the database schema:

    php bin/console doctrine:schema:update --force
    
  8. Add Dropzone.js and CSS to your admin panel:

    <link rel="stylesheet" href="{{ asset('bundles/googlecloudstoragemedia/css/dropzone.min.css') }}" />
    <script src="{{ asset('bundles/googlecloudstoragemedia/js/dropzone.min.js') }}"></script>
    
  9. Add Twig form theme in config/packages/twig.yaml:

    twig:
        form_themes:
            - '@GoogleCloudStorageMedia/form/fields.html.twig'
    
  10. Register routes in config/routes.yaml:

    media:
        resource: '@GoogleCloudStorageMediaBundle/Controller/'
        type: attribute
    

First Use Case

Create a form type to upload media:

// src/Form/Type/PostType.php
namespace App\Form\Type;

use AppVerk\GoogleCloudStorageMediaBundle\Form\Type\MediaType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;

class PostType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder->add('image', MediaType::class);
    }
}

Render the form in Twig and display the uploaded media:

{{ form_start(form) }}
    {{ form_widget(form) }}
    <button type="submit">Submit</button>
{{ form_end(form) }}

<img src="{{ post.image|media }}" />

Implementation Patterns

Workflow: File Upload and Storage

  1. Form Submission:

    • Use MediaType in your form to handle file uploads.
    • The bundle automatically validates the file against configured allowed_mime_types and max_file_size.
  2. Entity Management:

    • The Media entity is saved to the database with metadata (filename, mime type, size, etc.).
    • The actual file is uploaded to Google Cloud Storage (GCS) using Flysystem.
  3. Retrieving Files:

    • Use the Twig helper |media to generate the URL for the uploaded file:
      <img src="{{ mediaObject|media }}" />
      

Integration with Existing Systems

  1. Custom Validation Groups:

    • Define validation groups in google_cloud_storage_media.yaml:
      google_cloud_storage_media:
          groups:
              documents:
                  allowed_mime_types: ["application/pdf", "application/docx"]
                  max_file_size: 10000000
      
    • Apply the group in your form:
      $builder->add('document', MediaType::class, ['group' => 'documents']);
      
  2. Streaming and Reading Files:

    • Use the StorageService to stream or read files:
      use AppVerk\GoogleCloudStorageMediaBundle\Service\v2\StorageService;
      
      class SomeService {
          public function __construct(private StorageService $storageService) {}
      
          public function streamFile(Media $media) {
              return $this->storageService->readStream($media);
          }
      }
      
  3. Custom Naming Strategy:

    • Implement NamerInterface to customize how files are named in GCS:
      use AppVerk\GoogleCloudStorageMediaBundle\Namer\NamerInterface;
      
      class CustomNamer implements NamerInterface {
          public function generateName(Media $media): string {
              return 'custom_prefix_' . uniqid() . '.' . $media->getMimeType();
          }
      }
      
    • Configure in google_cloud_storage_media.yaml:
      google_cloud_storage_media:
          namer: "App\\Namer\\CustomNamer"
      
  4. Event Listeners:

    • Listen to media events (e.g., MediaUploadEvent) to perform custom actions post-upload:
      use AppVerk\GoogleCloudStorageMediaBundle\Event\MediaUploadEvent;
      use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
      
      class MediaUploadListener {
          #[AsEventListener(event: MediaUploadEvent::class, method: 'onMediaUpload')]
          public function onMediaUpload(MediaUploadEvent $event) {
              // Custom logic after upload
          }
      }
      

Best Practices

  • Use Groups for Validation: Leverage validation groups to handle different file types (e.g., images vs. documents) with distinct rules.
  • Leverage Flysystem: Utilize Flysystem’s capabilities (e.g., streaming, metadata) for advanced file operations.
  • Customize URLs: Use GoogleObjectUrlRetriever for signed URLs or LocalObjectUrlRetriever for public URLs.
  • Environment-Specific Config: Use Symfony’s parameter system to manage GCS credentials and bucket names across environments.

Gotchas and Tips

Pitfalls

  1. Configuration Errors:

    • Issue: Forgetting to configure filesystem_url_retriever or using an incorrect retriever (e.g., LocalObjectUrlRetriever for GCS).
    • Fix: Ensure filesystem_url_retriever matches your storage setup (use GoogleObjectUrlRetriever for GCS):
      google_cloud_storage_media:
          filesystem_url_retriever: 'AppVerk\GoogleCloudStorageMediaBundle\Flysystem\Retriever\GoogleObjectUrlRetriever'
      
  2. Key File Path:

    • Issue: Incorrect key_file_path in google_cloud_storage_media.yaml or services.yaml causing authentication failures.
    • Fix: Verify the path is absolute and points to a valid service account JSON key file:
      google_cloud_storage_media:
          gcs:
              key_file_path: "%kernel.project_dir%/config/gcs-key.json"
      
  3. Mime Type Validation:

    • Issue: Files are rejected even though their mime types are in allowed_mime_types.
    • Fix: Ensure the bundle’s mime type validation aligns with the actual file mime types (some browsers may send incorrect mime types). Use a custom validator if needed:
      use Symfony\Component\Validator\Constraints\File;
      
      $builder->add('file', MediaType::class, [
          'constraints' => [
              new File([
                  'maxSize' => '10M',
                  'mimeTypes' => ['image/jpeg', 'image/png'],
                  'mimeTypesMessage' => 'Please upload a valid image (JPEG or PNG).',
              ])
          ]
      ]);
      
  4. Flysystem Adapter:

    • Issue: Files fail to upload with errors like "Adapter not found."
    • Fix: Ensure the Flysystem adapter is correctly configured in flysystem.yaml and the service is autowired:
      flysystem:
          storages:
              default.storage:
                  adapter: 'gcs'  # Not 'gcloud'; use the correct adapter name
      
  5. Database Schema:

    • Issue: Schema update fails or
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.
emuniq/filament-browser-notifications
syriable/filament-translator
hungnm28/livewire-form
wenprise/eloquent
crudly/encrypted
fadion/bouncy
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony
clementtalleu/easyadmin-markdown-bundle
codeflextech/permission-manager
karnoweb/livewire-datepicker
sayedenam/sayed-dashboard
milito/query-filter
apiboxsym/user-bundle
apiboxsym/health-check-bundle
jayeshmepani/jpl-moshier-ephemeris-php
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui