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 Laravel Package

abc/api-problem

Lightweight PHP library for representing API errors using RFC 7807 “Problem Details for HTTP APIs”. Create ApiProblem instances with type, title, status, detail, and instance, then serialize to JSON for consistent error responses.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require abc/api-problem
    

    Add the namespace to your composer.json autoload or use use Abc\ApiProblem; directly.

  2. First Use Case: Return a standardized API error response in a Laravel controller:

    use Abc\ApiProblem;
    use Symfony\Component\HttpFoundation\Response;
    
    public function show($id)
    {
        if (!Resource::find($id)) {
            $problem = new ApiProblem(
                url('/api/resource'),
                'Resource Not Found',
                Response::HTTP_NOT_FOUND,
                "Resource with ID {$id} not found"
            );
            return response()->json($problem->toJson(), 404);
        }
        // ... success logic
    }
    
  3. Where to Look First:

    • RFC 7807: Understand the structure of API Problems (spec).
    • ApiProblem class: Focus on its constructor and toJson() method.
    • Laravel Integration: Check how to extend Laravel’s Response or middleware for consistency.

Implementation Patterns

Core Workflows

  1. Error Handling Middleware: Catch exceptions and convert them to ApiProblem responses:

    use Abc\ApiProblem;
    use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
    
    public function handle(NotFoundHttpException $e, $next)
    {
        $problem = new ApiProblem(
            url('/api'),
            'Not Found',
            404,
            $e->getMessage()
        );
        return response()->json($problem->toJson(), 404);
    }
    
  2. Validation Errors: Transform Laravel’s Validator errors into ApiProblem:

    $validator = Validator::make($request->all(), [...]);
    if ($validator->fails()) {
        $problem = new ApiProblem(
            url('/api/validate'),
            'Validation Error',
            422,
            $validator->errors()->first()
        );
        return response()->json($problem->toJson(), 422);
    }
    
  3. Extending with Custom Fields: Add RFC-compliant extensions (e.g., instance, about, or custom fields):

    $problem = new ApiProblem(
        url('/api/resource'),
        'Conflict',
        409,
        'Resource already exists',
        null,
        ['instance' => url("/api/resource/{$id}")]
    );
    
  4. API Versioning: Use the type field to distinguish between API versions:

    $problem = new ApiProblem(
        url('/api/v1/resource'),
        'Unsupported Media Type',
        415,
        'Only JSON is supported',
        null,
        ['type' => 'about:schemas.org/errors/v1/unsupported-media-type']
    );
    

Integration Tips

  • Laravel Responses: Wrap ApiProblem in a helper for consistency:
    if ($error) {
        return apiProblemResponse($error, 400, 'Bad Request');
    }
    
  • Testing: Mock ApiProblem in unit tests to verify error responses:
    $this->expectException(ApiProblem::class)
         ->expectJson($problem->toJson());
    
  • Documentation: Link to RFC 7807 in your API docs to explain error formats.

Gotchas and Tips

Pitfalls

  1. RFC Compliance:

    • The type field must be a URI (e.g., about:schemas.org/errors/resource-not-found).
    • Omit optional fields (e.g., instance, title, detail) if unused, but ensure required fields (type, status, detail) are present.
  2. JSON Serialization:

    • The toJson() method returns a string. Parse it with json_decode() if further manipulation is needed:
      $data = json_decode($problem->toJson(), true);
      
  3. Status Codes:

    • Laravel’s Response constants (e.g., Response::HTTP_NOT_FOUND) are preferred over raw integers for clarity.
  4. Localization:

    • The title and detail fields are not automatically translated. Localize them manually or use Laravel’s __() helper:
      $problem = new ApiProblem(
          url('/api/resource'),
          __('errors.resource_not_found.title'),
          404,
          __('errors.resource_not_found.detail', ['id' => $id])
      );
      

Debugging

  • Missing Fields: Use var_dump($problem) to inspect the object structure before calling toJson().
  • Invalid URIs: Validate type and instance fields with filter_var($uri, FILTER_VALIDATE_URL).
  • Middleware Conflicts: Ensure middleware doesn’t modify the response after ApiProblem is created (e.g., avoid app->abort() in middleware).

Extension Points

  1. Custom Problem Types: Extend the ApiProblem class to add domain-specific fields:

    class CustomProblem extends ApiProblem {
        public function __construct($type, $status, $detail, $customField) {
            parent::__construct($type, $status, $detail);
            $this->customField = $customField;
        }
    }
    
  2. Laravel Service Provider: Bind ApiProblem to the container for dependency injection:

    $this->app->bind(ApiProblem::class, function () {
        return new ApiProblem(...);
    });
    
  3. API Problem Factory: Create a factory class to standardize problem creation:

    class ProblemFactory {
        public static function notFound($id) {
            return new ApiProblem(
                url('/api/resource'),
                'Not Found',
                404,
                "Resource {$id} not found"
            );
        }
    }
    
  4. Logging: Log ApiProblem instances for analytics or debugging:

    \Log::error('API Problem', [
        'type' => $problem->type,
        'status' => $problem->status,
        'detail' => $problem->detail,
        'instance' => $problem->instance ?? null,
    ]);
    
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.
codifyo/ts-generator-bundle
andydefer/laravel-cluster
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