You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Laravel morphMany关联字段设置非数据库层默认值

方案1:使用makeUsing关联钩子(推荐,兼容Laravel 5.8+)

该方案无需修改调用逻辑,完全符合你需要的$post->images()->create()调用方式,仅修改Post模型的关联定义即可:

class Post{
    public function videos(){
        return $this->morphMany(File::class, 'filable')
                    ->where('type', File::VIDEO_TYPE)
                    // 新增以下代码,创建实例时自动注入type属性
                    ->makeUsing(fn ($attributes) => new File(array_merge($attributes, ['type' => File::VIDEO_TYPE])));
    }

    public function images(){
        return $this->morphMany(File::class, 'filable')
                    ->where('type', File::IMAGE_TYPE)
                    // 新增以下代码,创建实例时自动注入type属性
                    ->makeUsing(fn ($attributes) => new File(array_merge($attributes, ['type' => File::IMAGE_TYPE])));
    }
}

makeUsing是Laravel关联提供的原生方法,会在调用关联的make()、create()、createMany()生成File实例前触发,自动把对应type合并到属性中,不会影响原有查询功能。


方案2:封装创建辅助方法(兼容所有Laravel版本)

如果你使用的Laravel版本不支持makeUsing,可以直接在Post模型中新增专用创建方法,调用逻辑更简洁:

class Post{
    // 保留原有关联定义
    public function videos(){
        return $this->morphMany(File::class, 'filable')
                    ->where('type', File::VIDEO_TYPE);
    }

    public function images(){
        return $this->morphMany(File::class, 'filable')
                    ->where('type', File::IMAGE_TYPE);
    }

    // 新增创建辅助方法
    public function createImage(array $attributes)
    {
        return $this->images()->create(array_merge($attributes, [
            'type' => File::IMAGE_TYPE
        ]));
    }

    public function createVideo(array $attributes)
    {
        return $this->videos()->create(array_merge($attributes, [
            'type' => File::VIDEO_TYPE
        ]));
    }
}

调用方式:

$post->createImage(['path' => 'my-image.jpg']);
$post->createVideo(['path' => 'my-video.mp4']);

方案3:抽离通用Trait(多模型复用时推荐)

如果系统内还有其他模型(比如文章、用户等)也需要关联File模型,可以把逻辑抽成通用Trait,避免重复编码:

  1. 首先定义通用Trait
trait HasFiles
{
    public function fileRelation(string $type)
    {
        return $this->morphMany(File::class, 'filable')
                    ->where('type', $type)
                    ->makeUsing(fn ($attributes) => new File(array_merge($attributes, ['type' => $type])));
    }

    public function images()
    {
        return $this->fileRelation(File::IMAGE_TYPE);
    }

    public function videos()
    {
        return $this->fileRelation(File::VIDEO_TYPE);
    }

    public function audios()
    {
        return $this->fileRelation(File::AUDIO_TYPE);
    }

    public function applications()
    {
        return $this->fileRelation(File::APPLICATION_TYPE);
    }
}
  1. 在Post模型中引入Trait即可
class Post
{
    use HasFiles;

    // 不需要再手动编写各类文件关联方法
}

内容的提问来源于stack exchange,提问作者unnoq

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 21:09:02