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

Elissa Bundle Laravel Package

carthage-software/elissa-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require carthage-software/elissa-bundle
    

    Add the bundle to config/bundles.php:

    CarthageSoftware\ElissaBundle\ElissaBundle::class => ['all' => true],
    
  2. First Use Case: Inject PSR-7 factories into a service (no extra config needed):

    use Psr\Http\Message\RequestFactoryInterface;
    use Psr\Http\Message\ResponseFactoryInterface;
    
    class MyService {
        public function __construct(
            private RequestFactoryInterface $requestFactory,
            private ResponseFactoryInterface $responseFactory
        ) {}
    }
    
  3. Auto-Tagged PSR-15 Handlers: Create a class implementing \Psr\Http\Server\RequestHandlerInterface and tag it as a psr15.handler service:

    #[Tag('psr15.handler')]
    class MyHandler implements RequestHandlerInterface {
        public function handle(ServerRequestInterface $request): ResponseInterface {
            return new Response();
        }
    }
    

Implementation Patterns

PSR-7 Factories Integration

  • Dependency Injection: All PSR-7 factories (StreamFactoryInterface, RequestFactoryInterface, etc.) are auto-configured and injectable via Symfony’s DI container.

    use Psr\Http\Message\UploadedFileFactoryInterface;
    
    class FileUploader {
        public function __construct(
            private UploadedFileFactoryInterface $uploadedFileFactory
        ) {}
    }
    
  • Creating Requests/Responses:

    $request = $this->requestFactory->createRequest('GET', '/');
    $response = $this->responseFactory->createResponse(200);
    

PSR-15 Handlers and Middleware

  • Auto-Tagging: Annotate handlers with #[Tag('psr15.handler')] to register them automatically.

    #[Tag('psr15.handler', ['priority' => 10])] // Optional: Set priority
    class AuthHandler implements RequestHandlerInterface {}
    
  • Middleware Integration:

    • Tag middleware with #[Tag('psr15.middleware')]:
      #[Tag('psr15.middleware')]
      class LoggingMiddleware implements MiddlewareInterface {
          public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface {
              // ...
          }
      }
      
    • Third-Party Middleware: Use Symfony’s autoconfigure to auto-load middleware from vendor packages (e.g., nelmio/cors-bundle).
  • Stack Composition: Leverage Symfony’s psr15.middleware and psr15.handler tags to compose middleware stacks declaratively. Example in config/services.yaml:

    services:
        App\Middleware\FirstMiddleware:
            tags: ['psr15.middleware']
        App\Middleware\SecondMiddleware:
            tags: ['psr15.middleware']
    

Symfony Controller Integration

  • PSR-15 Handlers as Controllers: Tag a PSR-15 handler to replace Symfony’s default controller resolution:
    #[Tag('psr15.handler', ['priority' => 20])]
    class ApiHandler implements RequestHandlerInterface {
        public function handle(ServerRequestInterface $request): ResponseInterface {
            return new JsonResponse(['data' => 'hello']);
        }
    }
    
    • Route Matching: Ensure routes are matched via Symfony’s router (e.g., #[Route('/api')] on a controller that delegates to the PSR-15 handler).

Gotchas and Tips

Pitfalls

  1. Priority Conflicts:

    • PSR-15 handlers/middleware with the same priority may execute in an undefined order. Explicitly set priorities:
      #[Tag('psr15.middleware', ['priority' => 5])]
      
  2. Symfony Router vs. PSR-15:

    • If using PSR-15 handlers as controllers, ensure Symfony’s router doesn’t conflict. Disable Symfony’s controller resolver if needed:
      # config/packages/framework.yaml
      framework:
          http_method_override: false
          router:
              strict_requirements: ~
      
  3. Stream Detachment:

    • Detach streams explicitly when done to avoid memory leaks:
      $stream = $this->streamFactory->createStream();
      // ... use stream ...
      $stream->detach();
      
  4. Circular Dependencies:

    • Avoid circular dependencies between PSR-15 handlers/middleware. Use interfaces or abstract classes for shared logic.

Debugging

  • Middleware/Handler Order: Use Symfony’s debug:container to inspect tagged services:

    php bin/console debug:container --tag=psr15.middleware
    
  • Request/Response Inspection: Log requests/responses in middleware for debugging:

    #[Tag('psr15.middleware')]
    class DebugMiddleware implements MiddlewareInterface {
        public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface {
            error_log($request->getUri());
            $response = $handler->handle($request);
            error_log($response->getStatusCode());
            return $response;
        }
    }
    

Tips

  1. Reuse PSR-7 Objects:

    • Reuse factories to avoid redundant object creation:
      $this->responseFactory->createResponse(200)
          ->withHeader('Content-Type', 'application/json');
      
  2. Custom Factories:

    • Extend default factories for project-specific needs:
      class CustomStreamFactory implements StreamFactoryInterface {
          public function createStream(string $content = ''): StreamInterface {
              return new CustomStream($content);
          }
      }
      
      Register as a service:
      services:
          Psr\Http\Message\StreamFactoryInterface: '@App\Service\CustomStreamFactory'
      
  3. Performance:

    • For high-traffic apps, pool PSR-7 objects (e.g., responses) to reduce GC overhead:
      $responsePool = new ResponsePool($this->responseFactory);
      
  4. Testing:

    • Mock PSR-7 factories in tests:
      $this->mockBuilder()
          ->disableOriginal()
          ->getMockBuilder(StreamFactoryInterface::class)
          ->disableOriginalConstructor()
          ->getMock();
      
  5. Symfony 6+:

    • Use #[AsService] and #[Tag] attributes for cleaner service definitions:
      #[AsService(tag: 'psr15.middleware')]
      class MyMiddleware implements MiddlewareInterface {}
      
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
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
spatie/mailcoach-vapor