{"id":39441548,"url":"https://github.com/juliomotol/lapiv","last_synced_at":"2026-01-18T04:21:16.036Z","repository":{"id":37669724,"uuid":"295691801","full_name":"juliomotol/lapiv","owner":"juliomotol","description":"API versioning for Laravel made easy","archived":false,"fork":false,"pushed_at":"2024-04-02T14:32:41.000Z","size":72,"stargazers_count":23,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-12-08T05:25:42.772Z","etag":null,"topics":["api","api-versioning","laravel"],"latest_commit_sha":null,"homepage":"","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/juliomotol.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-09-15T10:24:58.000Z","updated_at":"2025-04-25T22:23:08.000Z","dependencies_parsed_at":"2022-08-18T04:45:55.687Z","dependency_job_id":null,"html_url":"https://github.com/juliomotol/lapiv","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/juliomotol/lapiv","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juliomotol%2Flapiv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juliomotol%2Flapiv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juliomotol%2Flapiv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juliomotol%2Flapiv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/juliomotol","download_url":"https://codeload.github.com/juliomotol/lapiv/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juliomotol%2Flapiv/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28529501,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-18T00:39:45.795Z","status":"online","status_checked_at":"2026-01-18T02:00:07.578Z","response_time":98,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["api","api-versioning","laravel"],"created_at":"2026-01-18T04:21:15.442Z","updated_at":"2026-01-18T04:21:16.024Z","avatar_url":"https://github.com/juliomotol.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Lapiv\n\n[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square)](LICENSE.md)\n[![Latest Version on Packagist](https://img.shields.io/packagist/v/juliomotol/lapiv.svg?style=flat-square)](https://packagist.org/packages/juliomotol/lapiv)\n[![Total Downloads](https://img.shields.io/packagist/dt/juliomotol/lapiv.svg?style=flat-square)](https://packagist.org/packages/juliomotol/lapiv)\n\n\u003e ## This package is **feature locked** \n\u003e\n\u003e With the recent developments in PHP, Laravel and its community of packages, it has been easier than ever to manage routes for versioned APIs.\n\u003e\n\u003e We have found better ways to do what this package does in a much cleaner way. We suggest for you to take a look at [spatie/laravel-route-attributes](https://github.com/spatie/laravel-route-attributes) or [spatie/laravel-route-discovery](https://spatie.be/docs/laravel-route-discovery/v1/introduction).\n\u003e\n\u003e With that, we will still continue to provide support for future PHP/Laravel updates until any major breakage.\n\n\nA Small Laravel package for a simple and easy API versioning.\n\nLapiv simply stands for (L)aravel (API) (V)ersioning.\n\n## Installation\n\nYou can install the package via composer:\n\n```bash\ncomposer require juliomotol/lapiv\n```\n\n## Config\n\n| Key                      | Default Value  | Description                                                                                       |\n| ------------------------ | -------------- | ------------------------------------------------------------------------------------------------- |\n| default                  | `\"uri\"`        | The versioning method. Supports: \"uri\", \"query_string\".                                           |\n| methods.uri.prefix       | `\"v{version}\"` | The prefix for uri based versioning. (NOTE: Always include the \"version\" parameter in the prefix) |\n| methods.query_string.key | `\"v\"`          | The query string key name for determining the version                                             |\n\n\u003e If you want to make changes in the configuration you can publish the config file using:\n\u003e\n\u003e ```\n\u003e php artisan vendor:publish --provider=\"JulioMotol\\Lapiv\\LapivServiceProvider\"\n\u003e ```\n\n## Setup\n\nNow the juicy part, we'll walk you through how to setup versioned Controllers.\n\n### `FooV1Controller.php`\n\nThis is very much like your standard controller. Nothing special here really. All action methods must be declared here e.g. `index`, `create`, `show`, etc.\n\n```php\nnamespace App\\Http\\Controllers\\Api\\Foo;\n\nuse App\\Http\\Controllers\\Controller;\n\nclass FooV1Controller extends Controller\n{\n    public function index()\n    {\n        return response()-\u003ejson(['message' =\u003e 'This is Foo V1']);\n    }\n}\n```\n\n### `FooGatewayController.php`\n\nNow the good stuff. This controller **MUST** extend `\\JulioMotol\\Lapiv\\GatewayController` in order for this whole thing to work. This will be in charge of dispatching the requests based on the requested version. Let's take a look inside.\n\n```php\nnamespace App\\Http\\Controllers\\Api\\Foo;\n\nuse JulioMotol\\Lapiv\\GatewayController;\n\nclass FooGatewayController extends GatewayController\n{\n    protected array $apiControllers = [\n        FooV1Controller::class, // The first version of you API endpoint.\n        // Preceeding version implementations...\n    ];\n}\n```\n\n\u003e The order in `$apiControllers` is critical. The first controller declared will be our `v1`, then will be `v2`, and so on.\n\n### Routing\n\nWith our controllers ready to go, lets create our route. Go to `routes/api.php`.\n\n```php\n/**\n * Registers a versioned API endpoint.\n *\n * Router::lapiv($callback = null)\n *\n * @param $callback\n */\nRoute::lapiv(function () {\n    Route::get('/foo', [FooGatewayController::class, 'index']);\n    Route::get('/bar', [BarGatewayController::class, 'index']);\n});\n```\n\nNotice we didn't point to the `[FooV1Controller::class, 'index']`. As we've said, the `FooGatewayController` will be doing much of the heavy work, so we'll just call that instead.\n\nWhen you run `php artisan route:list` you should see this.\n\n| Method    | URI                | Action                                              |\n| --------- | ------------------ | --------------------------------------------------- |\n| GET\\|HEAD | api/v{version}/foo | App\\Http\\Controllers\\Api\\FooGatewayController@index |\n| GET\\|HEAD | api/v{version}/bar | App\\Http\\Controllers\\Api\\BarGatewayController@index |\n\nNow, when we try to go to `/api/v1/foo`, it should be handled by `FooV1Controller`.\n\n### Bumping a version\n\nWhen your ready to bump your API version to v2, Simply add a new `FooV2Controller` and dont forget to add that to `FooGatewayController`'s `$apiControllers`.\n\n## Versioning Methods\n\nThis package supports 2 types of API Versioning methods, `uri` and `query_string`.\n\n### `uri` Method\n\nThis is the default of the versioning method. Here, the API version will be declared in the uri path (e.g. `example.com/api/v1/foo`).\n\nIn the config, you can change the prefix for the uri.\n\n```php\n\"methods\" =\u003e [\n    \"uri\" =\u003e [\n        \"prefix\" =\u003e '/version-{version}' // will generate `example.com/api/version-1/foo`\n    ]\n]\n```\n\n\u003e Don't forget to add the `version` parameter in the prefix.\n\n### `query_string` Method\n\nHere, the API version will be declared in the query string (e.g. `example.com/api/foo?v=1`).\n\nIn the config, you can change the query string key.\n\n```php\n\"methods\" =\u003e [\n    \"query_string\" =\u003e [\n        \"key\" =\u003e 'version' // will accept `example.com/api/foo?version=1`\n    ]\n]\n```\n\n### Want to handle your own versioning method?\n\nYou can define how you want to handle versioning your APIs by extending `JulioMotol\\Lapiv\\Drivers\\BaseDriver`:\n\n```php\nuse JulioMotol\\Lapiv\\Drivers\\BaseDriver;\nuse Illuminate\\Support\\Facades\\Request;\n\nclass HeaderDriver extends BaseDriver\n{\n    public function getVersion(): string|int\n    {\n        $headerValue = Request::header($methodOptions['key']) ?? null;\n        $matches = [];\n\n        preg_match('/application\\/vnd\\.my_application\\.v(\\d*)\\+json/', $headerValue, $matches);\n\n        return $matches[1] ?? null;\n    }\n}\n```\n\n\u003e You can also handle routing by overriding the `routeGroup()` method in the `BaseDriver`.\n\nThen add your new API driver in your `AppServiceProvider::boot()`:\n\n```php\n\nclass AppServiceProvider extends ServiceProvider\n{\n    public function boot()\n    {\n        ApiVersioningManager::extend('header', fn () =\u003e new HeaderDriver());\n    }\n}\n```\n\nAnd finally, use your new driver in the `config/lapiv.php`\n```php \n    'default' =\u003e 'header', // the value here will be the first parameter you've set in ApiVersioningManager::extend()\n```\n\n## Changelog\n\nPlease see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.\n\n## Contributing\n\nPlease see [CONTRIBUTING](CONTRIBUTING.md) for details.\n\n### Security\n\nIf you discover any security related issues, please email julio.motol89@gmail.com instead of using the issue tracker.\n\n## Credits\n\n-   [Julio Motol](https://github.com/juliomotol)\n-   [All Contributors](../../contributors)\n\n## License\n\nThe MIT License (MIT). Please see [License File](LICENSE.md) for more information.\n\n## Laravel Package Boilerplate\n\nThis package was generated using the [Laravel Package Boilerplate](https://laravelpackageboilerplate.com).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjuliomotol%2Flapiv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjuliomotol%2Flapiv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjuliomotol%2Flapiv/lists"}