{"id":21544318,"url":"https://github.com/railken/eloquent-mapper","last_synced_at":"2025-04-10T04:41:28.663Z","repository":{"id":62532810,"uuid":"175469773","full_name":"railken/eloquent-mapper","owner":"railken","description":"A laravel package that use the full power of relations to create automatic joins and perform advanced filtering","archived":false,"fork":false,"pushed_at":"2024-03-28T19:33:22.000Z","size":153,"stargazers_count":7,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-24T05:52:14.852Z","etag":null,"topics":["builder","eloquent","filter","joiner","laravel","query","relations","search"],"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/railken.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}},"created_at":"2019-03-13T17:38:35.000Z","updated_at":"2024-03-27T18:02:05.000Z","dependencies_parsed_at":"2022-11-02T14:33:10.019Z","dependency_job_id":null,"html_url":"https://github.com/railken/eloquent-mapper","commit_stats":null,"previous_names":[],"tags_count":49,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/railken%2Feloquent-mapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/railken%2Feloquent-mapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/railken%2Feloquent-mapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/railken%2Feloquent-mapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/railken","download_url":"https://codeload.github.com/railken/eloquent-mapper/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248160778,"owners_count":21057549,"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":["builder","eloquent","filter","joiner","laravel","query","relations","search"],"created_at":"2024-11-24T05:17:39.075Z","updated_at":"2025-04-10T04:41:28.638Z","avatar_url":"https://github.com/railken.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"left\"\u003eEloquent Mapper\u003c/h1\u003e\n\n[![Actions Status](https://github.com/railken/eloquent-mapper/workflows/Test/badge.svg)](https://github.com/railken/eloquent-mapper/actions)\n\nA laravel package that use the full power of relations to create automatic joins and perform advanced filtering.\n\nGiven for e.g. two models `Office` and `Employee`, you can transform a string like this `\"employees.name ct 'Mario Rossi' or employees.name ct 'Giacomo'\"` into a sql query like this\n\n```sql\nselect offices.* \nfrom `offices` \nleft join `employees` as `employees` on `employees`.`office_id` = `offices`.`id`\nwhere (`employees`.`name` like ? or `employees`.`name` like ?)\n```\n\nFunctions: \n\n- Join automatically your relations\n- Filter query with complex logic expression [lara-eye](https://github.com/railken/lara-eye)\n- Add missing relationship [laravel-eloquent-relationships](https://github.com/ankurk91/laravel-eloquent-relationships)\n\n## Requirements\n\nPHP 8.1 and laravel 8\n\n## Installation\n\nYou can install it via [Composer](https://getcomposer.org/) by typing the following command:\n\n```bash\ncomposer require railken/eloquent-mapper\n```\n\n## Usage\n\nIn order to use this library you need a map.\n\nCreate a new class wherever you want like the following example\n\n`app/Map.php`\n```php\nnamespace App;\n\nuse Railken\\EloquentMapper\\Map as BaseMap;\n\nclass Map extends BaseMap\n{\n    /**\n     * Return an array of all models you want to map\n     *\n     * @return array\n     */\n    public function models(): array\n    {\n        /** return [\n            \\App\\Models\\User::class\n        ]; **/\n    }\n}\n```\n\nThe method `models` must return a list of all models. You can even add models that are in your vendor folder, regardless of the logic you use, you only have to return an array.\n\n`Railken\\EloquentMapper\\Map` also has the mapping of relations and attributes based on the model, if you wish you can ovveride that functionality and write your own. [Check source](src/Map.php)\n\nThese methods are invoked only when you call the command `artisan mapper:generate` (see below) and the result will be cached in a file placed in `bootstrap/cache/map.php`. \n\nThis means you can perform whatever logic you want to retrieve all models (e.g. scanning files), so don't worry about caching.\n\n**Important**: In order to be detected, all relations must return the type `Illuminate\\Database\\Eloquent\\Relations\\Relation` like this:\n\n```php\nnamespace App;\n\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsTo;\n\nclass Foo extends Model\n{   \n    /**\n     * @return \\Illuminate\\Database\\Eloquent\\Relations\\BelongsTo\n     */\n    public function bar(): BelongsTo\n    {\n        return $this-\u003ebelongsTo(Bar::class);\n    }\n}\n```\n\nNow it's time to register this class in any provider to override the default one.\n\n`app/Providers/AppServiceProvider.php`\n\n```php\nnamespace App\\Providers;\n\nuse Illuminate\\Support\\ServiceProvider;\nuse App\\Map;\nuse Railken\\EloquentMapper\\Contracts\\Map as MapContract;\n\nclass AppServiceProvider extends ServiceProvider\n{\n    /**\n     * @inherit\n     */\n    public function register()\n    {\n        $this-\u003eapp-\u003ebind(MapContract::class, Map::class);\n    }\n}\n```\n\n## Artisan\n\nThere is only one command, and it's `artisan mapper:generate`. This command will remap and recache so keep in mind that you have to execute it whanever you change your code models .\n\nIf you use models that are in your vendor folder, you could add this in your `composer.json` to reload everytime the libreries are updated.\n```json\n{\n   \"scripts\": {\n        \"post-autoload-dump\": [\n            \"@php artisan mapper:generate\"\n        ]\n    }\n}\n```\n\n## Filtering\n\nSow how the filtering actually works?\n\n\n```php\nuse Railken\\EloquentMapper\\Scopes\\FilterScope;\nuse Railken\\EloquentMapper\\With\\WithCollection;\nuse Railken\\EloquentMapper\\With\\WithItem;\nuse App\\Models\\Foo;\n\n$foo = new Foo;\n$query = $foo-\u003enewQuery();\n$filter = \"created_at \u003e= 2019\";\n\n$scope = new FilterScope;\n$scope-\u003eapply($query, $filter, new WithCollection([\n    new WithItem('bar')\n]));\n\n```\n\nAnd that's it! `$query` is now filtered, if `Foo` has any relationships you can use the dot notation and the filter will automatically perform the join. For e.g. if `Foo` has a relationship called `tags` and you want to retrieve all `Foo` with the tag name `myCustomTag` simply use `tag.name = 'myCustomTag'`.\n\nHere's the [full syntax](https://github.com/railken/search-query#nodes)\n\nThe third parameter is the eager loading option. You can of course use the dot notation as well and add subquery.\nFor istance the following example rapresent a list of all authors that contains the name `Mario` and returns all of theirs books that have a `tag.name` called `sci-fi`.\n\n```php\nuse Railken\\EloquentMapper\\Scopes\\FilterScope;\nuse Railken\\EloquentMapper\\With\\WithCollection;\nuse Railken\\EloquentMapper\\With\\WithItem;\nuse Railken\\EloquentMapper\\Tests\\Models\\Author;\n\n$author = new Author;\n$query = $author-\u003enewQuery();\n$filter = \"name ct 'Mario'\";\n$scope = new FilterScope;\n\n$scope-\u003eapply($query, $filter, new WithCollection([\n    new WithItem('books', 'tag.name eq \"sci-fi\"')\n]));\n```\n\n## Joiner\n\nThis is an internal class used by the `FilterScope` to join the necessary relations before performing the filtering, but you can use it indipendently. [see tests](tests/JoinerTest.php)\n\n## Example - Setup\n\nLet's continue with a real example, first the setup. We will use two models: `Office` and `Employee`\n\n`app/Models/Office.php`\n```php\nnamespace App\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Relations\\HasMany;\n\nclass Office extends Model\n{   \n    /** \n     * @var array\n     */\n    public $fillable = [\n        'name',\n        'description'\n    ];\n\n    /**\n     * @return \\Illuminate\\Database\\Eloquent\\Relations\\HasMany\n     */\n    public function employees(): HasMany\n    {\n        return $this-\u003ehasMany(Employee::class);\n    }\n}\n```\n\n`app/Models/Employee.php`\n```php\nnamespace App\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsTo;\nuse App\\Models\\Office;\n\nclass Employee extends Model\n{   \n    /**\n     * @var array\n     */\n    public $fillable = [\n        'name',\n        'description',\n        'office_id'\n    ];\n\n    /**\n     * @return \\Illuminate\\Database\\Eloquent\\Relations\\BelongsTo\n     */\n    public function office(): BelongsTo\n    {\n        return $this-\u003ebelongsTo(Office::class);\n    }\n}\n```\n\n`app/Map.php`\n```php\nnamespace App;\n\nuse Railken\\EloquentMapper\\Map as BaseMap;\n\nclass Map extends BaseMap\n{\n    /**\n     * Return an array of all models you want to map\n     *\n     * @return array\n     */\n    public function models(): array\n    {\n        return [\n            \\App\\Models\\Employee::class,\n            \\App\\Models\\Office::class\n        ];\n    }\n}\n\n```\n\n# Example - Usage\n\nRetrieve all offices that have employees with name `Mario Rossi` or `Giacomo`\n\n```php\nuse App\\Models\\Office;\nuse Railken\\EloquentMapper\\Scopes\\FilterScope;\n\n$office = new Office;\n\n$query = $office-\u003enewQuery();\n$filter = \"employees.name ct 'Mario Rossi' or employees.name ct 'Giacomo'\"\n\n$scope = new FilterScope();\n$scope-\u003eapply($query, $filter);\n\necho $query-\u003etoSql();\n\n```\n\nResult:\n```sql\nselect offices.* \nfrom `offices` \nleft join `employees` as `employees` on `employees`.`office_id` = `offices`.`id`\nwhere (`employees`.`name` like ? or `employees`.`name` like ?)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frailken%2Feloquent-mapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frailken%2Feloquent-mapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frailken%2Feloquent-mapper/lists"}