{"id":17036789,"url":"https://github.com/mmghv/lumen-route-binding","last_synced_at":"2025-10-05T03:43:27.585Z","repository":{"id":12501592,"uuid":"72012210","full_name":"mmghv/lumen-route-binding","owner":"mmghv","description":"Adds support for route-model-binding in Lumen (Explicit, Implicit, Composite)","archived":false,"fork":false,"pushed_at":"2024-09-16T18:17:46.000Z","size":68,"stargazers_count":51,"open_issues_count":0,"forks_count":9,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-09T20:09:41.008Z","etag":null,"topics":["lumen","route-model-binding"],"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/mmghv.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"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":"2016-10-26T14:35:36.000Z","updated_at":"2024-09-16T18:14:25.000Z","dependencies_parsed_at":"2024-06-18T22:43:43.726Z","dependency_job_id":"776e96c7-a282-4bf8-aaed-87a0936ef727","html_url":"https://github.com/mmghv/lumen-route-binding","commit_stats":{"total_commits":50,"total_committers":3,"mean_commits":"16.666666666666668","dds":0.09999999999999998,"last_synced_commit":"4bd5545c1f508fcd92e889b5f694c6af27b1dca2"},"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mmghv%2Flumen-route-binding","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mmghv%2Flumen-route-binding/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mmghv%2Flumen-route-binding/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mmghv%2Flumen-route-binding/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mmghv","download_url":"https://codeload.github.com/mmghv/lumen-route-binding/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248103871,"owners_count":21048245,"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":["lumen","route-model-binding"],"created_at":"2024-10-14T08:51:59.743Z","updated_at":"2025-10-05T03:43:22.549Z","avatar_url":"https://github.com/mmghv.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Lumen Route Binding\n\n[![Build Status](https://travis-ci.org/mmghv/lumen-route-binding.svg?branch=master)](https://travis-ci.org/mmghv/lumen-route-binding)\n[![Lumen Version](https://img.shields.io/badge/Lumen-5%20--%2011-orange.svg)](https://github.com/laravel/lumen)\n[![Latest Stable Version](https://poser.pugx.org/mmghv/lumen-route-binding/v/stable)](https://packagist.org/packages/mmghv/lumen-route-binding)\n[![Total Downloads](https://poser.pugx.org/mmghv/lumen-route-binding/downloads)](https://packagist.org/packages/mmghv/lumen-route-binding)\n[![Latest Unstable Version](https://poser.pugx.org/mmghv/lumen-route-binding/v/unstable)](https://packagist.org/packages/mmghv/lumen-route-binding)\n[![License](https://poser.pugx.org/mmghv/lumen-route-binding/license)](LICENSE)\n\nThis package Adds support for `Route Model Binding` in Lumen (5 - 11).\n\n\u003e As known, Lumen doesn't support `Route Model Binding` out of the box due to the fact that Lumen doesn't use the Illuminate router that Laravel uses, Instead, It uses [FastRoute](https://github.com/nikic/FastRoute) which is much faster. With this package, We add support for the powerful `Route Model Binding` while still benefit the speed of FastRoute in Lumen.\n\n# Table of Contents\n\n  * [Installation](#installation)\n  * [Defining the bindings](#where-to-define-our-bindings)\n    * [Explicit Binding](#1-explicit-binding)\n    * [Implicit Binding](#2-implicit-binding)\n    * [Composite Binding](#3-composite-binding)\n  * [DingoAPI Integration](#dingoapi-integration)\n\n## Installation\n\n#### Using composer\n```\ncomposer require mmghv/lumen-route-binding \"^1.0\"\n```\n\n\u003e It requires\n\u003e ```\n\u003e php \u003e= 7.1\n\u003e Lumen 5 - 11\n\u003e ```\n\n#### Register the service provider\n\nIn the coming section ..\n\n\n## Usage\n\n\u003e Route model binding provides a convenient way to automatically inject the model instances directly into your routes. For example, instead of injecting a user's ID, you can inject the entire `User` model instance that matches the given ID.\n\n### Where to Define our Bindings\n\nCreate a service provider that extends the package's one and place it in `app/Providers` :\n\n```PHP\n// app/Providers/RouteBindingServiceProvider.php\n\nnamespace App\\Providers;\n\nuse mmghv\\LumenRouteBinding\\RouteBindingServiceProvider as BaseServiceProvider;\n\nclass RouteBindingServiceProvider extends BaseServiceProvider\n{\n    /**\n     * Boot the service provider\n     */\n    public function boot()\n    {\n        // The binder instance\n        $binder = $this-\u003ebinder;\n\n        // Here we define our bindings\n    }\n}\n```\n\nThen register it in `bootstrap/app.php` :\n\n```PHP\n$app-\u003eregister(App\\Providers\\RouteBindingServiceProvider::class);\n```\n\nNow we can define our `bindings` in the `boot` method.\n\n### Defining the Bindings\n\nWe have **Three** types of bindings:\n\n#### 1) Explicit Binding\n\nWe can explicitly bind a route wildcard name to a specific model using the `bind` method :\n\n```PHP\n$binder-\u003ebind('user', 'App\\User');\n```\n\nThis way, Anywhere in our routes if the wildcard `{user}` is found, It will be resolved to the `User` model instance that corresponds to the wildcard value, So we can define our route like this :\n\n```PHP\n$router-\u003eget('profile/{user}', function(App\\User $user) {\n    //\n});\n```\n\nBehind the scenes, The binder will resolve the model instance like this :\n\n```PHP\n$instance = new App\\User;\nreturn $instance-\u003ewhere($instance-\u003egetRouteKeyName(), $value)-\u003efirstOrFail();\n```\n\n##### Customizing The Key Name\n\nBy default, It will use the model's ID column. Similar to Laravel, If you would like it to use another column when retrieving a given model class, you may override the `getRouteKeyName` method on the Eloquent model :\n\n```PHP\n/**\n * Get the route key for the model.\n *\n * @return string\n */\npublic function getRouteKeyName()\n{\n    return 'slug';\n}\n```\n\n##### Using a Custom Resolver Callback :\n\nIf you wish to use your own resolution logic, you may pass a `Class@method` callable style or a `Closure` instead of the class name to the `bind` method, The callable will receive the value of the URI segment and should return the instance of the class that should be injected into the route :\n\n```PHP\n// Using a 'Class@method' callable style\n$binder-\u003ebind('article', 'App\\Article@findForRoute');\n\n// Using a closure\n$binder-\u003ebind('article', function($value) {\n    return \\App\\Article::where('slug', $value)-\u003efirstOrFail();\n});\n```\n\n##### Handling the `NotFound` Exception :\n\nIf no model found with the given key, The Eloquent `firstOrFail` will throw a `ModelNotFoundException`, To handle this exception, We can pass a closure as the third parameter to the `bind` method :\n\n```PHP\n$binder-\u003ebind('article', 'App\\Article', function($e) {\n    // We can return a default value if the model not found :\n    return new \\App\\Article();\n\n    // Or we can throw another exception for example :\n    throw new \\NotFoundHttpException;\n});\n```\n\n#### 2) Implicit Binding\n\nUsing the `implicitBind` method, We can tell the binder to automatically bind all models in a given namespace :\n\n```PHP\n$binder-\u003eimplicitBind('App');\n```\n\nSo in this example :\n\n```PHP\n$router-\u003eget('articles/{article}', function($myArticle) {\n    //\n});\n```\n\nThe binder will first check for any **explicit binding** that matches the `article` key. If no match found, It then (and according to our previous implicit binding) will check if the following class exists `App\\Article` (The namespace + ucFirst(the key)), If it finds it, Then it will call `firstOrFail` on the class like the explicit binding and inject the returned instance into the route, **However**, If no classes found with this name, It will continue to the next binding (if any) and return the route parameters unchanged if no bindings matches.\n\n##### Customizing The Key Name\n\nSimilar to explicit binding, we could specify another column to be used to retrieve the model instance by overriding the `getRouteKeyName` method on the Eloquent model :\n\n```PHP\n/**\n * Get the route key for the model.\n *\n * @return string\n */\npublic function getRouteKeyName()\n{\n    return 'slug';\n}\n```\n\n##### Implicit Binding with Repositories\n\nWe can use implicit binding with classes other than the `Eloquent` models, For example if we use something like `Repository Pattern` and would like our bindings to use the repository classes instead of the Eloquent models, We can do that.\n\nRepository classes names usually use a `Prefix` and\\or `Suffix` beside the Eloquent model name, For example, The `Article` Eloquent model, May have a corresponding repository class with the name `EloquentArticleRepository`, We can set our implicit binding to use this prefix and\\or suffix like this :\n\n```PHP\n$binder-\u003eimplicitBind('App\\Repositories', 'Eloquent', 'Repository');\n```\n\n(Of course we can leave out the `prefix` and\\or the `suffix` if we don't use it)\n\nSo in this example :\n\n```PHP\n$router-\u003eget('articles/{article}', function($myArticle) {\n    //\n});\n```\n\nThe binder will check if the following class exists `App\\Repositories\\EloquentArticleRepository` (The namespace + prefix + ucFirst(the key) + suffix), If it finds it, Then it will call `firstOrFail()` using the column from `getRouteKeyName()` (so you should have these methods on your repository).\n\n##### Using Custom Method\n\nIf you want to use a custom method on your class to retrieve the model instance, You can pass the method name as the fourth parameter :\n\n```PHP\n$binder-\u003eimplicitBind('App\\Repositories', 'Eloquent', 'Repository', 'findForRoute');\n```\n\nThis way, The binder will call the custom method `findForRoute` on our repository passing the route wildcard value and expecting it to return the resolved instance.\n\n###### Example of using a custom method with Implicit Binding while using the Repository Pattern :\n\n1- defining our binding in the service provider :\n\n```PHP\n$binder-\u003eimplicitBind('App\\Repositories', '', 'Repository', 'findForRoute');\n```\n\n2- defining our route in `routes.php` :\n\n```PHP\n$router-\u003eget('articles/{article}', function(App\\Article $article) {\n    return view('articles.view', compact('article'));\n});\n```\n\n3- Adding our custom method in our repository in `apps/Repositories/ArticleRepository.php` :\n\n```PHP\n/**\n * Find the Article for route-model-binding\n *\n * @param  string $val  wildcard value\n *\n * @return \\App\\Article\n */\npublic function findForRoute($val)\n{\n    return $this-\u003emodel-\u003ewhere('slug', $val)-\u003efirstOrFail();\n}\n```\n\n##### Handling the `NotFound` Exception :\n\nSimilar to explicit binding, We can handle the exception thrown in the resolver method (the model `firstOrFail` or in our repository) by passing a closure as the fifth parameter to the method `implicitBind`.\n\n#### 3) Composite Binding\n\nSometimes, you will have a route of two or more levels that contains wildcards of related models, Something like :\n\n```PHP\n$router-\u003eget('posts/{post}/comments/{comment}', function(App\\Post $post, App\\Comment $comment) {\n    //\n});\n```\n\nIn this example, If we use explicit or implicit binding, Each model will be resolved individually with no relation to each other, Sometimes that's OK, But what if we want to resolve these models in one binding to handle the relationship between them and maybe do a proper eager loading without repeating the process for each model individually, That's where `Composite Binding` comes into play.\n\nIn `Composite Binding` we tell the binder to register a binding for multiple wildcards in a specific order.\n\nWe use the method `compositeBind` passing an array of wildcards names as the first parameter, and a resolver callback (either a closure or a `Class@method` callable style) as the second parameter.\n\n```PHP\n// Using a 'Class@method' callable style\n$binder-\u003ecompositeBind(['post', 'comment'], 'App\\Repositories\\PostRepository@findPostCommentForRoute');\n\n// Using a closure\n$binder-\u003ecompositeBind(['post', 'comment'], function($postKey, $commentKey) {\n    $post = \\App\\Post::findOrFail($postKey);\n    $comment = $post-\u003ecomments()-\u003efindOrFail($commentKey);\n\n    return [$post, $comment];\n});\n```\n\n**Note:**\nThis binding will match the route that has **only** and **exactly** the given wildcards (in this case `{post}` and `{comment}`) and they appear in the same exact **order**. The resolver callback will be handled the wildcards values and **MUST** return the resolved models in an array of the same count and order of the wildcards.\n\n**Note:**\nThis type of binding takes a priority over any other type of binding, Meaning that in the previous example if we have an explicit or implicit binding for `post` and\\or `comment`, None of them will take place as long as the route **as whole** matches a composite binding.\n\n##### Handling the `NotFound` Exception :\n\nSimilar to explicit and implicit binding, We can handle the exception thrown in the resolver callback by passing a closure as the third parameter to the method `compositeBind`.\n\n## DingoAPI Integration\n\n**NOTE**\nThis documentation is for [dingo/api](https://github.com/dingo/api) `version 2.*`, for earlier versions of `dingo`, follow this [link](https://github.com/mmghv/lumen-route-binding/issues/6).\n\nTo integrate `dingo/api` with `LumenRouteBinding`, all you need to do is to replace the registration of the default `dingo` service provider with the custom one shipped with `LumenRouteBinding`:\n\nSo remove this line in `bootstrap/app.php` :\n```PHP\n$app-\u003eregister(Dingo\\Api\\Provider\\LumenServiceProvider::class);\n```\n\nAnd add this line instead :\n```PHP\n$app-\u003eregister(mmghv\\LumenRouteBinding\\DingoServiceProvider::class);\n```\n\n_(don't forget to also register the `LumenRouteBinding` service provider itself)_\n\nThat's it, Now you should be able to use `LumenRoutebinding` with `DingoAPI`.\n\n## Contributing\nIf you found an issue, Please report it [here](https://github.com/mmghv/lumen-route-binding/issues).\n\nPull Requests are welcome, just make sure to follow the PSR-2 standards and don't forget to add tests.\n\n## License \u0026 Copyright\n\nCopyright © 2016-2023, [Mohamed Gharib](https://github.com/mmghv).\nReleased under the [MIT license](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmmghv%2Flumen-route-binding","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmmghv%2Flumen-route-binding","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmmghv%2Flumen-route-binding/lists"}