├── .gitignore
├── LICENSE
├── README.md
├── composer.json
├── composer.lock
├── database
├── factories
│ └── UserFactory.php
├── migrations
│ └── 2020_01_01_000000_create_users_table.php
└── seeds
│ ├── DatabaseSeeder.php
│ └── UsersTableSeeder.php
├── helpers
└── helpers.php
├── models
├── User.php
└── UserFilters.php
├── phpunit.xml
├── src
├── FilterQueryString.php
├── Filters
│ ├── BaseClause.php
│ ├── ComparisonClauses
│ │ ├── BaseComparison.php
│ │ ├── Between
│ │ │ ├── Between.php
│ │ │ ├── Betweener.php
│ │ │ └── NotBetween.php
│ │ ├── GreaterOrEqualTo.php
│ │ ├── GreaterThan.php
│ │ ├── LessOrEqualTo.php
│ │ └── LessThan.php
│ ├── OrderbyClause.php
│ ├── WhereClause.php
│ ├── WhereInClause.php
│ └── WhereLikeClause.php
└── Resolvings.php
└── tests
├── CustomFilterTest.php
├── CustomParametersTest.php
├── Filters
├── CombinationTest.php
├── ComparisonClauses
│ ├── BetweenTest.php
│ ├── CombinationTest.php
│ ├── GreaterOrEqualTest.php
│ ├── GreaterThanTest.php
│ ├── LessOrEqualToTest.php
│ ├── LessThanTest.php
│ └── NotBetweenTest.php
├── OrderbyClauseTest.php
├── WhereClauseTest.php
├── WhereInClauseTest.php
└── WhereLikeClauseTest.php
└── TestCase.php
/.gitignore:
--------------------------------------------------------------------------------
1 | todo
2 | notes
3 | .idea
4 | vendor
5 | docker
6 | docker-compose.yaml
7 | .phpunit.result.cache
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Mehrad Sadeghi
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Laravel Filter Query String
2 | #### Filter your queries based on url query string parameters like a breeze.
3 |
4 | *Compatible with Laravel **5.x** **6.x** **7.x** **8.x** **9.x** **10.x** **11.x** **12.x***.
5 |
6 | ## Table of Content
7 | - [Describing the Problem](#Describing-the-Problem)
8 | - [Usage](#Usage)
9 | - [Installation](#Usage)
10 | - [Available Filters](#Available-Methods)
11 | - [Sort](#Sort)
12 | - [Comparisons](#Comparisons)
13 | - [In](#In)
14 | - [Like](#Like)
15 | - [Where clause](#Where-Clause-Default-Filter)
16 | - [Custom Filters](#Custom-Filters)
17 | - [Conditional Filters](#Conditional-Filters)
18 |
19 | ## Describing the Problem
20 |
21 | You have probably faced the situation where you needed to filter your query based on given parameters in url query-string and after developing the logics, You've had such a code:
22 |
23 | ```php
24 | $users = User::latest();
25 |
26 | if(request('username')) {
27 | $users->where('username', request('username'));
28 | }
29 |
30 | if(request('age')) {
31 | $users->where('age', '>', request('age'));
32 | }
33 |
34 | if(request('email')) {
35 | $users->where('email', request('email'));
36 | }
37 |
38 | return $users->get();
39 |
40 | ```
41 |
42 | This works, But it's not a good practice.
43 |
44 | When the number of parameters starts to grow, The number of these kind of `if` statements also grows and your code gets huge and hard to maintain.
45 |
46 | Also it's against the Open/Closed principal of SOLID principles, Because when you have a new parameter, You need to get into your existing code and add a new logic (which may breaks the existing implementations).
47 |
48 | So we have to design a way to make our filters logics separated from each other and apply them into the final query, which is the whole idea behind this package.
49 |
50 | ## Usage
51 | 1. First you need to install the package:
52 |
53 | `$ composer require mehradsadeghi/laravel-filter-querystring`
54 |
55 | 2. Then you should `use` the `FilterQueryString` trait in your model, And define `$filters` property which can be consist of [available filters](#Available-Methods) or your [custom filters](#custom-filters).
56 |
57 | ```php
58 | use Mehradsadeghi\FilterQueryString\FilterQueryString;
59 |
60 | class User extends Model
61 | {
62 | use FilterQueryString;
63 |
64 | protected $filters = [];
65 |
66 | ...
67 | }
68 | ```
69 | 3. You need to use `filter()` method in your eloquent query. For example:
70 |
71 | ```php
72 | User::select('name')->filter()->get();
73 | ```
74 |
75 | ### Available Methods
76 | - [Sort](#Sort)
77 | - [Comparisons](#Comparisons)
78 | - [In](#In)
79 | - [Like](#Like)
80 | - [Where clause](#Where-Clause-Default-Filter)
81 |
82 | For the purpose of explaining each method, Imagine we have such data in our `users` table:
83 |
84 | | id | name | email | username | age | created_at
85 | |:---:|:--------:|:--------------------------:|:----------:|:----:|:----------:|
86 | | 1 | mehrad | mehrad@example.com | mehrad123 | 20 | 2020-09-01 |
87 | | 2 | reza | reza@example.com | reza123 | 20 | 2020-10-01 |
88 | | 3 | hossein | hossein@example.com | hossein123 | 22 | 2020-11-01 |
89 | | 4 | dariush | dariush@example.com | dariush123 | 22 | 2020-12-01 |
90 |
91 | And assume our query is something like this:
92 |
93 | ```php
94 | User::filter()->get();
95 | ```
96 |
97 | ### Sort
98 | Sort is the equivalent to `order by` sql statement which can be used flexible in `FilterQueryString`:
99 |
100 | Conventions:
101 |
102 | ```
103 | ?sort=field
104 | ?sort=field,sort_type
105 | ?sort[0]=field1&sort[1]=field2
106 | ?sort[0]=field1&sort[1]=field2,sort_type
107 | ?sort[0]=field1,sort_type&sort[1]=field2,sort_type
108 | ```
109 |
110 | In User.php
111 | ```php
112 | protected $filters = ['sort'];
113 | ```
114 | **Single `sort`**:
115 |
116 | `https://example.com?sort=created_at`
117 |
118 | Output:
119 |
120 | | name | email | username | age | created_at
121 | |:--------:|:--------------------------:|:----------:|:----:|:----------:|
122 | | mehrad | mehrad@example.com | mehrad123 | 20 | 2020-09-01 |
123 | | reza | reza@example.com | reza123 | 20 | 2020-10-01 |
124 | | hossein | hossein@example.com | hossein123 | 22 | 2020-11-01 |
125 | | dariush | dariush@example.com | dariush123 | 22 | 2020-12-01 |
126 |
127 | - **Note** that when you're not defining `sort_type`, It'll be `asc` by default.
128 |
129 | **Multiple `sort`s**:
130 |
131 | `https://example.com?sort[0]=age,desc&sort[1]=created_at,desc`
132 |
133 | Output:
134 |
135 | | name | email | username | age | created_at
136 | |:--------:|:--------------------------:|:----------:|:----:|:----------:|
137 | | dariush | dariush@example.com | dariush123 | 22 | 2020-12-01 |
138 | | hossein | hossein@example.com | hossein123 | 22 | 2020-11-01 |
139 | | reza | reza@example.com | reza123 | 20 | 2020-10-01 |
140 | | mehrad | mehrad@example.com | mehrad123 | 20 | 2020-09-01 |
141 |
142 | **Bare in mind** that `sort` parameter with invalid values will be ignored from query and has no effect to the result.
143 |
144 |
145 | ### Comparisons
146 | Comparisons are consist of 6 filters:
147 | - greater
148 | - greater_or_equal
149 | - less
150 | - less_or_equal
151 | - between
152 | - not_between
153 |
154 | Conventions:
155 |
156 | ```
157 | ?greater=field,value
158 | ?greater_or_equal=field,value
159 | ?less=field,value
160 | ?less_or_equal=field,value
161 | ?between=field,value1,value2
162 | ?not_between=field,value1,value2
163 | ```
164 |
165 | In User.php
166 | ```php
167 | protected $filters = [
168 | 'greater',
169 | 'greater_or_equal',
170 | 'less',
171 | 'less_or_equal',
172 | 'between',
173 | 'not_between'
174 | ];
175 | ```
176 |
177 | **Example of `greater`**:
178 |
179 | `https://example.com?greater=age,20`
180 |
181 | Output:
182 |
183 | | name | email | username | age | created_at
184 | |:--------:|:--------------------------:|:----------:|:----:|:----------:|
185 | | hossein | hossein@example.com | hossein123 | 22 | 2020-11-01 |
186 | | dariush | dariush@example.com | dariush123 | 22 | 2020-12-01 |
187 |
188 | **Example of `not_between`**:
189 |
190 | `https://example.com?not_between=age,21,30`
191 |
192 | Output:
193 |
194 | | name | email | username | age | created_at
195 | |:--------:|:--------------------------:|:----------:|:----:|:----------:|
196 | | mehrad | mehrad@example.com | mehrad123 | 20 | 2020-09-01 |
197 | | reza | reza@example.com | reza123 | 20 | 2020-10-01 |
198 |
199 | **Bare in mind** that comparison parameters with invalid values will be ignored from query and has no effect to the result.
200 |
201 | ### In
202 | In clause is the equivalent to `where in` sql statement.
203 |
204 | Convention:
205 |
206 | ```
207 | ?in=field,value1,value2
208 | ```
209 |
210 | In User.php
211 | ```php
212 | protected $filters = ['in'];
213 | ```
214 | **Example**:
215 |
216 | `https://example.com?in=name,mehrad,reza`
217 |
218 | Output:
219 |
220 | | name | email | username | age | created_at
221 | |:--------:|:--------------------------:|:----------:|:----:|:----------:|
222 | | mehrad | mehrad@example.com | mehrad123 | 20 | 2020-09-01 |
223 | | reza | reza@example.com | reza123 | 20 | 2020-10-01 |
224 |
225 | **Bare in mind** that `in` parameter with invalid values will be ignored from query and has no effect to the result.
226 |
227 | ### Like
228 | Like clause is the equivalent to `like '%value%'` sql statement.
229 |
230 | Conventions:
231 |
232 | ```
233 | ?like=field,value
234 | ?like[0]=field1,value1&like[1]=field2,value2
235 | ```
236 |
237 | In User.php
238 | ```php
239 | protected $filters = ['like'];
240 | ```
241 | **Single `like`**:
242 |
243 | `https://example.com?like=name,meh`
244 |
245 | Output:
246 |
247 | | name | email | username | age | created_at
248 | |:--------:|:--------------------------:|:----------:|:----:|:----------:|
249 | | mehrad | mehrad@example.com | mehrad123 | 20 | 2020-09-01 |
250 |
251 |
252 | **Multiple `like`s**:
253 |
254 | `https://example.com?like[0]=name,meh&like[1]=username,dar`
255 |
256 | Output:
257 |
258 | | name | email | username | age | created_at
259 | |:--------:|:--------------------------:|:----------:|:----:|:----------:|
260 | | mehrad | mehrad@example.com | mehrad123 | 20 | 2020-09-01 |
261 | | dariush | dariush@example.com | dariush123 | 22 | 2020-12-01 |
262 |
263 | **Bare in mind** that `like` parameter with invalid values will be ignored from query and has no effect to the result.
264 |
265 | ### Where Clause (default filter)
266 | Generally when your query string parameters are not one of previous available methods, It'll get filtered by the default filter which is the `where` sql statement. It's the proper filter when you need to directly filter one of your table's columns.
267 |
268 | Conventions:
269 |
270 | ```
271 | ?field=value
272 | ?field1=value&field2=value
273 | ?field1[0]=value1&field1[1]=value2
274 | ?field1[0]=value1&field1[1]=value2&field2[0]=value1&field2[1]=value2
275 | ```
276 |
277 | Assuming we want to filter `name`, `username` and `age` database columns, In User.php
278 | ```php
279 | protected $filters = ['name', 'username', 'age'];
280 | ```
281 | **Example**:
282 |
283 | `https://example.com?name=mehrad`
284 |
285 | Output:
286 |
287 | | name | email | username | age | created_at
288 | |:--------:|:--------------------------:|:----------:|:----:|:----------:|
289 | | mehrad | mehrad@example.com | mehrad123 | 20 | 2020-09-01 |
290 |
291 |
292 | **Example**:
293 |
294 | `https://example.com?age=22&username=dariush123`
295 |
296 | Output:
297 |
298 | | name | email | username | age | created_at
299 | |:--------:|:--------------------------:|:----------:|:----:|:----------:|
300 | | dariush | dariush@example.com | dariush123 | 22 | 2020-12-01 |
301 |
302 |
303 | **Example**:
304 |
305 | `https://example.com?name[0]=mehrad&name[1]=dariush`
306 |
307 | Output:
308 |
309 | | name | email | username | age | created_at
310 | |:--------:|:--------------------------:|:----------:|:----:|:----------:|
311 | | mehrad | mehrad@example.com | mehrad123 | 20 | 2020-09-01 |
312 | | dariush | dariush@example.com | dariush123 | 22 | 2020-12-01 |
313 |
314 | **Example**:
315 |
316 | `https://example.com?name[0]=mehrad&name[1]=dariush&username[0]=mehrad123&username[1]=reza1234`
317 |
318 | Output:
319 |
320 | | name | email | username | age | created_at
321 | |:--------:|:--------------------------:|:----------:|:----:|:----------:|
322 | | mehrad | mehrad@example.com | mehrad123 | 20 | 2020-09-01 |
323 |
324 | **Bare in mind** that `default` filter parameter with invalid values will be ignored from query and has no effect to the result.
325 |
326 | ### Custom Filters
327 | By custom filters you can define your own methods as filters. This helps with the Open/Closed of SOLID principles, Hence each time a new filter is needed, you don't have to edit previous filters and you can just write a separate method for it.
328 |
329 | Let's create a custom filter. Assuming you want to create a filter named `all_except` which retrieves all users except the one that is specified:
330 |
331 | In User.php
332 | ```php
333 | protected $filters = ['all_except'];
334 |
335 | public function all_except($query, $value) {
336 | return $query->where('name', '!=', $value);
337 | }
338 | ```
339 | To test our newly added filter:
340 |
341 | `https://example.com?all_except=mehrad`
342 |
343 | Output:
344 |
345 | | name | email | username | age | created_at
346 | |:--------:|:--------------------------:|:----------:|:----:|:----------:|
347 | | reza | reza@example.com | reza123 | 20 | 2020-10-01 |
348 | | hossein | hossein@example.com | hossein123 | 22 | 2020-11-01 |
349 | | dariush | dariush@example.com | dariush123 | 22 | 2020-12-01 |
350 |
351 | **Note** that your custom defined filters have the most priority which means you can even override available filters.
352 |
353 | For example lets change `in` filter in a way that only accepts 3 values:
354 |
355 | In User.php
356 | ```php
357 | protected $filters = ['in'];
358 |
359 | public function in($query, $value) {
360 |
361 | $exploded = explode(',', $value);
362 |
363 | if(count($exploded) != 4) {
364 | // throwing an exception or whatever you like to do
365 | }
366 |
367 | $field = array_shift($exploded);
368 |
369 | return $query->whereIn($field, $exploded);
370 | }
371 | ```
372 |
373 | **Another** good example for custom filters are when you don't want to expose your database table's column name. For example assume we don't want to expose that we have a column named `username` in `users` table:
374 |
375 | In User.php
376 | ```php
377 | protected $filters = ['by'];
378 |
379 | public function by($query, $value) {
380 | return $query->where('username', $value);
381 | }
382 | ```
383 |
384 | `https://example.com?by=dariush123`
385 |
386 | Output:
387 |
388 | | name | email | username | age | created_at
389 | |:--------:|:--------------------------:|:----------:|:----:|:----------:|
390 | | dariush | dariush@example.com | dariush123 | 22 | 2020-12-01 |
391 |
392 | #### Minor Tip
393 | In order to prevent your model to get messy or populated with filter methods, You can create a trait for it and put everything about filters inside the trait.
394 |
395 | ### Conditional Filters
396 | The `$filters` property in your model is acting kind of global for that model. It means when you use `filter()` method on your eloquent query, it'll always performs all the `$filters` filters.
397 |
398 | There might be situations that based on a condition you need to specify which filters exactly you wish to be filtered.
399 |
400 | To achieve this you can specify your desired filters as arguments in `filter()` method.
401 |
402 | Example:
403 |
404 | In your query:
405 | ```php
406 | User::filter('in')->get();
407 | ```
408 |
409 | `in=name,mehrad,reza&like=name,mehrad`
410 |
411 | Output:
412 |
413 | | name | email | username | age | created_at
414 | |:--------:|:--------------------------:|:----------:|:----:|:----------:|
415 | | mehrad | mehrad@example.com | mehrad123 | 20 | 2020-09-01 |
416 | | reza | reza@example.com | reza123 | 20 | 2020-10-01 |
417 |
418 | If the `in` argument was not specified, The result of query would be only one record (`mehrad`).
419 |
420 | Another example:
421 |
422 | In your query:
423 | ```php
424 | User::filter('like', 'name')->get();
425 | ```
426 |
427 | `like=name,mehrad,reza,dariush,hossein&name[0]=mehrad&name[1]=hossein&username=mehrad`
428 |
429 | Output:
430 |
431 | | name | email | username | age | created_at
432 | |:--------:|:--------------------------:|:----------:|:----:|:----------:|
433 | | mehrad | mehrad@example.com | mehrad123 | 20 | 2020-09-01 |
434 | | hossein | hossein@example.com | hossein123 | 22 | 2020-11-01 |
435 | ----------------------------------------------
436 |
437 | ### Your Stars Matter
438 | If you find this package useful and you want to encourage me to maintain and work on it, Just press the star button to declare your willing.
439 |
440 | ----------------------------------------------
441 |
442 | ### Reward me with a cup of tea :tea:
443 |
444 | Send me as much as a cup of tea worth in your country, so I'll have the energy to maintain this package.
445 |
446 | - Ethereum: 0x2D5BFdEc132F9F0E9498Fb0B58C800db4007D154
447 |
448 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mehradsadeghi/laravel-filter-querystring",
3 | "description": "Filter your queries based on url query string parameters like a breeze.",
4 | "keywords": [
5 | "query",
6 | "query-string",
7 | "querystring",
8 | "filter",
9 | "filter-querystring",
10 | "filter-query-string"
11 | ],
12 | "homepage": "https://github.com/mehradsadeghi/laravel-filter-querystring",
13 | "license": "MIT",
14 | "type": "library",
15 | "authors": [
16 | {
17 | "name": "Mehrad Sadeghi",
18 | "email": "mehrad177@gmail.com",
19 | "role": "Developer"
20 | }
21 | ],
22 | "require": {
23 | "php": "^7.1|^8.0",
24 | "laravel/framework": "5.*|6.*|7.*|8.*|9.*|10.*|11.*|12.*"
25 | },
26 | "require-dev": {
27 | "orchestra/testbench": "^4.0"
28 | },
29 | "autoload": {
30 | "files": [
31 | "helpers/helpers.php"
32 | ],
33 | "psr-4": {
34 | "Mehradsadeghi\\FilterQueryString\\": "src/"
35 | }
36 | },
37 | "autoload-dev": {
38 | "classmap": [
39 | "database"
40 | ],
41 | "psr-4": {
42 | "Mehradsadeghi\\FilterQueryString\\Models\\": "models/",
43 | "Mehradsadeghi\\FilterQueryString\\Tests\\": "tests/"
44 | }
45 | },
46 | "scripts": {
47 | "test": "vendor/bin/phpunit",
48 | "test-coverage": "vendor/bin/phpunit --coverage-html coverage"
49 | }
50 | }
--------------------------------------------------------------------------------
/database/factories/UserFactory.php:
--------------------------------------------------------------------------------
1 | define(User::class, function (Faker $faker) {
9 | return [
10 | 'name' => $faker->name,
11 | 'email' => $faker->unique()->safeEmail,
12 | 'username' => $faker->unique()->userName,
13 | 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
14 | 'age' => $faker->randomNumber(2),
15 | ];
16 | });
17 |
--------------------------------------------------------------------------------
/database/migrations/2020_01_01_000000_create_users_table.php:
--------------------------------------------------------------------------------
1 | bigIncrements('id');
18 | $table->string('name');
19 | $table->string('email')->unique();
20 | $table->string('username')->unique();
21 | $table->string('password');
22 | $table->unsignedTinyInteger('age');
23 | $table->timestamps();
24 | });
25 | }
26 |
27 | /**
28 | * Reverse the migrations.
29 | *
30 | * @return void
31 | */
32 | public function down()
33 | {
34 | Schema::dropIfExists('users');
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/database/seeds/DatabaseSeeder.php:
--------------------------------------------------------------------------------
1 | call(UsersTableSeeder::class);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/database/seeds/UsersTableSeeder.php:
--------------------------------------------------------------------------------
1 | getStub();
16 |
17 | foreach ($users as $user) {
18 | factory(User::class)->create($user);
19 | }
20 | }
21 |
22 | private function getStub()
23 | {
24 | return [
25 | [
26 | 'name' => 'mehrad',
27 | 'email' => 'mehrad@example.com',
28 | 'username' => 'mehrad',
29 | 'age' => 20,
30 | 'created_at' => '2020-09-01',
31 | 'updated_at' => '2020-09-01',
32 | ],
33 | [
34 | 'name' => 'reza',
35 | 'email' => 'reza@example.com',
36 | 'username' => 'reza',
37 | 'age' => 20,
38 | 'created_at' => '2020-10-01',
39 | 'updated_at' => '2020-10-01',
40 | ],
41 | [
42 | 'name' => 'hossein',
43 | 'email' => 'hossein@example.com',
44 | 'username' => 'hossein',
45 | 'age' => 22,
46 | 'created_at' => '2020-11-01',
47 | 'updated_at' => '2020-11-01',
48 | ],
49 | [
50 | 'name' => 'dariush',
51 | 'email' => 'dariush@example.com',
52 | 'username' => 'dariush',
53 | 'age' => 22,
54 | 'created_at' => '2020-12-01',
55 | 'updated_at' => '2020-12-01',
56 | ],
57 | ];
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/helpers/helpers.php:
--------------------------------------------------------------------------------
1 | where('age', '<', 20);
29 | }
30 |
31 | return $query;
32 | }
33 |
34 | public function old($query, $value) {
35 |
36 | if($value == 1) {
37 | $query->where('age', '>', 20);
38 | }
39 |
40 | return $query;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ./tests
6 |
7 |
8 |
9 |
10 | ./app
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/FilterQueryString.php:
--------------------------------------------------------------------------------
1 | WhereClause::class,
16 | 'sort' => OrderbyClause::class,
17 | 'greater' => GreaterThan::class,
18 | 'greater_or_equal' => GreaterOrEqualTo::class,
19 | 'less' => LessThan::class,
20 | 'less_or_equal' => LessOrEqualTo::class,
21 | 'between' => Between::class,
22 | 'not_between' => NotBetween::class,
23 | 'in' => WhereInClause::class,
24 | 'like' => WhereLikeClause::class,
25 | ];
26 |
27 | public function scopeFilter($query, ...$filters)
28 | {
29 | $filters = collect($this->getFilters($filters))->map(function ($values, $filter) {
30 | return $this->resolve($filter, $values);
31 | })->toArray();
32 |
33 | return app(Pipeline::class)
34 | ->send($query)
35 | ->through($filters)
36 | ->thenReturn();
37 | }
38 |
39 | private function getFilters($filters)
40 | {
41 | $filter = function ($key) use($filters) {
42 |
43 | $filters = $filters ?: $this->filters ?: [];
44 |
45 | return $this->unguardFilters != true ? in_array($key, $filters) : true;
46 | };
47 |
48 | return array_filter(request()->query(), $filter, ARRAY_FILTER_USE_KEY) ?? [];
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Filters/BaseClause.php:
--------------------------------------------------------------------------------
1 | values = $values;
16 | $this->filter = $filter;
17 | }
18 |
19 | public function handle($query, $nextFilter)
20 | {
21 | $query = $nextFilter($query);
22 |
23 | if(static::validate($this->values) === false) {
24 | return $query;
25 | }
26 |
27 | return static::apply($query);
28 | }
29 |
30 | abstract protected function apply($query): Builder;
31 |
32 | abstract protected function validate($value): bool;
33 | }
34 |
--------------------------------------------------------------------------------
/src/Filters/ComparisonClauses/BaseComparison.php:
--------------------------------------------------------------------------------
1 | normalizeValues($this->values);
17 |
18 | foreach ($this->normalized as $field => $value) {
19 | $query->{$this->determineMethod($value)}($field, $this->operator, $value);
20 | }
21 |
22 | return $query;
23 | }
24 |
25 | public function validate($value): bool
26 | {
27 | if(is_null($value)) {
28 | return false;
29 | }
30 |
31 | if (!hasComma($value)) {
32 | return false;
33 | }
34 |
35 | return true;
36 | }
37 |
38 | protected function determineMethod($value)
39 | {
40 | return isDateTime($value) ? 'whereDate' : 'where';
41 | }
42 |
43 | protected function normalizeValues($values)
44 | {
45 | [$field, $val] = separateCommaValues($values);
46 | $this->normalized[$field] = $val;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/Filters/ComparisonClauses/Between/Between.php:
--------------------------------------------------------------------------------
1 | normalizeValues($this->values);
12 |
13 | foreach($this->normalized as $field => $values) {
14 | $query->{$this->method}($field, $values);
15 | }
16 |
17 | return $query;
18 | }
19 |
20 | public function validate($value): bool
21 | {
22 | if (count(separateCommaValues($value)) != 3) {
23 | return false;
24 | }
25 |
26 | return true;
27 | }
28 |
29 | protected function normalizeValues($values)
30 | {
31 | [$field, $val1, $val2] = separateCommaValues($values);
32 | $this->normalized[$field] = [$val1, $val2];
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/Filters/ComparisonClauses/Between/NotBetween.php:
--------------------------------------------------------------------------------
1 | =';
8 | }
9 |
--------------------------------------------------------------------------------
/src/Filters/ComparisonClauses/GreaterThan.php:
--------------------------------------------------------------------------------
1 | ';
8 | }
9 |
--------------------------------------------------------------------------------
/src/Filters/ComparisonClauses/LessOrEqualTo.php:
--------------------------------------------------------------------------------
1 | normalizeValues() as $field => $order) {
12 | $query->orderBy($field, $order);
13 | }
14 |
15 | return $query;
16 | }
17 |
18 | public function validate($value): bool {
19 | return !in_array(null, (array)$value);
20 | }
21 |
22 | private function normalizeValues()
23 | {
24 | $normalized = [];
25 |
26 | foreach ((array)$this->values as $value) {
27 |
28 | $exploded = separateCommaValues($value);
29 |
30 | if (!empty($exploded[1]) and in_array($exploded[1], ['asc', 'desc'])) {
31 | $normalized[$exploded[0]] = $exploded[1];
32 | continue;
33 | }
34 |
35 | $normalized[$exploded[0]] = 'asc';
36 | }
37 |
38 | return $normalized;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Filters/WhereClause.php:
--------------------------------------------------------------------------------
1 | values) ? 'orWhere' : 'andWhere';
12 |
13 | return $this->{$method}($query, $this->filter, $this->values);
14 | }
15 |
16 | protected function validate($value): bool {
17 | return !is_null($value);
18 | }
19 |
20 | private function orWhere($query, $filter, $values)
21 | {
22 | $query->where(function($query) use($values, $filter) {
23 | foreach((array)$values as $value) {
24 | $query->orWhere($filter, $value);
25 | }
26 | });
27 |
28 | return $query;
29 | }
30 |
31 | private function andWhere($query, $filter, $values)
32 | {
33 | foreach((array)$values as $value) {
34 | $query->where($filter, $value);
35 | }
36 |
37 | return $query;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/Filters/WhereInClause.php:
--------------------------------------------------------------------------------
1 | normalizeValues();
12 |
13 | return $query->whereIn($field, $values);
14 | }
15 |
16 | public function validate($value): bool
17 | {
18 | if(is_null($value)) {
19 | return false;
20 | }
21 |
22 | if(count(separateCommaValues($value)) < 2) {
23 | return false;
24 | }
25 |
26 | return true;
27 | }
28 |
29 | private function normalizeValues()
30 | {
31 | $elements = separateCommaValues($this->values);
32 | return [array_shift($elements), $elements];
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/Filters/WhereLikeClause.php:
--------------------------------------------------------------------------------
1 | normalizeValues();
12 |
13 | $query->where(function($query) use($normalized) {
14 | foreach ($normalized as $field => $values) {
15 | foreach ($values as $value) {
16 | $query->orWhere($field, 'like', "%$value%");
17 | }
18 | }
19 | });
20 |
21 | return $query;
22 | }
23 |
24 | public function validate($value): bool
25 | {
26 | if (is_null($value)) {
27 | return false;
28 | }
29 |
30 | foreach ((array) $value as $item) {
31 | if(count(separateCommaValues($item)) != 2) {
32 | return false;
33 | }
34 | }
35 |
36 | return true;
37 | }
38 |
39 | private function normalizeValues()
40 | {
41 | $normalized = [];
42 |
43 | foreach ((array) $this->values as $value) {
44 | [$field, $value] = separateCommaValues($value);
45 | $normalized[$field][] = $value;
46 | }
47 |
48 | return $normalized;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Resolvings.php:
--------------------------------------------------------------------------------
1 | isCustomFilter($filterName)) {
10 | return $this->resolveCustomFilter($filterName, $values);
11 | }
12 |
13 | $availableFilter = $this->availableFilters[$filterName] ?? $this->availableFilters['default'];
14 |
15 | return app($availableFilter, ['filter' => $filterName, 'values' => $values]);
16 | }
17 |
18 | private function resolveCustomFilter($filterName, $values)
19 | {
20 | return $this->getClosure($this->makeCallable($filterName), $values);
21 | }
22 |
23 | private function makeCallable($filter)
24 | {
25 | return static::class.'@'.$filter;
26 | }
27 |
28 | private function isCustomFilter($filterName)
29 | {
30 | return method_exists($this, $filterName);
31 | }
32 |
33 | private function getClosure($callable, $values)
34 | {
35 | return function ($query, $nextFilter) use ($callable, $values) {
36 | return app()->call($callable, ['query' => $nextFilter($query), 'value' => $values]);
37 | };
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/tests/CustomFilterTest.php:
--------------------------------------------------------------------------------
1 | get("/?$query");
15 |
16 | $response->assertJsonCount(0);
17 |
18 | $query = 'young=0';
19 |
20 | $response = $this->get("/?$query");
21 |
22 | $response->assertJsonCount(User::count());
23 | }
24 |
25 | /** @test */
26 | public function young_and_old_custom_method()
27 | {
28 | $query = 'young=1&old=1';
29 |
30 | $response = $this->get("/?$query");
31 |
32 | $response->assertJsonCount(0);
33 | }
34 |
35 | /** @test */
36 | public function young_custom_method_and_in()
37 | {
38 | $query = 'young=0&in=name,mehrad';
39 |
40 | $response = $this->get("/?$query");
41 |
42 | $response->assertJsonCount(1);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/tests/CustomParametersTest.php:
--------------------------------------------------------------------------------
1 | filter('in')->get();
15 | });
16 |
17 | $query = 'in=name,mehrad,reza&like=name,mehrad';
18 |
19 | $response = $this->get("/?$query");
20 |
21 | $response->assertJsonCount(2);
22 | }
23 |
24 | /** @test */
25 | public function filter_with_specific_parameters_can_be_performed_correctly2()
26 | {
27 | Route::get('/', function () {
28 | return User::select('name')->filter('like', 'name')->get();
29 | });
30 |
31 | $query = 'like=name,mehrad,reza,dariush,hossein&name[0]=mehrad&name[1]=hossein&username=mehrad';
32 |
33 | $response = $this->get("/?$query");
34 |
35 | $response->assertJsonCount(2);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/tests/Filters/CombinationTest.php:
--------------------------------------------------------------------------------
1 | get("/?$query");
15 | $decodedResponse = $response->decodeResponseJson();
16 |
17 | $response->assertJsonCount(2);
18 | $this->assertEquals('mehrad', $decodedResponse[0]['name']);
19 | }
20 |
21 | /** @test */
22 | public function combination2()
23 | {
24 | $query = 'like[0]=name,meh&like[1]=name,rez&like[2]=name,omi&less=age,21&sort=created_at,desc';
25 |
26 | $response = $this->get("/?$query");
27 | $decodedResponse = $response->decodeResponseJson();
28 |
29 | $response->assertJsonCount(2);
30 | $this->assertEquals('reza', $decodedResponse[0]['name']);
31 | }
32 |
33 | /** @test */
34 | public function combination3()
35 | {
36 | $query = 'greater_or_equal=age,21&sort=created_at,desc';
37 |
38 | $response = $this->get("/?$query");
39 | $decodedResponse = $response->decodeResponseJson();
40 |
41 | $response->assertJsonCount(2);
42 | $this->assertEquals('dariush', $decodedResponse[0]['name']);
43 | }
44 |
45 | /** @test */
46 | public function combination4()
47 | {
48 | $query = 'in=name,mehrad,reza,hossein¬_between=age,22,30&sort=updated_at';
49 |
50 | $response = $this->get("/?$query");
51 | $decodedResponse = $response->decodeResponseJson();
52 |
53 | $response->assertJsonCount(2);
54 | $this->assertEquals('mehrad', $decodedResponse[0]['name']);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/tests/Filters/ComparisonClauses/BetweenTest.php:
--------------------------------------------------------------------------------
1 | get("/?$query");
16 |
17 | $response->assertJsonCount(4);
18 | }
19 |
20 | /** @test */
21 | public function list_of_user_with_age_between_10_and_20()
22 | {
23 | $query = 'between=age,10,20';
24 |
25 | $response = $this->get("/?$query");
26 |
27 | $response->assertJsonCount(2);
28 | }
29 |
30 | /** @test */
31 | public function between_statement_with_invalid_parameters_will_be_ignored()
32 | {
33 | $query = 'between=created_at,2020-11-01';
34 |
35 | $response = $this->get("/?$query");
36 |
37 | $response->assertJsonCount(User::count());
38 |
39 | $query = 'between=created_at';
40 |
41 | $response = $this->get("/?$query");
42 |
43 | $response->assertJsonCount(User::count());
44 |
45 | $query = 'between=';
46 |
47 | $response = $this->get("/?$query");
48 |
49 | $response->assertJsonCount(User::count());
50 |
51 | $query = 'between=created_at,2020-11-01,2020-12-01,2020-09-01';
52 |
53 | $response = $this->get("/?$query");
54 |
55 | $response->assertJsonCount(User::count());
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/tests/Filters/ComparisonClauses/CombinationTest.php:
--------------------------------------------------------------------------------
1 | get("/?$query");
15 |
16 | $response->assertJsonCount(1);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/tests/Filters/ComparisonClauses/GreaterOrEqualTest.php:
--------------------------------------------------------------------------------
1 | get("/?$query");
16 |
17 | $response->assertJsonCount(4);
18 |
19 | $query = 'greater_or_equal=created_at,2020-10-01';
20 |
21 | $response = $this->get("/?$query");
22 |
23 | $response->assertJsonCount(3);
24 | }
25 |
26 | /** @test */
27 | public function greater_or_equal_with_undefined_field_or_value_will_be_ignored()
28 | {
29 | $query = 'greater_or_equal=20';
30 |
31 | $response = $this->get("/?$query");
32 |
33 | $response->assertJsonCount(User::count());
34 |
35 | $query = 'greater_or_equal=age';
36 |
37 | $response = $this->get("/?$query");
38 |
39 | $response->assertJsonCount(User::count());
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/tests/Filters/ComparisonClauses/GreaterThanTest.php:
--------------------------------------------------------------------------------
1 | get("/?$query");
16 |
17 | $response->assertJsonCount(2);
18 |
19 | $query = 'greater=created_at,2020-10-01';
20 |
21 | $response = $this->get("/?$query");
22 |
23 | $response->assertJsonCount(2);
24 | }
25 |
26 | /** @test */
27 | public function greater_than_with_undefined_field_or_value_will_be_ignored()
28 | {
29 | $query = 'greater=20';
30 |
31 | $response = $this->get("/?$query");
32 |
33 | $response->assertJsonCount(User::count());
34 |
35 | $query = 'greater=age';
36 |
37 | $response = $this->get("/?$query");
38 |
39 | $response->assertJsonCount(User::count());
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/tests/Filters/ComparisonClauses/LessOrEqualToTest.php:
--------------------------------------------------------------------------------
1 | get("/?$query");
16 |
17 | $response->assertJsonCount(4);
18 |
19 | $query = 'less_or_equal=created_at,2020-10-01';
20 |
21 | $response = $this->get("/?$query");
22 |
23 | $response->assertJsonCount(2);
24 | }
25 |
26 | /** @test */
27 | public function less_or_equal_with_undefined_field_or_value_will_be_ignored()
28 | {
29 | $query = 'less_or_equal=20';
30 |
31 | $response = $this->get("/?$query");
32 |
33 | $response->assertJsonCount(User::count());
34 |
35 | $query = 'less_or_equal=age';
36 |
37 | $response = $this->get("/?$query");
38 |
39 | $response->assertJsonCount(User::count());
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/tests/Filters/ComparisonClauses/LessThanTest.php:
--------------------------------------------------------------------------------
1 | get("/?$query");
16 |
17 | $response->assertJsonCount(2);
18 |
19 | $query = 'less=created_at,2020-10-01';
20 |
21 | $response = $this->get("/?$query");
22 |
23 | $response->assertJsonCount(1);
24 | }
25 |
26 | /** @test */
27 | public function less_with_undefined_field_or_value_will_be_ignored()
28 | {
29 | $query = 'less=20';
30 |
31 | $response = $this->get("/?$query");
32 |
33 | $response->assertJsonCount(User::count());
34 |
35 | $query = 'less=age';
36 |
37 | $response = $this->get("/?$query");
38 |
39 | $response->assertJsonCount(User::count());
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/tests/Filters/ComparisonClauses/NotBetweenTest.php:
--------------------------------------------------------------------------------
1 | get("/?$query");
16 |
17 | $response->assertJsonCount(2);
18 | }
19 |
20 | /** @test */
21 | public function list_of_user_with_age_not_between_20_and_30()
22 | {
23 | $query = 'not_between=age,20,30';
24 |
25 | $response = $this->get("/?$query");
26 |
27 | $response->assertJsonCount(0);
28 | }
29 |
30 | /** @test */
31 | public function not_between_statement_with_invalid_parameters_will_be_ignored()
32 | {
33 | $query = 'not_between=created_at,2020-11-01';
34 |
35 | $response = $this->get("/?$query");
36 |
37 | $response->assertJsonCount(User::count());
38 |
39 | $query = 'not_between=created_at';
40 |
41 | $response = $this->get("/?$query");
42 |
43 | $response->assertJsonCount(User::count());
44 |
45 | $query = 'not_between=';
46 |
47 | $response = $this->get("/?$query");
48 |
49 | $response->assertJsonCount(User::count());
50 |
51 | $query = 'not_between=created_at,2020-11-01,2020-12-01,2020-09-01';
52 |
53 | $response = $this->get("/?$query");
54 |
55 | $response->assertJsonCount(User::count());
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/tests/Filters/OrderbyClauseTest.php:
--------------------------------------------------------------------------------
1 | get("/?$query");
16 |
17 | $response->assertJsonCount(User::count());
18 | }
19 |
20 | /** @test */
21 | public function a_sort_clause_without_sort_type_can_be_performed_correctly()
22 | {
23 | $query = 'sort=name';
24 |
25 | $response = $this->get("/?$query");
26 |
27 | $decodedResponse = $response->decodeResponseJson();
28 |
29 | $this->assertEquals('dariush', $decodedResponse[0]['name']);
30 | $this->assertEquals('reza', end($decodedResponse)['name']);
31 | }
32 |
33 | /** @test */
34 | public function a_sort_clause_with_sort_type_can_be_performed_correctly()
35 | {
36 | $query = 'sort=name,desc';
37 |
38 | $response = $this->get("/?$query");
39 |
40 | $decodedResponse = $response->decodeResponseJson();
41 |
42 | $this->assertEquals('reza', $decodedResponse[0]['name']);
43 | $this->assertEquals('dariush', end($decodedResponse)['name']);
44 | }
45 |
46 | /** @test */
47 | public function a_sort_clause_with_two_fields_and_without_sort_type_can_be_performed_correctly()
48 | {
49 | $query = 'sort=name,created_at';
50 |
51 | $response = $this->get("/?$query");
52 |
53 | $decodedResponse = $response->decodeResponseJson();
54 |
55 | $this->assertEquals('dariush', $decodedResponse[0]['name']);
56 | $this->assertEquals('reza', end($decodedResponse)['name']);
57 |
58 | $query = 'sort=created_at,name';
59 |
60 | $response = $this->get("/?$query");
61 |
62 | $decodedResponse = $response->decodeResponseJson();
63 |
64 | $this->assertEquals('mehrad', $decodedResponse[0]['name']);
65 | $this->assertEquals('dariush', end($decodedResponse)['name']);
66 | }
67 |
68 | /** @test */
69 | public function a_sort_clause_with_two_fields_and_with_one_sort_type_can_be_performed_correctly()
70 | {
71 | $query = 'sort=name,created_at,desc';
72 |
73 | $response = $this->get("/?$query");
74 |
75 | $decodedResponse = $response->decodeResponseJson();
76 |
77 | $this->assertEquals('dariush', $decodedResponse[0]['name']);
78 | $this->assertEquals('reza', end($decodedResponse)['name']);
79 |
80 | $query = 'sort=created_at,desc,name';
81 |
82 | $response = $this->get("/?$query");
83 |
84 | $decodedResponse = $response->decodeResponseJson();
85 |
86 | $this->assertEquals('dariush', $decodedResponse[0]['name']);
87 | $this->assertEquals('mehrad', end($decodedResponse)['name']);
88 | }
89 |
90 | /** @test */
91 | public function a_sort_clause_with_two_fields_and_with_two_sort_type_can_be_performed_correctly()
92 | {
93 | $query = 'sort[0]=age,desc&sort[1]=name,desc';
94 |
95 | $response = $this->get("/?$query");
96 |
97 | $decodedResponse = $response->decodeResponseJson();
98 |
99 | $this->assertEquals('hossein', $decodedResponse[0]['name']);
100 | $this->assertEquals('mehrad', end($decodedResponse)['name']);
101 |
102 | $query = 'sort[0]=age,desc&sort[1]=created_at,desc';
103 |
104 | $response = $this->get("/?$query");
105 |
106 | $decodedResponse = $response->decodeResponseJson();
107 |
108 | $this->assertEquals('dariush', $decodedResponse[0]['name']);
109 | $this->assertEquals('mehrad', end($decodedResponse)['name']);
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/tests/Filters/WhereClauseTest.php:
--------------------------------------------------------------------------------
1 | get("/?$query");
17 |
18 | $response->assertJsonCount(User::count());
19 | }
20 |
21 | /** @test */
22 | public function a_where_clause_can_be_performed_correctly()
23 | {
24 | $query = 'name=mehrad';
25 |
26 | $response = $this->get("/?$query");
27 |
28 | $response->assertJsonCount(1);
29 | $response->assertJson([['name' => 'mehrad']]);
30 |
31 | $query = 'name=reza';
32 |
33 | $response = $this->get("/?$query");
34 |
35 | $response->assertJsonCount(1);
36 | $response->assertJson([['name' => 'reza']]);
37 | }
38 |
39 | /** @test */
40 | public function two_non_array_will_unite_the_result()
41 | {
42 | $query = 'name=mehrad&username=hossein';
43 |
44 | $response = $this->get("/?$query");
45 |
46 | $response->assertJsonCount(0);
47 |
48 | $query = 'name=mehrad&username=mehrad';
49 |
50 | $response = $this->get("/?$query");
51 |
52 | $response->assertJsonCount(1);
53 | $response->assertJson([['name' => 'mehrad']]);
54 | }
55 |
56 | /** @test */
57 | public function a_where_query_with_wrong_field_name_will_be_ignored()
58 | {
59 | $query = 'wrong_field=mehrad';
60 |
61 | $response = $this->get("/?$query");
62 |
63 | $response->assertJsonCount(User::count());
64 |
65 | $query = 'name=mehrad&wrong_field=hossein';
66 |
67 | $response = $this->get("/?$query");
68 |
69 | $response->assertJsonCount(1);
70 | }
71 |
72 | /** @test */
73 | public function no_query_will_be_performed_without_using_filter_eloquent_method()
74 | {
75 | Route::get('/temp', function () {
76 | return User::select('name')->get();
77 | });
78 |
79 | $query = 'name=mehrad';
80 |
81 | $response = $this->get("/temp?$query");
82 |
83 | $response->assertJsonCount(User::count());
84 | }
85 |
86 | /** @test */
87 | public function two_values_of_one_field_will_union_the_result()
88 | {
89 | $query = 'name[0]=mehrad&name[1]=hossein';
90 |
91 | $response = $this->get("/?$query");
92 |
93 | $response->assertJsonCount(2);
94 | }
95 |
96 | /** @test */
97 | public function two_values_of_two_fields_will_union_internally_and_unite_externally_the_result()
98 | {
99 | $query = 'name[0]=mehrad&name[1]=hossein&username[0]=reza&username[1]=dariush';
100 |
101 | $response = $this->get("/?$query");
102 |
103 | $response->assertJsonCount(0);
104 | }
105 |
106 | /** @test */
107 | public function two_values_of_one_field_and_one_value_of_another_field_will_unite_the_result()
108 | {
109 | $query = 'name[0]=mehrad&name[1]=reza&username=hossein';
110 |
111 | $response = $this->get("/?$query");
112 |
113 | $response->assertJsonCount(0);
114 | }
115 |
116 | /** @test */
117 | public function two_values_of_two_fields_and_one_value_of_another_field_will_unite_the_result()
118 | {
119 | $query = 'name[0]=mehrad&name[1]=reza&username[0]=hossein&username[1]=mehrad&email=mehrad@example.com';
120 |
121 | $response = $this->get("/?$query");
122 |
123 | $response->assertJsonCount(1);
124 |
125 | $query = 'name[0]=mehrad&name[1]=reza&username[0]=hossein&username[1]=mehrad&email=dariush@example.com';
126 |
127 | $response = $this->get("/?$query");
128 |
129 | $response->assertJsonCount(0);
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/tests/Filters/WhereInClauseTest.php:
--------------------------------------------------------------------------------
1 | get("/?$query");
16 |
17 | $response->assertJsonCount(2);
18 | }
19 |
20 | /** @test */
21 | public function wherein_clause_with_empty_field_and_values_will_be_ignored()
22 | {
23 | $query = 'in=';
24 |
25 | $response = $this->get("/?$query");
26 |
27 | $response->assertJsonCount(User::count());
28 | }
29 |
30 | /** @test */
31 | public function wherein_clause_with_empty_values()
32 | {
33 | $query = 'in=name';
34 |
35 | $response = $this->get("/?$query");
36 |
37 | $response->assertJsonCount(User::count());
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/tests/Filters/WhereLikeClauseTest.php:
--------------------------------------------------------------------------------
1 | get("/?$query");
17 |
18 | $response->assertJsonCount(1);
19 | }
20 |
21 | /** @test */
22 | public function two_where_like_clauses_can_be_performed()
23 | {
24 | $query = 'like[0]=name,meh&like[1]=email,reza';
25 |
26 | $response = $this->get("/?$query");
27 |
28 | $response->assertJsonCount(2);
29 |
30 | $query = 'like[0]=name,meh&like[1]=name,rez';
31 |
32 | $response = $this->get("/?$query");
33 |
34 | $response->assertJsonCount(2);
35 | }
36 |
37 | /** @test */
38 | public function where_like_clause_with_invalid_values_will_be_ignored()
39 | {
40 | $query = 'like=';
41 |
42 | $response = $this->get("/?$query");
43 |
44 | $response->assertJsonCount(User::count());
45 |
46 | $query = 'like=name';
47 |
48 | $response = $this->get("/?$query");
49 |
50 | $response->assertJsonCount(User::count());
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/tests/TestCase.php:
--------------------------------------------------------------------------------
1 | loadMigrationsFrom(__DIR__.'/../database/migrations');
15 | $this->withFactories(__DIR__.'/../database/factories');
16 | $this->artisan('db:seed');
17 |
18 | $this->defineDefaultRoute();
19 | }
20 |
21 | private function defineDefaultRoute()
22 | {
23 | Route::get('/', function () {
24 | return User::select('name')->filter()->get();
25 | });
26 | }
27 | }
--------------------------------------------------------------------------------