railken / eloquent-mapper
Requires
- php: >=8.1
- ankurk91/laravel-eloquent-relationships: ^2.1
- railken/bag: ^2.0
- railken/lara-eye: 3.*
- ramsey/collection: ^2.0
Requires (Dev)
- dev-master
- v0.4.4
- v0.4.3
- v0.4.2
- v0.4.1
- v0.4
- v0.3.5
- v0.3.4
- v0.3.3
- v0.3.2
- v0.3.1
- v0.3.0
- v0.2.3
- v0.2.2
- v0.2.1
- v0.2.0
- v0.1.38
- V0.1.37
- v0.1.36
- v0.1.35
- v0.1.34
- v0.1.33
- v0.1.32
- v0.1.31
- v0.1.30
- v0.1.29
- v0.1.28
- v0.1.27
- v0.1.26
- v0.1.25
- v0.1.24
- v0.1.23
- v0.1.22
- v0.1.21
- v0.1.20
- v0.1.19
- v0.1.18
- v0.1.17
- v0.1.16
- v0.1.15
- v0.1.14
- v0.1.13
- v0.1.12
- v0.1.11
- v0.1.10
- v0.1.9
- v0.1.8
- v0.1.7
- v0.1.6
- v0.1.5
- v0.1.4
- v0.1.3
- v0.1.2
- v0.1.1
- v0.1.0
This package is auto-updated.
Last update: 2024-08-28 20:24:47 UTC
README
一个Laravel包,利用关系的全部力量来创建自动连接并执行高级筛选。
例如,对于两个模型 Office
和 Employee
,你可以将如下字符串转换为这样的SQL查询:
select offices.* from `offices` left join `employees` as `employees` on `employees`.`office_id` = `offices`.`id` where (`employees`.`name` like ? or `employees`.`name` like ?)
功能
- 自动连接你的关系
- 使用复杂逻辑表达式筛选查询 lara-eye
- 添加缺失的关系 laravel-eloquent-relationships
需求
PHP 8.1和laravel 8
安装
你可以通过以下命令使用Composer安装它:
composer require railken/eloquent-mapper
使用方法
为了使用这个库,你需要一个映射。
在你想创建的地方创建一个新类,如下面的示例所示
app/Map.php
namespace App; use Railken\EloquentMapper\Map as BaseMap; class Map extends BaseMap { /** * Return an array of all models you want to map * * @return array */ public function models(): array { /** return [ \App\Models\User::class ]; **/ } }
方法 models
必须返回所有模型列表。你甚至可以添加位于你的vendor文件夹中的模型,无论你使用什么逻辑,你只需返回一个数组。
Railken\EloquentMapper\Map
还基于模型提供关系的映射和属性映射,如果你希望,你可以覆盖该功能并编写自己的。 查看源代码
这些方法仅在调用 artisan mapper:generate
命令(见下文)时调用,并将结果缓存到位于 bootstrap/cache/map.php
的文件中。
这意味着你可以执行任何逻辑来检索所有模型(例如扫描文件),因此请放心缓存。
重要:为了被检测到,所有关系都必须返回类型 Illuminate\Database\Eloquent\Relations\Relation
,如下所示
namespace App; use Illuminate\Database\Eloquent\Relations\BelongsTo; class Foo extends Model { /** * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function bar(): BelongsTo { return $this->belongsTo(Bar::class); } }
现在是将这个类注册到任何提供者中以覆盖默认类的时候了。
app/Providers/AppServiceProvider.php
namespace App\Providers; use Illuminate\Support\ServiceProvider; use App\Map; use Railken\EloquentMapper\Contracts\Map as MapContract; class AppServiceProvider extends ServiceProvider { /** * @inherit */ public function register() { $this->app->bind(MapContract::class, Map::class); } }
Artisan
只有一个命令,就是 artisan mapper:generate
。这个命令将重新映射并重新缓存,所以请记住,每次你更改代码模型时都必须执行它。
如果你使用位于你的vendor文件夹中的模型,你可以在 composer.json
中添加以下内容,以便在库更新时重新加载。
{ "scripts": { "post-autoload-dump": [ "@php artisan mapper:generate" ] } }
筛选
看看筛选是如何实际工作的?
use Railken\EloquentMapper\Scopes\FilterScope; use Railken\EloquentMapper\With\WithCollection; use Railken\EloquentMapper\With\WithItem; use App\Models\Foo; $foo = new Foo; $query = $foo->newQuery(); $filter = "created_at >= 2019"; $scope = new FilterScope; $scope->apply($query, $filter, new WithCollection([ new WithItem('bar') ]));
就是这样! $query
现在已经被筛选,如果 Foo
有任何关系,你可以使用点表示法,筛选将自动执行连接。例如,如果 Foo
有一个名为 tags
的关系,并且你想检索所有标签名为 myCustomTag
的 Foo
,只需使用 tag.name = 'myCustomTag'
。
这里是 完整语法
第三个参数是预加载选项。你当然可以使用点表示法,并添加子查询。例如,以下示例表示一个包含名称 Mario
的所有作者列表,并返回所有具有名为 tag.name
的 sci-fi
的书籍。
use Railken\EloquentMapper\Scopes\FilterScope; use Railken\EloquentMapper\With\WithCollection; use Railken\EloquentMapper\With\WithItem; use Railken\EloquentMapper\Tests\Models\Author; $author = new Author; $query = $author->newQuery(); $filter = "name ct 'Mario'"; $scope = new FilterScope; $scope->apply($query, $filter, new WithCollection([ new WithItem('books', 'tag.name eq "sci-fi"') ]));
连接器
这是一个内部类,由FilterScope
在执行过滤前连接必要的关联关系使用,但您也可以独立使用它。查看测试
示例 - 设置
让我们用一个真实例子来继续,首先是设置。我们将使用两个模型:Office
和Employee
app/Models/Office.php
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; class Office extends Model { /** * @var array */ public $fillable = [ 'name', 'description' ]; /** * @return \Illuminate\Database\Eloquent\Relations\HasMany */ public function employees(): HasMany { return $this->hasMany(Employee::class); } }
app/Models/Employee.php
namespace App\Models; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use App\Models\Office; class Employee extends Model { /** * @var array */ public $fillable = [ 'name', 'description', 'office_id' ]; /** * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function office(): BelongsTo { return $this->belongsTo(Office::class); } }
app/Map.php
namespace App; use Railken\EloquentMapper\Map as BaseMap; class Map extends BaseMap { /** * Return an array of all models you want to map * * @return array */ public function models(): array { return [ \App\Models\Employee::class, \App\Models\Office::class ]; } }
示例 - 使用
检索所有有名为Mario Rossi
或Giacomo
的员工的办公室
use App\Models\Office; use Railken\EloquentMapper\Scopes\FilterScope; $office = new Office; $query = $office->newQuery(); $filter = "employees.name ct 'Mario Rossi' or employees.name ct 'Giacomo'" $scope = new FilterScope(); $scope->apply($query, $filter); echo $query->toSql();
结果
select offices.* from `offices` left join `employees` as `employees` on `employees`.`office_id` = `offices`.`id` where (`employees`.`name` like ? or `employees`.`name` like ?)