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

Api Problem Bundle Laravel Package

phpro/api-problem-bundle

Symfony bundle that turns exceptions into RFC7807 Problem Details responses (application/problem+json). Listens for ApiProblemException/HttpException/Security exceptions and converts them to standardized JSON errors based on phpro/api-problem, with support for custom transformers.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require phpro/api-problem-bundle
    

    Add to config/app.php (Laravel) or config/bundles.php (Symfony):

    // Laravel (no XML config support in 1.12.1+)
    Phpro\ApiProblemBundle\PhproApiProblemBundle::class => ['all' => true],
    
  2. First Use Case Throw a problem in a controller:

    use Phpro\ApiProblemBundle\Exception\ProblemException;
    
    public function show(User $user)
    {
        if (!$user->isActive()) {
            throw new ProblemException('User is inactive', 403, [
                'type' => 'https://example.com/probs/inactive-user',
                'title' => 'Inactive User',
                'detail' => 'The requested user is inactive',
            ]);
        }
        return $user;
    }
    
  3. Where to Look First

    • ProblemException: Core class for RFC7807-compliant errors (now XML-config-free).
    • ProblemFactory: Customize default problem structures via PHP config.
    • Middleware: Laravel-specific exception handling (Symfony listeners are deprecated for config).

Implementation Patterns

Common Workflows

  1. Validation Errors Use ProblemException with validation_errors type:

    throw new ProblemException('Validation failed', 422, [
        'type' => 'https://example.com/probs/validation-error',
        'errors' => ['email' => ['The email field is required.']],
    ]);
    
  2. Global Exception Handling (Laravel) Replace Symfony listeners with middleware (1.12.1+ recommended):

    // app/Http/Middleware/HandleApiProblems.php
    public function handle($request, Closure $next)
    {
        try {
            return $next($request);
        } catch (ProblemException $e) {
            return response()->json($e->getProblem(), $e->getStatusCode());
        }
    }
    
  3. Custom Problem Types Register factories in config/api_problem.php (no XML support):

    'factories' => [
        'auth_error' => [
            'class' => \App\Problem\AuthProblemFactory::class,
            'status' => 401,
            'type' => 'https://example.com/probs/auth-error',
        ],
    ],
    
  4. Linking Problems Add links for API documentation:

    throw new ProblemException('Rate limit exceeded', 429, [
        'links' => [
            ['href' => '/docs/rate-limits', 'rel' => 'documentation'],
        ],
    ]);
    

Integration Tips

  • Laravel Validation: Use ProblemException in HandleInvalidUserInput:
    public function invalid($request, $validator, $customMessages)
    {
        throw new ProblemException('Validation failed', 422, [
            'errors' => $validator->errors()->toArray(),
        ]);
    }
    
  • OpenAPI/Swagger: Reference problem types:
    components:
      schemas:
        Problem:
          $ref: 'https://tools.ietf.org/html/rfc7807'
    

Gotchas and Tips

Pitfalls

  1. XML Config Removed

    • Breaking: XML configuration (e.g., api_problem.xml) is dropped in 1.12.1. Use PHP config (config/api_problem.php) only.
    • Fix: Migrate any XML configs to PHP arrays:
      // Old (XML)
      <problem type="auth_error" status="401" />
      
      // New (PHP)
      'factories' => [
          'auth_error' => [
              'status' => 401,
              'type' => 'https://example.com/probs/auth-error',
          ],
      ],
      
  2. Symfony Listeners Deprecated

    • The ProblemResponseListener is Symfony-specific. In Laravel, always use middleware for exception handling.
  3. Status Code Defaults

    • ProblemException defaults to 500 if no status is provided. Always specify:
      // ❌ Avoid
      throw new ProblemException('Error');
      
      // ✅ Correct
      throw new ProblemException('Error', 404);
      
  4. Type URIs Must Be Absolute

    • Use full URIs (e.g., https://example.com/probs/...) to avoid collisions in multi-environment APIs.

Debugging

  • Missing Headers: Ensure Content-Type: application/problem+json is set. Laravel’s response()->json() handles this automatically.
  • Factory Loading: Verify custom factories are autoloaded and registered in config/api_problem.php.
  • Development Debugging: Use Problem::create()->withDebug() to include stack traces:
    Problem::create('Oops')
        ->setStatus(500)
        ->withDebug()
        ->throw();
    

Extension Points

  1. Custom Problem Classes Extend Problem for domain logic:

    class PaymentProblem extends Problem
    {
        public function setTransactionId(string $id): self
        {
            $this->set('transaction_id', $id);
            return $this;
        }
    }
    
  2. Middleware for Global Metadata Add fields to all problems:

    public function handle($request, Closure $next)
    {
        $response = $next($request);
        if ($response->exception instanceof ProblemException) {
            $problem = $response->exception->getProblem();
            $problem->set('request_id', $request->header('X-Request-ID'));
            $response->setContent(json_encode($problem));
        }
        return $response;
    }
    
  3. Testing Problems Mock problems in tests:

    $problem = Problem::create('Test')
        ->setStatus(400)
        ->setType('https://example.com/probs/test');
    
    $this->expectException(ProblemException::class);
    $this->expectExceptionMessage($problem->getDetail());
    
  4. Problem Transformers Convert problems to other formats (e.g., XML) via custom middleware or listeners.

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.
calmfox/watch-sylius
damienfern/grpc-symfony-bundle
atoolo/index-bundle
atoolo/genai-bundle
coprotoai/laravel-ticket
davidjln/llm-carbon-bundle
cryonighter/valid-request-bundle
coolms/taxonomy-bundle
coolms/field-bundle
articulate-orm/symfony
aaix/laravel-tall-architect
ephoto/akeneo-connector
emmanuelballery/eb-plantumlbundle
emielburgman/symfony-visitor-beacon
emielburgman/symfony-visit-storage
emielburgman/symfony-security-headers
emielburgman/symfony-log-viewer
emarref/xdebug-bundle
emarref/pubnub-bundle
elriseio/finance-money-bundle