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

Rest Problem Bundle Laravel Package

alterway/rest-problem-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require alterway/rest-problem-bundle
    

    Enable the bundle in config/bundles.php:

    return [
        // ...
        Alterway\Bundle\RestProblemBundle\AwRestProblemBundle::class => ['all' => true],
    ];
    
  2. First Use Case: Return a ProblemResponse for invalid form submissions:

    use Alterway\Bundle\RestProblemBundle\Response\ProblemResponse;
    use Alterway\Bundle\RestProblemBundle\Problem;
    
    public function submitAction(Request $request)
    {
        $form = $this->createForm(YourFormType::class);
        $form->handleRequest($request);
    
        if (!$form->isValid()) {
            $problem = new Problem\InvalidQueryForm($form);
            return new ProblemResponse($problem, Response::HTTP_BAD_REQUEST);
        }
    }
    

Key Files to Review

  • src/Problem/ (Default problem types like InvalidQuery, InvalidQueryForm).
  • src/Response/ProblemResponse.php (Core response class).
  • src/Controller/Annotations/Problem.php (Annotation for automatic problem handling).

Implementation Patterns

Common Workflows

  1. Manual Problem Responses:

    // For custom errors (e.g., 404 with details)
    $problem = new Problem\CustomProblem('Resource not found', 'https://example.com/probs/resource-not-found');
    return new ProblemResponse($problem, Response::HTTP_NOT_FOUND);
    
  2. Annotation-Driven Problems:

    use Alterway\Bundle\RestProblemBundle\Controller\Annotations\Problem;
    
    /**
     * @Problem
     */
    public function createAction(Request $request)
    {
        // Automatically wraps exceptions in ProblemResponse with 500 status.
    }
    
  3. Extending Problem Types: Create a custom problem class (e.g., src/Problem/ValidationProblem.php):

    namespace App\Problem;
    
    use Alterway\Bundle\RestProblemBundle\Problem\Problem;
    
    class ValidationProblem extends Problem
    {
        public function __construct(array $errors)
        {
            parent::__construct('Validation failed', 'https://example.com/probs/validation-failed');
            $this->setDetail($errors);
        }
    }
    
  4. Integration with Symfony’s Exception Listener: Override the default exception handler to use ProblemResponse:

    # config/packages/framework.yaml
    framework:
        exception_listener:
            enabled: false  # Disable Symfony's default handler
    

Integration Tips

  • API Versioning: Use the type field in problems to version your API errors (e.g., type: "https://api.example.com/v1/probs/...").
  • Logging: Log problem details for debugging:
    $this->logger->error('Problem occurred', ['problem' => $problem->toArray()]);
    
  • Testing: Mock ProblemResponse in unit tests:
    $this->assertInstanceOf(ProblemResponse::class, $response);
    $this->assertEquals(400, $response->getStatusCode());
    

Gotchas and Tips

Pitfalls

  1. Deprecated Symfony 2.x:

    • The bundle targets Symfony 2.2+. For Symfony 3/4/5, consider forking or using alternatives like nelmio/api-doc-bundle (which supports Problem Details natively).
    • Workaround: Use a compatibility layer or polyfill for missing features (e.g., ProblemResponse in Symfony 3+).
  2. Annotation Setup:

    • Forgetting to register the annotation autoloader in config/packages/annotations.yaml:
      annotations:
          autoload_resource: true
      
    • Fix: Add this to your config or manually register the loader in kernel.php.
  3. Problem Type Discovery:

    • The bundle doesn’t auto-discover custom problem types. Ensure they’re in a namespace autoloaded by Composer (e.g., src/Problem/).
  4. Header Mismatch:

    • The bundle sets Content-Type: application/api-problem+json. Some clients expect application/problem+json (RFC 7807). Override the ProblemResponse class to fix this:
      class CustomProblemResponse extends ProblemResponse
      {
          public function getContentType()
          {
              return 'application/problem+json';
          }
      }
      

Debugging Tips

  1. Inspect Problem Data: Dump the problem object to verify fields:

    $problem = new Problem\InvalidQueryForm($form);
    dump($problem->toArray()); // Check structure
    
  2. Check Status Codes: Ensure the HTTP status code matches the problem severity (e.g., 4xx for client errors, 5xx for server errors).

  3. Validate RFC Compliance: Use tools like Postman or Swagger UI to validate the Problem response structure against RFC 7807.

Extension Points

  1. Custom Problem Fields: Extend the Problem class to add custom fields (e.g., setMeta()):

    class CustomProblem extends Problem
    {
        protected $meta = [];
    
        public function setMeta(array $meta)
        {
            $this->meta = $meta;
            return $this;
        }
    
        public function toArray()
        {
            $array = parent::toArray();
            $array['meta'] = $this->meta;
            return $array;
        }
    }
    
  2. Global Problem Handling: Create a subscriber to convert exceptions to ProblemResponse:

    use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
    
    class ProblemSubscriber implements EventSubscriberInterface
    {
        public function onKernelException(GetResponseForExceptionEvent $event)
        {
            $exception = $event->getThrowable();
            $problem = new Problem\ServerError($exception);
            $event->setResponse(new ProblemResponse($problem, Response::HTTP_INTERNAL_SERVER_ERROR));
        }
    
        public static function getSubscribedEvents()
        {
            return [
                KernelEvents::EXCEPTION => 'onKernelException',
            ];
        }
    }
    
  3. Localization: Override the getTitle()/getDetail() methods to support translations:

    class LocalizedProblem extends Problem
    {
        public function getTitle()
        {
            return $this->translator->trans('problem.title', [], 'errors');
        }
    }
    
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.
comsave/common
alecsammon/php-raml-parser
chrome-php/wrench
lendable/composer-license-checker
typhoon/reflection
mesilov/moneyphp-percentage
mike42/gfx-php
bookdown/themes
aura/view
aura/html
aura/cli
povils/phpmnd
nayjest/manipulator
omnipay/tests
psr-mock/http-message-implementation
psr-mock/http-factory-implementation
psr-mock/http-client-implementation
voku/email-check
voku/urlify
rtheunissen/guzzle-log-middleware