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

Laravel中Anime表无法更新问题排查与修复求助

问题分析与修复方案

问题背景

当前Laravel项目中,Anime模型的updateAnime方法可正常更新关联表StudioAnime、AuthorAnime,并能在Studio表创建新数据,但无法更新Anime主表。此前直接指定字段的更新代码可正常运行。

现有模型代码:

public function updateAnime(Request $request)
{
    $updatedFields = [];

    $request->validate([
        'title' => ['required'],
        'release_date' => ['required', 'integer'],
        'author' => ['required'],
        'studio' => ['required'],
        'description' => ['required'],
    ]);

    $request->release_date = (int)$request->release_date;
    $animeInfo = Anime::where('title', $request->oldTitle)->with('authors', 'studios')->first();

    $author = Author::firstOrCreate(['author' => $request->author]);
    AuthorAnime::where([
        ['author', $animeInfo->authors[0]->author],
        ['anime', $request->oldTitle]
    ])->update([
        'author' => $author->author,
        'anime' => str_replace(' ', '-', $request->title)
    ]);

    $studio = Studio::firstOrCreate(['studio_name' => $request->studio]);
    StudioAnime::where([
        ['studio', $animeInfo->studios[0]->studio_name],
        ['anime', $request->oldTitle]
    ])->update([
        'studio' => $studio->studio_name,
        'anime' => str_replace(' ', '-', $request->title)
    ]);

    foreach ($request->all() as $key => $value) {
        if (property_exists($animeInfo, $key)) {
            if ($request->$key != $animeInfo->$key) {
                $updatedFields[$key] = $request->$key;
            }
        }
    }

    $animeInfo->update($updatedFields);
    return response()->json(['message' => 'Data was updated successfully. \n Updated data: ' . implode(', ', array_keys($updatedFields))]);
}

控制器调用代码:

$anime = new Anime();
return $anime->updateAnime($request);

此前正常运行的更新代码:

$animeInfo->update([
    'title' => str_replace(' ', '-',$request->title),
    'poster' => $animeInfo->poster,
    'description' => $request->description,
    'release_date' => $request->release_date,
    'trailer' => $animeInfo->trailer,
]);
return response()->json(['message' => 'Data was updated successuflly']);

原因分析

  • property_exists检测逻辑错误:Laravel Eloquent模型的字段属性并非直接挂载在对象实例上,而是存储在$attributes数组中。使用property_exists($animeInfo, $key)无法检测到模型的数据库字段,导致$updatedFields始终为空,最终没有执行主表更新。
  • title字段未做格式转换:关联表更新时将title用str_replace(' ', '-', $request->title)处理,但主表更新的循环中直接使用原始$request->title,即使检测通过也会导致标题格式不一致,且可能不符合数据库存储规则。
  • 请求字段未过滤:$request->all()包含了oldTitle等非Anime表字段,循环时会无效遍历这些字段,进一步导致有效字段未被正确识别。

修复方案

方案1:修正字段检测逻辑并处理title格式

将property_exists替换为Eloquent模型的hasAttribute()方法,同时处理title的格式转换,并过滤非模型字段:

public function updateAnime(Request $request)
{
    $updatedFields = [];

    $request->validate([
        'title' => ['required'],
        'release_date' => ['required', 'integer'],
        'author' => ['required'],
        'studio' => ['required'],
        'description' => ['required'],
    ]);

    $request->release_date = (int)$request->release_date;
    $animeInfo = Anime::where('title', $request->oldTitle)->with('authors', 'studios')->first();

    // 空值判断,避免后续报错
    if (!$animeInfo) {
        return response()->json(['message' => 'Anime not found'], 404);
    }

    // 关联表更新逻辑保留
    $author = Author::firstOrCreate(['author' => $request->author]);
    AuthorAnime::where([
        ['author', $animeInfo->authors[0]->author],
        ['anime', $request->oldTitle]
    ])->update([
        'author' => $author->author,
        'anime' => str_replace(' ', '-', $request->title)
    ]);

    $studio = Studio::firstOrCreate(['studio_name' => $request->studio]);
    StudioAnime::where([
        ['studio', $animeInfo->studios[0]->studio_name],
        ['anime', $request->oldTitle]
    ])->update([
        'studio' => $studio->studio_name,
        'anime' => str_replace(' ', '-', $request->title)
    ]);

    // 提取需要更新的字段,修正检测逻辑
    $allowedFields = ['title', 'release_date', 'description', 'poster', 'trailer']; // 列出Anime表的可更新字段
    foreach ($allowedFields as $key) {
        if ($request->has($key)) {
            $value = $request->$key;
            // 处理title的格式转换
            if ($key === 'title') {
                $value = str_replace(' ', '-', $value);
            }
            if ($value != $animeInfo->$key) {
                $updatedFields[$key] = $value;
            }
        }
    }

    // 如果有更新字段才执行更新
    if (!empty($updatedFields)) {
        $animeInfo->update($updatedFields);
    }

    return response()->json(['message' => 'Data was updated successfully. \n Updated data: ' . implode(', ', array_keys($updatedFields))]);
}

方案2:复用之前的直接指定字段方式(更稳定)

如果不需要动态字段更新,直接沿用之前可正常运行的代码逻辑,避免循环检测的问题:

public function updateAnime(Request $request)
{
    $request->validate([
        'title' => ['required'],
        'release_date' => ['required', 'integer'],
        'author' => ['required'],
        'studio' => ['required'],
        'description' => ['required'],
    ]);

    $request->release_date = (int)$request->release_date;
    $animeInfo = Anime::where('title', $request->oldTitle)->with('authors', 'studios')->first();

    // 空值判断,避免后续报错
    if (!$animeInfo) {
        return response()->json(['message' => 'Anime not found'], 404);
    }

    // 关联表更新逻辑保留
    $author = Author::firstOrCreate(['author' => $request->author]);
    AuthorAnime::where([
        ['author', $animeInfo->authors[0]->author],
        ['anime', $request->oldTitle]
    ])->update([
        'author' => $author->author,
        'anime' => str_replace(' ', '-', $request->title)
    ]);

    $studio = Studio::firstOrCreate(['studio_name' => $request->studio]);
    StudioAnime::where([
        ['studio', $animeInfo->studios[0]->studio_name],
        ['anime', $request->oldTitle]
    ])->update([
        'studio' => $studio->studio_name,
        'anime' => str_replace(' ', '-', $request->title)
    ]);

    // 直接指定字段更新,沿用之前的正常逻辑
    $updatedFields = [
        'title' => str_replace(' ', '-',$request->title),
        'description' => $request->description,
        'release_date' => $request->release_date,
        'poster' => $animeInfo->poster,
        'trailer' => $animeInfo->trailer,
    ];
    $animeInfo->update($updatedFields);

    return response()->json(['message' => 'Data was updated successfully. \n Updated data: title, description, release_date']);
}

额外优化建议

  • 确保Anime模型中设置了正确的$fillable属性,比如:
    protected $fillable = ['title', 'release_date', 'description', 'poster', 'trailer'];
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 13:44:59