我想计算每个评论对某个任务有多少个文件。我有一个 Laravel 项目(项目管理应用程序),具有以下模型:Project、Board、Task、Comment、File。以下是每个模型中定义的关系。
// 项目模型
<?php
namespace App\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\DB;
class Project extends Model
{
use HasFactory;
protected $fillable = [
'name',
'description',
'due_date',
'created_by',
'contact_id',
'status',
];
public function boards(): HasMany
{
return $this->hasMany(Board::class);
}
public function files()
{
return $this->morphMany(File::class, 'fileable');
}
protected static function boot()
{
parent::boot();
static::creating(function ($project) {
$project->pid = Str::orderedUuid();
});
static::updating(function ($project) {
if (!isset($project->pid)) {
$project->pid = Str::orderedUuid();
}
});
}
}
// 板模型
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Board extends Model
{
use HasFactory;
protected $fillable = [
'name',
'project_id',
];
public function project(): BelongsTo
{
return $this->belongsTo(Project::class);
}
public function tasks(): HasMany
{
return $this->hasMany(Task::class);
}
}
// *任务模型
<?php
namespace App\Models;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Stevebauman\Purify\Casts\PurifyHtmlOnGet;
class Task extends Model
{
use HasFactory;
protected $fillable = [
'name',
'description',
'assigned_to',
'board_id',
'position',
'priority'
];
public function board(): BelongsTo
{
return $this->belongsTo(Board::class);
}
public function comments(): HasMany
{
return $this->hasMany(Comment::class);
}
public function files(): HasManyThrough
{
return $this->hasManyThrough(
File::class,
Comment::class,
'id',
'model_id',
'id',
'id'
)->where('model_type', Comment::class);
}
}
// 评论模型
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Comment extends Model
{
use HasFactory;
protected $fillable = [
'body',
'task_id',
'user_id',
];
public function task()
{
return $this->belongsTo(Task::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
public function files()
{
return $this->morphMany(File::class, 'model');
}
}
// 文件模型
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
class File extends Model
{
use HasFactory;
protected $guarded = [];
public function model(): MorphTo
{
return $this->morphTo();
}
protected static function boot()
{
parent::boot();
static::creating(function ($file) {
$file->fid = Str::orderedUuid();
});
static::updating(function ($file) {
if (!isset($file->fid)) {
$file->fid = Str::orderedUuid();
}
});
}
}
我尝试过:
$project->load([
'boards.tasks.user',
'boards.tasks.comments.user',
'boards.tasks.comments.files',
'boards.tasks' => function ($query) {
$query->withCount('comments');
},
'boards.tasks.comments' => function ($query) {
$query->withCount('files');
}
])
但它不返回files_count,只显示了comments_count。
我也尝试过
$project->load([
'boards.tasks.user',
'boards.tasks.comments.user',
'boards.tasks.comments.files',
'boards.tasks' => function ($query) {
$query->withCount(['comments', 'files']); // trying to ustilize the **hasManyThrough**
},
])
但它仍然没有返回 files_count,只显示 comments_count。
经过多次尝试和思考,我找到了解决方案。解决办法如下:
<?php
namespace App\Http\Controllers\Projects;
use App\Data\ProjectFullData;
use App\Http\Controllers\Controller;
use App\Models\Comment;
use App\Models\Project;
use Illuminate\Support\Facades\DB;
use Inertia\Inertia;
class Show extends Controller
{
public function __invoke(Project $project)
{
$project = ProjectFullData::from(
$project->load([
'contact.firm',
'contact.emails',
'boards.tasks.user',
'boards.tasks.comments.user',
'boards.tasks.comments.files',
'boards.tasks' => function ($query) {
$query->withCount(['comments', 'files']);
},
])
);
return Inertia::render('Projects/Show', [
'project' => $project
]);
}
}
我在评论中添加了
withCount
,并在一个子查询中添加了files