{"id":21561670,"url":"https://github.com/testmonitor/eloquent-searchable","last_synced_at":"2025-04-10T12:05:51.918Z","repository":{"id":247208772,"uuid":"824909779","full_name":"testmonitor/eloquent-searchable","owner":"testmonitor","description":"A Laravel package that adds search functionality to Eloquent models, allowing for various search techniques such as exact and partial matches.","archived":false,"fork":false,"pushed_at":"2025-04-09T12:55:06.000Z","size":60,"stargazers_count":0,"open_issues_count":0,"forks_count":3,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-09T13:17:12.320Z","etag":null,"topics":[],"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/testmonitor.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-07-06T09:20:25.000Z","updated_at":"2025-04-09T12:55:09.000Z","dependencies_parsed_at":"2024-11-24T12:17:16.156Z","dependency_job_id":null,"html_url":"https://github.com/testmonitor/eloquent-searchable","commit_stats":null,"previous_names":["testmonitor/eloquent-searchable"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/testmonitor%2Feloquent-searchable","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/testmonitor%2Feloquent-searchable/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/testmonitor%2Feloquent-searchable/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/testmonitor%2Feloquent-searchable/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/testmonitor","download_url":"https://codeload.github.com/testmonitor/eloquent-searchable/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248216753,"owners_count":21066631,"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-24T09:27:33.045Z","updated_at":"2025-04-10T12:05:51.899Z","avatar_url":"https://github.com/testmonitor.png","language":"PHP","readme":"# Eloquent Searchable\n\n[![Latest Stable Version](https://poser.pugx.org/testmonitor/eloquent-searchable/v/stable)](https://packagist.org/packages/testmonitor/eloquent-searchable)\n[![codecov](https://codecov.io/gh/testmonitor/eloquent-searchable/graph/badge.svg?token=EK8IWK6R9G)](https://codecov.io/gh/testmonitor/eloquent-searchable)\n[![StyleCI](https://styleci.io/repos/824909779/shield)](https://styleci.io/repos/824909779)\n[![License](https://poser.pugx.org/testmonitor/eloquent-searchable/license)](https://packagist.org/packages/eloquent-searchable)\n\nA package that provides a search feature for Eloquent models. You can define SearchAspects for your Eloquent model that use different search techniques, such as an exact match or partial match.\n\nIt is heavily inspired by Spatie's [Query Builder](https://github.com/spatie/laravel-query-builder/) and can be used in conjunction with this package.\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Usage](#usage)\n  - [Aspects](#aspects)\n  - [Search weighing](#search-weighing)\n  - [Search related models](#search-related-models)\n- [Tests](#tests)\n- [Changelog](#changelog)\n- [Contributing](#contributing)\n- [Credits](#credits)\n- [License](#license)\n\n## Installation\n\nThis package can be installed through Composer:\n\n```sh\n$ composer require testmonitor/eloquent-searchable\n```\n\nNext, publish the configuration file:\n\n```sh\n$ php artisan vendor:publish --tag=eloquent-searchable\n```\n\nThe configuration file allows you the change the HTTP parameter name as well\nas the minimal query length.\n\n## Usage\n\nTo add searchable functionality to your Eloquent model, follow these steps:\n\n1. Use the trait ```TestMonitor\\Searchable\\Searchable``` in your model(s).\n2. Include the searchUsing scope together with one or more SearchAspects.\n\nAdd the searchable trait on the models you want to make searchable:\n\n```php\nuse Illuminate\\Database\\Eloquent\\Model;\nuse TestMonitor\\Searchable\\Searchable;\n\nclass User extends Model\n{\n    use Searchable;\n\n    // ...\n}\n```\n\nNext, include the `searchUsing` scope with `SearchAspects` to define your\nsearch strategy:\n\n```php\nuse App\\Models\\User;\nuse Illuminate\\Routing\\Controller;\nuse TestMonitor\\Searchable\\Aspects\\SearchAspect;\n\nclass UsersController extends Controller\n{\n    public function index()\n    {\n        return User::query()\n            -\u003eseachUsing([\n                SearchAspect::exact('first_name'),\n                SearchAspect::exact('last_name'),\n                SearchAspect::partial('email'),\n            ])\n            -\u003eget();\n    }\n}\n```\n\nIn this example, the controller provides a way to search through a\nset of users:\n\n- Both the first and last names are searched using the “exact” strategy.\nOnly exact matches will be returned.\n- The email field is searched using the “partial” match strategy. When\nthe query term occurs within the email address, it will be returned.\n\nThe search query is automatically derived from the HTTP request. You can\nmodify the HTTP query parameter in the configuration file. By default,\nthe name `query` is used.\n\n### Aspects\n\nA model's search strategy is defined by search aspects. An aspect defines a matching configuration. For example,\nthe exact search aspect perfoms an exact search on the provided attribute.\n\nEloquent Searcheable provides multiple aspects out of the box. Additionally, you can also define your own\nmatching configuration using the custom aspect.\n\n#### Exact match\n\nThe Exact search aspect will only return matches that are equal to the search term.\n\n```php\nuse App\\Models\\Post;\nuse Illuminate\\Routing\\Controller;\nuse TestMonitor\\Searchable\\Aspects\\SearchAspect;\n\nclass PostsController extends Controller\n{\n    public function index()\n    {\n        return Post::query()\n            -\u003eseachUsing([\n                SearchAspect::exact(name: 'title'),\n            ])\n            -\u003eget();\n    }\n}\n```\n\n#### Partial match\n\nThe Partial search aspect returns matches where the search query occurs anywhere within the given attribute.\n\n```php\nuse App\\Models\\Post;\nuse Illuminate\\Routing\\Controller;\nuse TestMonitor\\Searchable\\Aspects\\SearchAspect;\n\nclass PostsController extends Controller\n{\n    public function index()\n    {\n        return Post::query()\n            -\u003eseachUsing([\n                SearchAspect::partial(name: 'title'),\n            ])\n            -\u003eget();\n    }\n}\n```\n\n#### JSON match\n\nThe JSON search aspect returns matches where the search query occurs anywhere within the given JSON attribute.\n\n```php\nuse App\\Models\\Post;\nuse Illuminate\\Routing\\Controller;\nuse TestMonitor\\Searchable\\Aspects\\SearchAspect;\n\nclass PostsController extends Controller\n{\n    public function index()\n    {\n        return Post::query()\n            -\u003eseachUsing([\n                SearchAspect::json(name: 'settings'),\n            ])\n            -\u003eget();\n    }\n}\n```\n\n#### Prefix match\n\nThe Prefix aspect combines the exact and partial strategy with the ability to strip one or more characters from the search query. \nThis can be useful when your application provides an incremental code with a prefix to your user (say, ISSUE-12), \nbut only store the number in your database (which would be the number 12).\n\nAs a default, the partial match strategy is used. Using the `exact` parameter, you can enable exact matching.\n\n```php\nuse App\\Models\\Issue;\nuse Illuminate\\Routing\\Controller;\nuse TestMonitor\\Searchable\\Aspects\\SearchAspect;\n\nclass IssuesController extends Controller\n{\n    public function index()\n    {\n        return Issue::query()\n            -\u003eseachUsing([\n                SearchAspect::prefix(name: 'code', prefix: 'ISSUE-', exact: true),\n                SearchAspect::prefix(name: 'code', prefix: 'ISSUE-'),\n            ])\n            -\u003eget();\n    }\n}\n```\n\n#### Custom aspect\n\nYou can create your own search aspect by creating a class that implements the `TestMonitor\\Searchable\\Contracts\\Search` contract.\n\nLet's implement a new search aspect: a strategy that matches the beginning of an attribute. Your custom search aspect would look\nsomething like this:\n\n```php\nuse TestMonitor\\Searchable\\Weights;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse TestMonitor\\Searchable\\Contracts\\Search;\n\nclass StartsWithSearch implements Search\n{\n    /**\n     * @param \\Illuminate\\Database\\Eloquent\\Builder\u003c\\Illuminate\\Database\\Eloquent\\Model\u003e $query\n     * @param \\TestMonitor\\Searchable\\Weights $weights\n     * @param string $property\n     * @param string $term\n     * @param int $weight\n     */\n    public function __invoke(Builder $query, Weights $weights, string $property, string $term, int $weight = 1): void\n    {\n        $query-\u003ewhere($property, 'like', \"{$term}%\");\n    }\n}\n```\n\nTo use this custom aspect, define it in your search criteria like this:\n\n```php\nuse App\\Models\\Post;\nuse Illuminate\\Routing\\Controller;\nuse App\\Search\\Aspects\\CustomSearch;\nuse TestMonitor\\Searchable\\Aspects\\SearchAspect;\n\nclass PostsController extends Controller\n{\n    public function index()\n    {\n        return Post::query()\n            -\u003eseachUsing([\n                SearchAspect::custom('name', new CustomSearch),\n            ])\n            -\u003eget();\n    }\n}\n```\n\n### Search weighing\n\nOptionally, you can use search weights. Weighing prioritizes search criteria, placing results with higher weights at the top.\n\nLet's make a Post model searchable and use the following criteria:\n\n- A partial keyword match in the post's title should be ranked highest.\n- A partial keyword match in the summary should be ranked below any title match.\n- A partial keyword match in the description should be ranked below any other criteria.\n\nHere's an example that implements these criteria:\n\n```php\nuse App\\Models\\Post;\nuse Illuminate\\Routing\\Controller;\nuse TestMonitor\\Searchable\\Aspects\\SearchAspect;\n\nclass PostsController extends Controller\n{\n    public function index()\n    {\n        return Post::query()\n            -\u003eseachUsing([\n                SearchAspect::partial(name: 'title', weight: 20),\n                SearchAspect::partial(name: 'summary', weight: 10),\n                SearchAspect::partial('description'),\n            ])\n            -\u003eget();\n    }\n}\n```\n\n### Search related models\n\nUse dotted notation to search through related model attributes.\n\nLet's say you want to search your posts based on their blog's title and description. Here's an example that \nimplements these criteria:\n\n```php\nuse App\\Models\\Post;\nuse Illuminate\\Routing\\Controller;\nuse TestMonitor\\Searchable\\Aspects\\SearchAspect;\n\nclass PostsController extends Controller\n{\n    public function index()\n    {\n        return Post::query()\n            -\u003eseachUsing([\n                SearchAspect::exact('blog.title'),\n                SearchAspect::partial('blog.description'),\n            ])\n            -\u003eget();\n    }\n}\n```\n\n## Tests\n\nThe package contains integration tests. You can run them using PHPUnit.\n\n```\n$ vendor/bin/phpunit\n```\n\n## Changelog\n\nRefer to [CHANGELOG](CHANGELOG.md) for more information.\n\n## Contributing\n\nRefer to [CONTRIBUTING](CONTRIBUTING.md) for contributing details.\n\n## Credits\n\n- [Thijs Kok](https://www.testmonitor.com/)\n- [Stephan Grootveld](https://www.testmonitor.com/)\n- [Frank Keulen](https://www.testmonitor.com/)\n- [All Contributors](../../contributors)\n\n## License\n\nThe MIT License (MIT). Refer to the [License](LICENSE.md) for more information.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftestmonitor%2Feloquent-searchable","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftestmonitor%2Feloquent-searchable","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftestmonitor%2Feloquent-searchable/lists"}