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

基于MySQL数据表实现复选框选中状态展示与编辑的技术求助

问题:实现用户游戏选择的全量展示与提交保存

需求说明

我使用两张MySQL数据表:存储游戏列表的Videogames表,以及记录用户已选游戏的videojuegos_tienen_usuarios表。需要实现两个功能:

  • 展示全部可用游戏的复选框,用户已选的游戏复选框默认处于选中状态;
  • 用户可新增选择或取消已选游戏,提交后保存修改。

但现有代码无法实现该效果,附上相关代码和表结构信息寻求帮助。

表结构:videojuegos_tienen_usuarios

该表为用户与游戏的关联中间表,包含字段:user_id(用户ID)、videogames_id(游戏ID)

控制器代码

public function editGamesUser(int $id)
{
$user = Usuario::findOrFail($id);

return view('admin.videojuegos.usuarios', [
user => $user,
]);
}
public function editExecuteGamesUsers(Request $request, int $id)
{
$request->validate(User::VALIDATE_RULES, User::VALIDATE_MESSAGES);

$user = User::findOrFail($id);

$data = $request->except(['_token']);

try {
DB::transaction(function() use ($user, $data) {
$user->update($data);
$user->usersVideogames()->sync($data['videojuegos_tienen_usuarios'] ?? []);
});
return redirect()
->route('admin.videojuegos.users)
->with('statusType', 'success')
->with('statusMessage', 'The videogames were updated.');
} catch(\Exception $e) {
return redirect()
->route('admin.videojuegos.usuarios', ['id' => $id])
->with('statusType', 'danger')
->with('statusMessage', 'Error.')
->withInput();
}
}

Videogame 模型代码

protected $table = 'videogames';
protected $primaryKey = 'videogames_id';
protected $fillable = ['plataforma_id', 'titulo', 'subtitulo', 'precio', 'fecha_estreno', 'sinopsis', 'contenido' , 'portada', 'portada_juego', 'portada_descripcion', 'categoria_id', 'numjugadores_id', 'img_descripcion'];

public function users()
{
return $this->belongsToMany(
User::class,
'videojuegos_tienen_usuarios',
'videogames_id',
'user_id',
'videogames_id',
'user_id',
);
}

User 模型代码

public function usersVideogames()
{
return $this->belongsToMany(Videogames::class, 'usuarios_tienen_videojuegos', 'user_id', 'videogames_id');
}

public function getGameId(): array
{
return $this->videogames->pluck('videogames_id')->toArray();
}

前端HTML代码

目前仅能展示用户已选的游戏,需要修改为展示全部游戏并默认选中已选项:

@foreach($user->usersVideogames as $game)
<div class="form-check form-check-inline">
<input
type="checkbox"
name="videogames[]"
value="{{ $game->videogames_id }}"
@checked($user->usersVideogames)
>
<label for="game-{{ $game->videogames_id }}" class="form-check-label">{{ $game->subtitle }}</label>
</div>
@endforeach

<button type="submit">Update Games</button>

问题修复方案

1. 控制器修改:传递全量游戏数据到视图

当前控制器仅传递用户数据,需新增全量游戏查询并传递给视图,同时预加载用户已选游戏避免N+1查询:

public function editGamesUser(int $id)
{
$user = Usuario::findOrFail($id);
// 查询所有游戏
$allGames = Videogames::all();
// 预加载用户已选游戏
$user->load('usersVideogames');

return view('admin.videojuegos.usuarios', [
'user' => $user,
'allGames' => $allGames
]);
}

2. 模型关联修正

User模型中关联的中间表名错误,需改为实际表名videojuegos_tienen_usuarios;同时getGameId方法关联名称错误,需改为usersVideogames:

public function usersVideogames()
{
return $this->belongsToMany(Videogames::class, 'videojuegos_tienen_usuarios', 'user_id', 'videogames_id');
}

public function getGameId(): array
{
return $this->usersVideogames->pluck('videogames_id')->toArray();
}

3. 前端HTML修改:遍历全量游戏并判断选中状态

将遍历用户已选游戏改为遍历所有游戏,通过in_array判断当前游戏是否在用户已选列表中,同时补全input的id属性与label的for属性对应:

@foreach($allGames as $game)
<div class="form-check form-check-inline">
<input
type="checkbox"
name="videogames[]"
id="game-{{ $game->videogames_id }}"
value="{{ $game->videogames_id }}"
@checked(in_array($game->videogames_id, $user->getGameId()))
>
<label for="game-{{ $game->videogames_id }}" class="form-check-label">{{ $game->subtitulo }}</label>
</div>
@endforeach

<button type="submit">更新游戏选择</button>

4. 提交逻辑修正

控制器中sync方法的参数需与前端input的name对应(前端name为videogames[]),同时修正路由名称的语法错误:

$user->usersVideogames()->sync($data['videogames'] ?? []);

// 修正redirect的路由引号
return redirect()
->route('admin.videojuegos.users')
->with('statusType', 'success')
->with('statusMessage', '游戏选择已更新。');

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 06:37:36