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

View Bundle Laravel Package

chamber-orchestra/view-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Install the Bundle:

    composer require chamber-orchestra/view-bundle
    

    Add to config/bundles.php:

    return [
        // ...
        ChamberOrchestra\ViewBundle\ChamberOrchestraViewBundle::class => ['all' => true],
    ];
    
  2. First Use Case: Typed JSON Response Replace raw JsonResponse in controllers with ViewInterface:

    use ChamberOrchestra\ViewBundle\View\ViewInterface;
    use ChamberOrchestra\ViewBundle\View\DataView;
    
    public function showUserAction(User $user): ViewInterface
    {
        return new DataView($user, 200, ['Content-Type' => 'application/json']);
    }
    

    The bundle auto-serializes the object to JSON, stripping null values by default.

  3. Key Files to Explore:

    • src/View/DataView.php: Core view class.
    • src/Attribute/: Attributes for customizing serialization (e.g., @View\Expose, @View\Hide).
    • src/Serializer/: Custom serializer logic.

Implementation Patterns

1. Controller Integration

  • Return ViewInterface instead of JsonResponse for consistent API responses.
  • Use Attributes to control serialization:
    #[View\Expose]
    #[View\As("full_name")]
    public function getFullName(): string { ... }
    
    #[View\Hide]
    public ?string $sensitiveData;
    
  • Leverage Collections:
    return new DataView($user->posts, 200, [], PostView::class);
    
    The bundle auto-maps collections to arrays of views.

2. Custom View Classes

  • Extend AbstractView for reusable view logic:
    class UserView extends AbstractView
    {
        public function __construct(private User $user) {}
    
        public function toArray(): array
        {
            return [
                'id' => $this->user->id,
                'name' => $this->user->name,
                // Auto-stripped nulls handled by parent
            ];
        }
    }
    

3. Cache Warming

  • Pre-generate serializer caches in bootstrap.php:
    $kernel = new AppKernel();
    $kernel->boot();
    $cache = PropertyAccessor::createCache();
    $cache->warmup();
    
  • Run during deployment or via a Symfony command.

4. Event Subscribers

  • Hook into kernel.response to transform responses:
    # config/services.yaml
    ChamberOrchestra\ViewBundle\EventSubscriber\ViewSubscriber:
        tags: ['kernel.event_subscriber']
    
  • Automatically converts ViewInterface to JsonResponse.

5. Dynamic Property Binding

  • Use BindUtils for runtime property mapping:
    use ChamberOrchestra\ViewBundle\Utils\BindUtils;
    
    $data = BindUtils::bind($user, [
        'name' => 'full_name',
        'posts' => ['title', 'published_at'],
    ]);
    

Gotchas and Tips

Pitfalls

  1. Cache Invalidation:

    • Clear caches (cache:clear) after adding new attributes or view classes.
    • Debugging tip: Set APP_DEBUG=true to bypass cache and test live serialization.
  2. Circular References:

    • Avoid bidirectional relationships (e.g., User->posts and Post->author) without explicit breaking logic:
      #[View\Expose]
      #[View\CircularReference]
      public function getAuthor(): ?User { ... }
      
  3. Null Handling:

    • By default, null values are stripped. To preserve them:
      new DataView($user, 200, [], [], false); // Disable null stripping
      
  4. PHP 8.5+ Features:

    • Uses readonly properties and typed class constants. Downgrading requires refactoring.

Debugging Tips

  • Inspect Serialized Output:

    $view = new DataView($user);
    dump($view->toArray()); // Raw data before JSON encoding
    
  • Check Cache Warming:

    php bin/console debug:container ChamberOrchestra\ViewBundle\Serializer\ViewSerializer
    

    Verify the serializer is cached.

  • Attribute Conflicts:

    • Use #[View\Priority] to resolve attribute precedence:
      #[View\Expose(priority: 10)]
      #[View\Hide(priority: 20)]
      

Extension Points

  1. Custom Serializers:

    • Implement ViewSerializerInterface for non-standard types (e.g., DateTime formatting):
      class CustomDateSerializer implements ViewSerializerInterface
      {
          public function serialize($data, ViewContext $context): mixed
          {
              return $data->format('Y-m-d');
          }
      }
      
    • Register via Symfony DI:
      services:
          App\Serializer\CustomDateSerializer:
              tags: [chamber_orchestra.view.serializer]
      
  2. Post-Processing:

    • Use ViewEvent subscribers to modify responses:
      public function onView(ViewEvent $event): void
      {
          $event->getView()->addHeader('X-Custom', 'value');
      }
      
  3. Testing Edge Cases:

    • Test null values, circular references, and custom attributes:
      $this->assertEquals(
          ['id' => 1, 'name' => 'John'],
          (new DataView(new User(null, 'John')))->toArray()
      );
      

Performance Quirks

  • Cache Overhead: Cache warming adds ~100ms during bootstrap. Disable in dev:
    # config/packages/chamber_orchestra_view.yaml
    chamber_orchestra_view:
        cache_warming: '%kernel.debug% ? false : true'
    
  • Large Collections: Use View\Chunk for pagination:
    #[View\Chunk(size: 20)]
    public function getPosts(): array { ... }
    

```markdown
### **Config Quirks**
1. **Default Headers**:
   Override globally in `config/packages/chamber_orchestra_view.yaml`:
   ```yaml
   chamber_orchestra_view:
       default_headers:
           Cache-Control: 'public, max-age=3600'
  1. Attribute Overrides: Disable auto-stripping for specific properties:

    chamber_orchestra_view:
        attributes:
            App\Entity\User:
                - { name: 'sensitiveData', strip_null: false }
    
  2. Serializer Groups: Use Symfony’s serializer groups for conditional fields:

    #[View\Groups(['default', 'admin'])]
    public function getAdminData(): array { ... }
    

    Pass groups to DataView:

    new DataView($user, 200, [], [], [], ['admin']);
    
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.
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
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager