mysql - Laravel JOIN SQLSTATE [23000] 的问题:违反完整性约束:1052 字段列表中的列 'album_id' 不明确
问题描述
我已经引用了像我这样的其他问题,但我无法弄清楚为什么在我的示例中会出现错误。
我有 3 张桌子。nn_album 、 nn_song 和数据透视表 nn_song_album_song
我的表 ID 名称是 nn_album.album_id , nn_song.song_id ,数据透视表有 id 作为主键和相同的列名“song_id”和“album_id”
我可以添加专辑,但是当我想在专辑中添加新歌时,保存功能出现此错误...
SQLSTATE [23000]:完整性约束违规:1052 字段列表中的列 'album_id' 不明确(SQL:
album_id
从nn_album
内部连接nn_song_album_song
中选择nn_album
。album_id
=nn_song_album_song
. = 21)album_id
nn_song_album_song
song_id
我的歌曲模型
public function albums()
{
return $this->belongsToMany('App\Albums', 'nn_song_album_song', 'song_id', 'album_id');
}
我的专辑模特
public function songs()
{
return $this->belongsToMany('App\SongDetail', 'nn_song_album_song', 'song_id', 'album_id');
}
我的控制器保存功能
$albums = request('albums');
if ($song_id>0)
{
$entry = SongDetail::where('song_id', $song_id)->firstOrfail();
$entry->update($data);
$entry->albums()->sync($albums);
}
else
{
$entry = SongDetail::create($data);
$entry->albums()->attach($albums);
}
我在管理员端的视图用于选择专辑输入(我可以选择要添加的多个专辑)
<div class="form-group form-float mainalbum" style="margin-bottom: 45px;border-bottom: solid 1px;">
<div class="form-line">
<select class="form-control show-tick" name="albums[]" id="albums" data-live-search="true" >
@foreach($albums as $album)
@if($album->album_id != 1)<option value="{{ $album->album_id }}" {{ collect(old('albums', $album))->contains($album->album_id) ? 'selected': '' }}>
{{ $album->album_name }}</option>@endif
@endforeach
</select>
<select class="albums2" name="albums2[]" id="albums2" multiple>
@foreach($albums as $album)
@if($album->album_id != 1)<option value="{{ $album->album_id }}" {{ collect(old('albums', $album))->contains($album->album_id) ? 'selected': '' }}>
{{ $album->album_name }}</option>@endif
@endforeach
</select>
</div>
</div>
你知道这里发生了什么吗?我的错是什么?如果你和我分享你的想法,我很感激你。
谢谢你。
解决方案
好吧,通过根据 Laravel 约定命名所有内容,您确实使事情变得比您需要的要复杂得多。如果按预期进行设置,您将拥有名为Album
和的模型Song
,存储在数据库表albums
和songs
中,并带有一个名为 的数据透视表album_song
。那时事情会容易得多。
但是,如果阅读文档,则可以解决这些约定:
如前所述,为了确定关系连接表的表名,Eloquent 会按字母顺序连接两个相关模型名。但是,您可以随意覆盖此约定。您可以通过将第二个参数传递给该
belongsToMany
方法来做到这一点。除了自定义连接表的名称外,您还可以通过向
belongsToMany
方法传递附加参数来自定义表上键的列名。第三个参数是定义关系的模型的外键名称,而第四个参数是要加入的模型的外键名称。
所以,修正你的论点,我们得到:
class SongDetail extends Model
{
public function albums()
{
return $this->belongsToMany('App\Albums', 'nn_song_album_song', 'song_id', 'album_id');
}
}
class Albums extends Model
{
public function songs()
{
return $this->belongsToMany('App\SongDetail', 'nn_song_album_song', 'album_id', 'song_id');
}
}
哪个应该正确定义关系。你的控制器再次违反惯例,因为 Laravel 资源控制器通常定义了单独的存储和更新方法。但我可以提出一个建议来清理您显示的代码:
$albums = request('albums');
try {
$entry = SongDetail::findOrFail($song_id);
$entry->update($data);
} catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
$entry = SongDetail::create($data);
}
$entry->albums()->sync($albums);
在您看来,如果您想传递一个值数组,您需要multiple
在<select>
元素上指定。