基于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
相关产品推荐
相关产品推荐

