首页 > 解决方案 > 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_idnn_album内部连接nn_song_album_song中选择nn_albumalbum_id= nn_song_album_song. = 21)album_idnn_song_album_songsong_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>

你知道这里发生了什么吗?我的错是什么?如果你和我分享你的想法,我很感激你。

谢谢你。

标签: mysqllaraveleloquentpivot-table

解决方案


好吧,通过根据 Laravel 约定命名所有内容,您确实使事情变得比您需要的要复杂得多。如果按预期进行设置,您将拥有名为Album和的模型Song,存储在数据库表albumssongs中,并带有一个名为 的数据透视表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>元素上指定。


推荐阅读