Skip to content

Commit c954aee

Browse files
authored
V3 (#57)
1 parent 2759081 commit c954aee

File tree

9 files changed

+317
-127
lines changed

9 files changed

+317
-127
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ docs
44
vendor
55
coverage
66
.phpunit.result.cache
7-
.phpunit.result.cache
87
.idea
8+
.env

README.md

Lines changed: 83 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Hey! We've built a Docker-based deployment tool to launch apps and sites fully c
2323
* Support for cross-model [pagination](https://laravel.com/docs/master/pagination#introduction).
2424
* Search through single or multiple columns.
2525
* Search through (nested) relationships.
26+
* Support for Full-Text Search, even through relationships.
2627
* Order by (cross-model) columns or by relevance.
2728
* Use [constraints](https://laravel.com/docs/master/eloquent#retrieving-models) and [scoped queries](https://laravel.com/docs/master/eloquent#query-scopes).
2829
* [Eager load relationships](https://laravel.com/docs/master/eloquent-relationships#eager-loading) for each model.
@@ -47,24 +48,30 @@ You can install the package via composer:
4748
composer require protonemedia/laravel-cross-eloquent-search
4849
```
4950

50-
## Upgrading from v1
51+
## Upgrading from v2 to v3
52+
53+
* The `get` method has been renamed to `search`.
54+
* The `addWhen` method has been removed in favor of [`when`](#usage).
55+
* By default, the results are sorted by the *updated* column, which is the `updated_at` column in most cases. If you don't use timestamps, it will now use the primary key by default.
56+
57+
## Upgrading from v1 to v2
5158

5259
* The `startWithWildcard` method has been renamed to `beginWithWildcard`.
5360
* The default order column is now evaluated by the `getUpdatedAtColumn` method. Previously it was hard-coded to `updated_at`. You still can use [another column](#sorting) to order by.
5461
* The `allowEmptySearchQuery` method and `EmptySearchQueryException` class have been removed, but you can still [get results without searching](#getting-results-without-searching).
5562

5663
## Usage
5764

58-
Start your search query by adding one or more models to search through. Call the `add` method with the model's class name and the column you want to search through. Then call the `get` method with the search term, and you'll get a `\Illuminate\Database\Eloquent\Collection` instance with the results.
65+
Start your search query by adding one or more models to search through. Call the `add` method with the model's class name and the column you want to search through. Then call the `search` method with the search term, and you'll get a `\Illuminate\Database\Eloquent\Collection` instance with the results.
5966

60-
The results are sorted in ascending order by the *updated* column by default. In most cases, this column is `updated_at`. If you've [customized](https://laravel.com/docs/master/eloquent#timestamps) your model's `UPDATED_AT` constant, or overwritten the `getUpdatedAtColumn` method, this package will use the customized column. Of course, you can [order by another column](#sorting) as well.
67+
The results are sorted in ascending order by the *updated* column by default. In most cases, this column is `updated_at`. If you've [customized](https://laravel.com/docs/master/eloquent#timestamps) your model's `UPDATED_AT` constant, or overwritten the `getUpdatedAtColumn` method, this package will use the customized column. If you don't use timestamps at all, it will use the primary key by default. Of course, you can [order by another column](#sorting) as well.
6168

6269
```php
6370
use ProtoneMedia\LaravelCrossEloquentSearch\Search;
6471

6572
$results = Search::add(Post::class, 'title')
6673
->add(Video::class, 'title')
67-
->get('howto');
74+
->search('howto');
6875
```
6976

7077
If you care about indentation, you can optionally use the `new` method on the facade:
@@ -73,7 +80,7 @@ If you care about indentation, you can optionally use the `new` method on the fa
7380
Search::new()
7481
->add(Post::class, 'title')
7582
->add(Video::class, 'title')
76-
->get('howto');
83+
->search('howto');
7784
```
7885

7986
You can add multiple models at once by using the `addMany` method:
@@ -82,16 +89,16 @@ You can add multiple models at once by using the `addMany` method:
8289
Search::addMany([
8390
[Post::class, 'title'],
8491
[Video::class, 'title'],
85-
])->get('howto');
92+
])->search('howto');
8693
```
8794

88-
There's also an `addWhen` method, that adds the model when the first argument given to the method evaluates to `true`:
95+
There's also an `when` method to apply certain clauses based on another condition:
8996

9097
```php
9198
Search::new()
92-
->addWhen($user, Post::class, 'title')
93-
->addWhen($user->isAdmin(), Video::class, 'title')
94-
->get('howto');
99+
->when($user->isVerified(), fn($search) => $search->add(Post::class, 'title'))
100+
->when($user->isAdmin(), fn($search) => $search->add(Video::class, 'title'))
101+
->search('howto');
95102
```
96103

97104
### Wildcards
@@ -102,7 +109,7 @@ By default, we split up the search term, and each keyword will get a wildcard sy
102109
Search::add(Post::class, 'title')
103110
->add(Video::class, 'title')
104111
->beginWithWildcard()
105-
->get('os');
112+
->search('os');
106113
```
107114

108115
*Note: in previous versions of this package, this method was called `startWithWildcard()`.*
@@ -114,7 +121,7 @@ Search::add(Post::class, 'title')
114121
->add(Video::class, 'title')
115122
->beginWithWildcard()
116123
->endWithWildcard(false)
117-
->get('os');
124+
->search('os');
118125
```
119126

120127
### Multi-word search
@@ -124,7 +131,7 @@ Multi-word search is supported out of the box. Simply wrap your phrase into doub
124131
```php
125132
Search::add(Post::class, 'title')
126133
->add(Video::class, 'title')
127-
->get('"macos big sur"');
134+
->search('"macos big sur"');
128135
```
129136

130137
You can disable the parsing of the search term by calling the `dontParseTerm` method, which gives you the same results as using double-quotes.
@@ -133,7 +140,7 @@ You can disable the parsing of the search term by calling the `dontParseTerm` me
133140
Search::add(Post::class, 'title')
134141
->add(Video::class, 'title')
135142
->dontParseTerm()
136-
->get('macos big sur');
143+
->search('macos big sur');
137144
```
138145

139146
### Sorting
@@ -144,7 +151,7 @@ If you want to sort the results by another column, you can pass that column to t
144151
Search::add(Post::class, 'title', 'published_at')
145152
->add(Video::class, 'title', 'released_at')
146153
->orderByDesc()
147-
->get('learn');
154+
->search('learn');
148155
```
149156

150157
You can call the `orderByRelevance` method to sort the results by the number of occurrences of the search terms. Imagine these two sentences:
@@ -158,7 +165,7 @@ If you search for *Apple iPad*, the second sentence will come up first, as there
158165
Search::add(Post::class, 'title')
159166
->beginWithWildcard()
160167
->orderByRelevance()
161-
->get('Apple iPad');
168+
->search('Apple iPad');
162169
```
163170

164171
Ordering by relevance is *not* supported if you're searching through (nested) relationships.
@@ -173,12 +180,12 @@ Search::new()
173180
->orderByModel([
174181
Post::class, Video::class, Comment::class,
175182
])
176-
->get('Artisan School');
183+
->search('Artisan School');
177184
```
178185

179186
### Pagination
180187

181-
We highly recommend paginating your results. Call the `paginate` method before the `get` method, and you'll get an instance of `\Illuminate\Contracts\Pagination\LengthAwarePaginator` as a result. The `paginate` method takes three (optional) parameters to customize the paginator. These arguments are [the same](https://laravel.com/docs/master/pagination#introduction) as Laravel's database paginator.
188+
We highly recommend paginating your results. Call the `paginate` method before the `search` method, and you'll get an instance of `\Illuminate\Contracts\Pagination\LengthAwarePaginator` as a result. The `paginate` method takes three (optional) parameters to customize the paginator. These arguments are [the same](https://laravel.com/docs/master/pagination#introduction) as Laravel's database paginator.
182189

183190
```php
184191
Search::add(Post::class, 'title')
@@ -188,7 +195,7 @@ Search::add(Post::class, 'title')
188195
// or
189196
->paginate($perPage = 15, $pageName = 'page', $page = 1)
190197

191-
->get('build');
198+
->search('build');
192199
```
193200

194201
You may also use [simple pagination](https://laravel.com/docs/master/pagination#simple-pagination). This will return an instance of `\Illuminate\Contracts\Pagination\Paginator`, which is not length aware:
@@ -201,7 +208,7 @@ Search::add(Post::class, 'title')
201208
// or
202209
->simplePaginate($perPage = 15, $pageName = 'page', $page = 1)
203210

204-
->get('build');
211+
->search('build');
205212
```
206213

207214
### Constraints and scoped queries
@@ -211,7 +218,7 @@ Instead of the class name, you can also pass an instance of the [Eloquent query
211218
```php
212219
Search::add(Post::published(), 'title')
213220
->add(Video::where('views', '>', 2500), 'title')
214-
->get('compile');
221+
->search('compile');
215222
```
216223

217224
### Multiple columns per model
@@ -221,7 +228,7 @@ You can search through multiple columns by passing an array of columns as the se
221228
```php
222229
Search::add(Post::class, ['title', 'body'])
223230
->add(Video::class, ['title', 'subtitle'])
224-
->get('eloquent');
231+
->search('eloquent');
225232
```
226233

227234
### Search through (nested) relationships
@@ -231,7 +238,30 @@ You can search through (nested) relationships by using the *dot* notation:
231238
```php
232239
Search::add(Post::class, ['comments.body'])
233240
->add(Video::class, ['posts.user.biography'])
234-
->get('solution');
241+
->search('solution');
242+
```
243+
244+
### Full-Text Search
245+
246+
You may use [MySQL's Full-Text Search](https://laravel.com/docs/master/queries#full-text-where-clauses) by using the `addFullText` method. You can search through a single or multiple columns (using [full text indexes](https://laravel.com/docs/master/migrations#available-index-types)), and you can specify a set of options, for example, to specify the mode. You can even regular and full-text searches in one query:
247+
248+
```php
249+
Search::new()
250+
->add(Post::class, 'title')
251+
->addFullText(Video::class, 'title', ['mode' => 'boolean'])
252+
->addFullText(Blog::class, ['title', 'subtitle', 'body'], ['mode' => 'boolean'])
253+
->search('framework -css');
254+
```
255+
256+
If you want to search through relationships, you need to pass in an array where the array key contains the relation, while the value is an array of columns:
257+
258+
```php
259+
Search::new()
260+
->addFullText(Page::class, [
261+
'posts' => ['title', 'body'],
262+
'sections' => ['title', 'subtitle', 'body'],
263+
], )
264+
->search('framework -css');
235265
```
236266

237267
### Sounds like
@@ -243,7 +273,7 @@ Search::new()
243273
->add(Post::class, 'framework')
244274
->add(Video::class, 'framework')
245275
->soundsLike()
246-
->get('larafel');
276+
->search('larafel');
247277
```
248278

249279
### Eager load relationships
@@ -253,19 +283,19 @@ Not much to explain here, but this is supported as well :)
253283
```php
254284
Search::add(Post::with('comments'), 'title')
255285
->add(Video::with('likes'), 'title')
256-
->get('guitar');
286+
->search('guitar');
257287
```
258288

259289
### Getting results without searching
260290

261-
You call the `get` method without a term or with an empty term. In this case, you can discard the second argument of the `add` method. With the `orderBy` method, you can set the column to sort by (previously the third argument):
291+
You call the `search` method without a term or with an empty term. In this case, you can discard the second argument of the `add` method. With the `orderBy` method, you can set the column to sort by (previously the third argument):
262292

263293
```php
264294
Search::add(Post::class)
265295
->orderBy('published_at')
266296
->add(Video::class)
267297
->orderBy('released_at')
268-
->get();
298+
->search();
269299
```
270300

271301
### Counting records
@@ -287,7 +317,7 @@ Search::add(Post::class, 'title')
287317
->add(Video::class, 'title')
288318
->includeModelType()
289319
->paginate()
290-
->get('foo');
320+
->search('foo');
291321

292322
// Example result with model identifier.
293323
{
@@ -318,9 +348,32 @@ Search::add(Post::class, 'title')
318348

319349
By default, it uses the `type` key, but you can customize this by passing the key to the method.
320350

351+
You can also customize the `type` value by adding a public method `searchType()` to your model to override the default class base name.
352+
321353
```php
322-
Search::new()
323-
->includeModelType('model_type');
354+
class Video extends Model
355+
{
356+
public function searchType()
357+
{
358+
return 'awesome_video';
359+
}
360+
}
361+
362+
// Example result with searchType() method.
363+
{
364+
"current_page": 1,
365+
"data": [
366+
{
367+
"id": 1,
368+
"video_id": null,
369+
"title": "foo",
370+
"published_at": null,
371+
"created_at": "2021-12-03T09:39:10.000000Z",
372+
"updated_at": "2021-12-03T09:39:10.000000Z",
373+
"type": "awesome_video",
374+
}
375+
],
376+
...
324377
```
325378

326379
### Standalone parser

0 commit comments

Comments
 (0)