{"id":20310150,"url":"https://github.com/phpro/api-problem","last_synced_at":"2025-04-12T17:44:54.478Z","repository":{"id":44415140,"uuid":"139485267","full_name":"phpro/api-problem","owner":"phpro","description":"RFC7807 Problem details implementation","archived":false,"fork":false,"pushed_at":"2025-01-30T08:02:59.000Z","size":58,"stargazers_count":66,"open_issues_count":2,"forks_count":8,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-03-11T01:35:05.684Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/phpro.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-07-02T19:27:34.000Z","updated_at":"2025-01-30T08:02:34.000Z","dependencies_parsed_at":"2025-02-13T17:11:09.319Z","dependency_job_id":"bd360c5c-0e4e-4076-99a6-96d3b458e2cc","html_url":"https://github.com/phpro/api-problem","commit_stats":{"total_commits":40,"total_committers":6,"mean_commits":6.666666666666667,"dds":0.5,"last_synced_commit":"75de32a9c672178a3081d7f8ef4dbbc07c24d688"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phpro%2Fapi-problem","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phpro%2Fapi-problem/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phpro%2Fapi-problem/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phpro%2Fapi-problem/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phpro","download_url":"https://codeload.github.com/phpro/api-problem/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248609490,"owners_count":21132914,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-14T17:30:14.417Z","updated_at":"2025-04-12T17:44:54.442Z","avatar_url":"https://github.com/phpro.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Travis](https://img.shields.io/travis/phpro/api-problem/master.svg)](http://travis-ci.org/phpro/api-problem)\n[![Installs](https://img.shields.io/packagist/dt/phpro/api-problem.svg)](https://packagist.org/packages/phpro/api-problem/stats)\n[![Packagist](https://img.shields.io/packagist/v/phpro/api-problem.svg)](https://packagist.org/packages/phpro/api-problem)\n\n# Api Problem\n\nThis package provides a [RFC7807](https://tools.ietf.org/html/rfc7807) Problem details implementation.\nIt can be integrated everywhere in your code and should result in a general error response format for HTTP APis.\n\nThis package only provides a generic interface, an exception class and some built-in api problem messages.\nSince handling the exceptions is up to the framework, here is a list of known framework integrations:\n\n- **Symfony** `^4.1`: [ApiProblemBundle](https://www.github.com/phpro/api-problem-bundle)\n\n## Installation\n\n```sh\ncomposer require phpro/api-problem\n```\n\n## Usage\n\nThis package provides a general interface for creating ApiProblem value objects.\n\n```php\nuse Phpro\\ApiProblem\\Exception;\n\nthrow new ApiProblemException(\n    new HttpApiProblem(418, ['detail' =\u003e 'Did you know 4,000 people are injured by teapots every year?!'])\n);\n```\n\n### Built-in problems\n\n- General problems\n  - [ExceptionApiProblem](#exceptionapiproblem)\n  - [HttpApiProblem](#httpapiproblem)\n\n- Symfony integration problems\n  - [ValidationApiProblem](#validationapiproblem)\n\n- Http problems\n  - 400 [BadRequestProblem](#badrequestproblem)\n  - 401 [UnauthorizedProblem](#unauthorizedproblem)\n  - 403 [ForbiddenProblem](#forbiddenproblem)\n  - 404 [NotFoundProblem](#notfoundproblem)\n  - 405 [MethodNotAllowedProblem](#methodnotallowedproblem)\n  - 409 [ConflictProblem](#conflictproblem)\n  - 412 [PreconditionFailedProblem](#preconditionfailedproblem)\n  - 415 [UnsupportedMediaTypeProblem](#unsupportedmediatypeproblem)\n  - 418 [IAmATeapotProblem](#iamateapotproblem)\n  - 422 [UnprocessableEntityProblem](#unprocessableentityproblem)\n  - 423 [LockedProblem](#lockedproblem)\n  - 428 [PreconditionRequiredProblem](#preconditionrequiredproblem)\n\n#### ExceptionApiProblem\n\n*Debuggable*: The `exception` part will only be added in debug context!\n\n```php\nuse Phpro\\ApiProblem\\Http\\ExceptionApiProblem;\n\nnew ExceptionApiProblem(new \\Exception('message', 500));\n```\n\n```json\n{\n  \"status\": 500,\n  \"type\": \"http:\\/\\/www.w3.org\\/Protocols\\/rfc2616\\/rfc2616-sec10.html\",\n  \"title\": \"Internal Server Error\",\n  \"detail\": \"message\",\n  \"exception\": {\n    \"message\": \"message\",\n    \"type\": \"RuntimeException\",\n    \"code\": 500,\n    \"line\": 23,\n    \"file\": \"exception.php\",\n    \"trace\": [\n         \"#0 [internal function]: ...\",\n         \"#1 [internal function]: ...\",\n         \"#3 [internal function]: ...\",\n         \"...\"\n    ],\n    \"previous\": [\n      {\n        \"message\": \"previous\",\n        \"type\": \"InvalidArgumentException\",\n        \"code\": 0,\n        \"line\": 20,\n        \"file\": \"exception.php\",\n        \"trace\": [\n            \"#0 [internal function]: ...\",\n            \"#1 [internal function]: ...\",\n            \"#3 [internal function]: ...\",\n            \"...\"\n        ]\n      }\n    ]\n  }\n}\n````\n\n#### HttpApiProblem\n\n```php\nuse Phpro\\ApiProblem\\Http\\HttpApiProblem;\n\nnew HttpApiProblem(404, ['detail' =\u003e 'The book could not be found.']);\n```\n\n```json\n{\n    \"status\": 404,\n    \"type\": \"http:\\/\\/www.w3.org\\/Protocols\\/rfc2616\\/rfc2616-sec10.html\",\n    \"title\": \"Not found\",\n    \"detail\": \"The book could not be found.\"\n}\n````\n\n#### ValidationApiProblem\n\n```sh\ncomposer require symfony/validator:^4.1\n```\n\n```php\nuse Phpro\\ApiProblem\\Http\\ValidationApiProblem;\nuse Symfony\\Component\\Validator\\ConstraintViolation;\nuse Symfony\\Component\\Validator\\ConstraintViolationList;\n\nnew ValidationApiProblem(new ConstraintViolationList([\n    new ConstraintViolation('Invalid email', '', [], '', 'email', '', null, '8615ecd9-afcb-479a-9c78-8bcfe260cf2a'),\n]));\n```\n\n```json\n{\n    \"status\": 400,\n    \"type\": \"https:\\/\\/symfony.com\\/errors\\/validation\",\n    \"title\": \"Validation Failed\",\n    \"detail\": \"email: Invalid Email\",\n    \"violations\": [\n        {\n            \"propertyPath\": \"email\",\n            \"title\": \"Invalid email\",\n            \"type\": \"urn:uuid:8615ecd9-afcb-479a-9c78-8bcfe260cf2a\"\n        }\n    ]\n}\n````\n\n#### BadRequestProblem\n\n```php\nuse Phpro\\ApiProblem\\Http\\BadRequestProblem;\n\nnew BadRequestProblem('Bad request. Bad!.');\n```\n\n```json\n{\n    \"status\": 400,\n    \"type\": \"http:\\/\\/www.w3.org\\/Protocols\\/rfc2616\\/rfc2616-sec10.html\",\n    \"title\": \"Bad Request\",\n    \"detail\": \"Bad request. Bad!\"\n}\n````\n\n#### UnauthorizedProblem\n\n```php\nuse Phpro\\ApiProblem\\Http\\UnauthorizedProblem;\n\nnew UnauthorizedProblem('You are not authorized to access X.');\n```\n\n```json\n{\n    \"status\": 401,\n    \"type\": \"http:\\/\\/www.w3.org\\/Protocols\\/rfc2616\\/rfc2616-sec10.html\",\n    \"title\": \"Unauthorized\",\n    \"detail\": \"You are not authenticated. Please login.\"\n}\n````\n\n#### ForbiddenProblem\n\n```php\nuse Phpro\\ApiProblem\\Http\\ForbiddenProblem;\n\nnew ForbiddenProblem('Not authorized to access gold.');\n```\n\n```json\n{\n  \"status\": 403,\n  \"type\": \"http:\\/\\/www.w3.org\\/Protocols\\/rfc2616\\/rfc2616-sec10.html\",\n  \"title\": \"Forbidden\",\n  \"detail\": \"Not authorized to access gold.\"\n}\n````\n\n#### NotFoundProblem\n\n```php\nuse Phpro\\ApiProblem\\Http\\NotFoundProblem;\n\nnew NotFoundProblem('The book with ID 20 could not be found.');\n```\n\n```json\n{\n    \"status\": 404,\n    \"type\": \"http:\\/\\/www.w3.org\\/Protocols\\/rfc2616\\/rfc2616-sec10.html\",\n    \"title\": \"Not found\",\n    \"detail\": \"The book with ID 20 could not be found.\"\n}\n````\n\n#### MethodNotAllowedProblem\n\n```php\nuse Phpro\\ApiProblem\\Http\\MethodNotAllowedProblem;\n\nnew MethodNotAllowedProblem('Only POST and GET allowed.');\n```\n\n```json\n{\n    \"status\": 405,\n    \"type\": \"http:\\/\\/www.w3.org\\/Protocols\\/rfc2616\\/rfc2616-sec10.html\",\n    \"title\": \"Method Not Allowed\",\n    \"detail\": \"Only POST and GET allowed.\"\n}\n````\n\n#### ConflictProblem\n\n```php\nuse Phpro\\ApiProblem\\Http\\ConflictProblem;\nnew ConflictProblem('Duplicated key for book with ID 20.');\n```\n\n```json\n{\n    \"status\": 409,\n    \"type\": \"http:\\/\\/www.w3.org\\/Protocols\\/rfc2616\\/rfc2616-sec10.html\",\n    \"title\": \"Conflict\",\n    \"detail\": \"Duplicated key for book with ID 20.\"\n}\n````\n\n#### PreconditionFailedProblem\n\n```php\nuse Phpro\\ApiProblem\\Http\\PreconditionFailedProblem;\n\nnew PreconditionFailedProblem('Incorrect entity tag provided.');\n```\n\n```json\n{\n    \"status\": 412,\n    \"type\": \"http:\\/\\/www.w3.org\\/Protocols\\/rfc2616\\/rfc2616-sec10.html\",\n    \"title\": \"Precondition Failed\",\n    \"detail\": \"Incorrect entity tag provided.\"\n}\n````\n\n#### UnsupportedMediaTypeProblem\n\n```php\nuse Phpro\\ApiProblem\\Http\\UnsupportedMediaTypeProblem;\n\nnew UnsupportedMediaTypeProblem('Please provide valid JSON.');\n```\n\n```json\n{\n    \"status\": 415,\n    \"type\": \"http:\\/\\/www.w3.org\\/Protocols\\/rfc2616\\/rfc2616-sec10.html\",\n    \"title\": \"Unsupported Media Type\",\n    \"detail\": \"Please provide valid JSON.\"\n}\n````\n\n#### IAmATeapotProblem\n\n```php\nuse Phpro\\ApiProblem\\Http\\IAmATeapotProblem;\n\nnew IAmATeapotProblem('More tea please.');\n```\n\n```json\n{\n    \"status\": 418,\n    \"type\": \"http:\\/\\/www.w3.org\\/Protocols\\/rfc2616\\/rfc2616-sec10.html\",\n    \"title\": \"I'm a teapot\",\n    \"detail\": \"More tea please.\"\n}\n````\n\n#### UnprocessableEntityProblem\n\n```php\nuse Phpro\\ApiProblem\\Http\\UnprocessableEntityProblem;\n\nnew UnprocessableEntityProblem('Unable to process the contained instructions.');\n```\n\n```json\n{\n    \"status\": 422,\n    \"type\": \"http:\\/\\/www.w3.org\\/Protocols\\/rfc2616\\/rfc2616-sec10.html\",\n    \"title\": \"Unprocessable Entity\",\n    \"detail\": \"Unable to process the contained instructions.\"\n}\n````\n\n#### LockedProblem\n\n```php\nuse Phpro\\ApiProblem\\Http\\LockedProblem;\n\nnew LockedProblem('This door is locked.');\n```\n\n```json\n{\n    \"status\": 423,\n    \"type\": \"http:\\/\\/www.w3.org\\/Protocols\\/rfc2616\\/rfc2616-sec10.html\",\n    \"title\": \"Locked\",\n    \"detail\": \"This door is locked.\"\n}\n````\n\n#### PreconditionRequiredProblem\n\n```php\nuse Phpro\\ApiProblem\\Http\\PreconditionRequiredProblem;\n\nnew PreconditionRequiredProblem('If-match header is required.');\n```\n\n```json\n{\n    \"status\": 428,\n    \"type\": \"http:\\/\\/www.w3.org\\/Protocols\\/rfc2616\\/rfc2616-sec10.html\",\n    \"title\": \"Precondition Required\",\n    \"detail\": \"If-match header is required.\"\n}\n````\n\n### Creating your own problem\n\nCreating problem sounds scary right!?\nSince the RFC is very loose, we made the interface as easy as possible:\n\n```php\nuse Phpro\\ApiProblem\\ApiProblemInterface;\n\nclass MyProblem implements ApiProblemInterface\n{\n    public function toArray(): array\n    {\n        return [\n            'type' =\u003e 'about:blank',\n            'status' =\u003e '99',\n            'title' =\u003e 'Got 99 problems but a glitch aint one!',\n        ];\n    }\n}\n```\n\nA lot of problems will be detected in an HTTP context. Therefore, we also provided a base `HttpApiProblem` class.\nThis one will automatically fill in the type and title section based on the HTTP code.\nThe only thing you'll need to do, is add some additional data to it:\n\n```php\nuse Phpro\\ApiProblem\\Http\\HttpApiProblem;\n\nclass MyProblem extends HttpApiProblem\n{\n    public function __construct(string $details)\n    {\n        parent::__construct(500, ['details' =\u003e $details]);\n    }\n}\n```\n\nIf you want to log additional information in a debug context, it is possible to implement an additional `DebuggableApiProblemInterface`:\n\n```php\nuse Phpro\\ApiProblem\\DebuggableApiProblemInterface;\n\nclass MyProblem implements DebuggableApiProblemInterface\n{\n    public function toArray(): array\n    {\n        return [\n            'type' =\u003e 'about:blank',\n            'status' =\u003e '99',\n            'title' =\u003e 'Got 99 problems but a glitch ain\\'t one!',\n        ];\n    }\n\n    public function toDebuggableArray(): array\n    {\n        return array_merge(\n            $this-\u003etoArray(),\n            [\n                'situation' =\u003e 'If you are having code problems, I feel bad for you son',\n            ]\n        );\n    }\n}\n```\n\n## About\n\n### Submitting bugs and feature requests\n\nBugs and feature request are tracked on [GitHub](https://github.com/phpro/api-problem/issues).\nPlease take a look at our rules before [contributing your code](CONTRIBUTING).\n\n### License\n\napi-problem is licensed under the [MIT License](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphpro%2Fapi-problem","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphpro%2Fapi-problem","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphpro%2Fapi-problem/lists"}