Skip to content

Commit 9a0ae11

Browse files
committed
Added support for scopes
Signed-off-by: Gertjan Roke <[email protected]>
1 parent 675894b commit 9a0ae11

File tree

9 files changed

+88
-10
lines changed

9 files changed

+88
-10
lines changed

.github/FUNDING.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
github: :vendor_name
1+
github: GertjanRoke

.github/ISSUE_TEMPLATE/config.yml

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
blank_issues_enabled: false
22
contact_links:
3-
- name: Ask a question
4-
url: https://github.com/:vendor_slug/:package_slug/discussions/new?category=q-a
5-
about: Ask the community for help
63
- name: Request a feature
7-
url: https://github.com/:vendor_slug/:package_slug/discussions/new?category=ideas
4+
url: https://github.com/GertjanRoke/laravel-db-model/issues/new
85
about: Share ideas for new features
96
- name: Report a bug
10-
url: https://github.com/:vendor_slug/:package_slug/issues/new
7+
url: https://github.com/GertjanRoke/laravel-db-model/issues/new
118
about: Report a reproducable bug

.github/SECURITY.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# Security Policy
22

3-
If you discover any security related issues, please email author@domain.com instead of using the issue tracker.
3+
If you discover any security related issues, please email g.a.roke90@gmail.com instead of using the issue tracker.

README.md

+59-1
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,68 @@ use GertjanRoke\LaravelDbModel\DBModel;
2626

2727
class Post extends DBModel
2828
{
29-
public $table = 'posts';
29+
// public $table = 'posts';
3030

3131
// public $connection = 'mysql';
3232
}
33+
```
34+
If no table name was given it will guess it based on the class name just like the Eloquent model those.
35+
Same for the connection, if none is set it will use the default connection.
36+
37+
## How to extend custom scopes
38+
It's basically the same as for Eloquent models, you would need to prefix the methods with `scope`
39+
```php
40+
...
41+
42+
class Post extends DBModel
43+
{
44+
public function scopeActive()
45+
{
46+
$this->db->where('active', true);
47+
48+
return $this;
49+
}
50+
}
51+
```
52+
53+
## Some examples
54+
55+
You can easly create short functions for basic where's or even more complex queries so you have it always in one location instead of everywhere in your code base.
56+
```php
57+
<?php
58+
59+
namespace App\Models;
60+
61+
use App\Models\Comment;
62+
use GertjanRoke\LaravelDbModel\DBModel;
63+
64+
class Post extends DBModel
65+
{
66+
public function scopeActive(): self
67+
{
68+
$this->db->where('active', true);
69+
70+
return $this;
71+
}
72+
73+
public function scopeWithLatestComment(): self
74+
{
75+
$postTable = $this->getTable();
76+
$commentTable = (new Comment())->getTable();
77+
78+
$this->db->join($commentTable, "{$commentTable}.post_id", '=', "{$postTable}.id")
79+
->addSelect("{$commentTable}.body");
80+
81+
return $this;
82+
}
83+
}
84+
85+
// Inside your controller
86+
$post = Post::active()->withLatestComment()->latest()->first();
87+
88+
// Keep in mind the order of calling methods doesn't matter as long as the method before returned the builder instance.
89+
// Like this example will return the same result as the query above.
90+
$post = Post::active()->latest()->withLatestComment()->first();
3391

3492
```
3593

composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
},
4141
"scripts": {
4242
"test": "./vendor/bin/pest --no-coverage",
43-
"test-coverage": "vendor/bin/phpunit --coverage-html coverage"
43+
"test-coverage": "./vendor/bin/pest --coverage-html coverage"
4444
},
4545
"config": {
4646
"sort-packages": true

src/DBModel.php

+5
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,11 @@ public function getDB(): Builder
5050
*/
5151
public function __call($method, $parameters)
5252
{
53+
$scopeMethod = (string) Str::of($method)->ucfirst()->prepend('scope');
54+
if (method_exists(static::class, $scopeMethod)) {
55+
return $this->$scopeMethod(...$parameters);
56+
}
57+
5358
$response = $this->db->$method(...$parameters);
5459

5560
return ($response instanceof Builder) ? $this : $response;

tests/MethodCallingTest.php

+12
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,15 @@
2121

2222
expect($returned)->toBeInstanceOf(Collection::class);
2323
});
24+
25+
it("doesn't matter in which order you call the query methods", function () {
26+
$grammer = (new Model())->getDB()->grammar;
27+
28+
$query = Model::where('title', 'Hello World')->active()->toSql();
29+
30+
expect($query)->toEndWith($grammer->wrap('title') . ' = ? and ' . $grammer->wrap('active') . ' = ?');
31+
32+
$query = Model::active()->where('title', 'Hello World')->toSql();
33+
34+
expect($query)->toEndWith($grammer->wrap('active') . ' = ? and ' . $grammer->wrap('title') . ' = ?');
35+
});

tests/Models/Model.php

+6-1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,10 @@
66

77
class Model extends DBModel
88
{
9-
public $table = 'models';
9+
public function scopeActive(): self
10+
{
11+
$this->db->where('active', true);
12+
13+
return $this;
14+
}
1015
}

tests/migrations/ModelTableMigration.php

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ public function up()
1212
Schema::create('models', function(Blueprint $table) {
1313
$table->id();
1414
$table->string('title')->nullable();
15+
$table->boolean('active')->default(false);
1516
$table->timestamps();
1617
});
1718
}

0 commit comments

Comments
 (0)