将查询构建的一部分重构为 Eloquent 模型,并使其可与其他构建器链接
Refactor a section of query-building to the Eloquent model and make it chainable with other Builders
我想重构以下代码中的 withCount
部分以重用它并缩短控制器。
class GroupController extends Controller
{
public function show(int $group = 1)
{
return Group::where('id', '>', 0) // to simulate starting the query with some builder
->withCount([
"requests",
'requests AS requests_count_pending' => function ($query) {
$query->where('state', 'pending');
},
'requests AS requests_count_accepted' => function ($query) {
$query->where('state', 'accepted');
},
'requests AS requests_count_refused' => function ($query) {
$query->where('state', 'refused');
}
])
->find($group);
}
}
我想使用以下语法构建查询:
$group = Group::where('id', '>', 0)
::withCountRequests()
->find($group);
我试过的(补丁)
public static function withRequestsCount()
{
return self::withCount([
"requests",
'requests AS requests_count_pending' => function ($query) {
$query->where('state', 'pending');
},
'requests AS requests_count_accepted' => function ($query) {
$query->where('state', 'accepted');
},
'requests AS requests_count_refused' => function ($query) {
$query->where('state', 'refused');
}
]);
}
public function show(int $group = 1)
{
return Group::withRequestsCount()
->where('id', '>', 0)
->find($group);
}
该解决方案仅在我首先调用静态方法时有效。但我想像其他任何东西一样流畅地链接它 Builder
正在复制
php .\artisan make:model -mcrf Group
php .\artisan make:model -mcrf Request
迁移
public function up(): void
{
Schema::create('groups', function (Blueprint $table) {
$table->id();
$table->timestamps();
});
}
public function up(): void
{
Schema::create('requests', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->set('state', ['pending', 'accepted', 'refused']);
$table->foreignId('group_id');
});
}
型号
class Group extends Model
{
use HasFactory;
public function requests()
{
return $this->hasMany(Request::class);
}
}
工厂和播种机
class RequestFactory extends Factory
{
public function definition(): array
{
return [
'group_id' => 1,
'state' => $this->faker->randomElement(['pending', 'accepted', 'refused']),
];
}
}
class DatabaseSeeder extends Seeder
{
public function run()
{
DB::table('groups')->insertOrIgnore(['id' => 1]);
Request::factory(50)->create();
}
}
路线
Route::get('the_group', [GroupController::class, 'show']);
使用查询范围。它类似于您尝试使用 withRequestCount
函数。
public static function scopeWithRequestsCount($query)
{
return $query->withCount([
"requests",
'requests AS requests_count_pending' => function ($query) {
$query->where('state', 'pending');
},
'requests AS requests_count_accepted' => function ($query) {
$query->where('state', 'accepted');
},
'requests AS requests_count_refused' => function ($query) {
$query->where('state', 'refused');
}
]);
}
我想重构以下代码中的 withCount
部分以重用它并缩短控制器。
class GroupController extends Controller
{
public function show(int $group = 1)
{
return Group::where('id', '>', 0) // to simulate starting the query with some builder
->withCount([
"requests",
'requests AS requests_count_pending' => function ($query) {
$query->where('state', 'pending');
},
'requests AS requests_count_accepted' => function ($query) {
$query->where('state', 'accepted');
},
'requests AS requests_count_refused' => function ($query) {
$query->where('state', 'refused');
}
])
->find($group);
}
}
我想使用以下语法构建查询:
$group = Group::where('id', '>', 0)
::withCountRequests()
->find($group);
我试过的(补丁)
public static function withRequestsCount()
{
return self::withCount([
"requests",
'requests AS requests_count_pending' => function ($query) {
$query->where('state', 'pending');
},
'requests AS requests_count_accepted' => function ($query) {
$query->where('state', 'accepted');
},
'requests AS requests_count_refused' => function ($query) {
$query->where('state', 'refused');
}
]);
}
public function show(int $group = 1)
{
return Group::withRequestsCount()
->where('id', '>', 0)
->find($group);
}
该解决方案仅在我首先调用静态方法时有效。但我想像其他任何东西一样流畅地链接它 Builder
正在复制
php .\artisan make:model -mcrf Group
php .\artisan make:model -mcrf Request
迁移
public function up(): void
{
Schema::create('groups', function (Blueprint $table) {
$table->id();
$table->timestamps();
});
}
public function up(): void
{
Schema::create('requests', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->set('state', ['pending', 'accepted', 'refused']);
$table->foreignId('group_id');
});
}
型号
class Group extends Model
{
use HasFactory;
public function requests()
{
return $this->hasMany(Request::class);
}
}
工厂和播种机
class RequestFactory extends Factory
{
public function definition(): array
{
return [
'group_id' => 1,
'state' => $this->faker->randomElement(['pending', 'accepted', 'refused']),
];
}
}
class DatabaseSeeder extends Seeder
{
public function run()
{
DB::table('groups')->insertOrIgnore(['id' => 1]);
Request::factory(50)->create();
}
}
路线
Route::get('the_group', [GroupController::class, 'show']);
使用查询范围。它类似于您尝试使用 withRequestCount
函数。
public static function scopeWithRequestsCount($query)
{
return $query->withCount([
"requests",
'requests AS requests_count_pending' => function ($query) {
$query->where('state', 'pending');
},
'requests AS requests_count_accepted' => function ($query) {
$query->where('state', 'accepted');
},
'requests AS requests_count_refused' => function ($query) {
$query->where('state', 'refused');
}
]);
}