Laravel имеет отношение One-belongsToMany?

Итак, я изо всех сил пытался заставить эту схему работать (кстати, полный новичок в laravel...). У меня есть таблица «фотографии» и таблица «аудиодорожек», и я хочу иметь возможность сделать что-то вроде этого:

Модель трека:

// Get the photo associated with this track.
public function cover_art() {
    return $this->hasOne('App\Photo');
}

Фото модели:

// Get all the tracks associated with this photo.  
public function tracks() {
    return $this->belongsToMany('App\Track');
}

Как лучше всего представить эту взаимосвязь (аудиодорожка может иметь только одну фотографию, а фотография может принадлежать нескольким дорожкам)?

Ну наконец-то я все настроил и получаю ожидаемые ошибки:

Фото таблицы:

Schema::create('photos', function (Blueprint $table) {
    $table->increments('id');
    $table->string('path');
    $table->string('filename');
    $table->string('original_filename');
    $table->boolean('is_cover')->default(false);
    $table->string('title');
    $table->string('slug')->unique();
    $table->string('caption')->nullable();
    $table->timestamps();
});

Таблица дорожек:

Schema::create('tracks', function (Blueprint $table) {
    $table->increments('id');
    $table->integer('photo_id')->unsigned()->nullable();
    $table->string('path');
    $table->string('filename');
    $table->string('original_filename');
    $table->string('title');
    $table->string('slug')->unique();
    $table->string('caption')->nullable();
    $table->timestamps();
    $table->foreign('photo_id')->references('id')->on('photos')->onDelete('set null');
});

Итак, теперь, когда, например, я вызываю соответствующие методы в своих представлениях или в своих контроллерах, я получаю следующие ошибки:

@foreach($tracks as $track)
    {{ $track->cover_art }}
@endforeach

SQLSTATE [42S22]: столбец не найден: 1054 Неизвестный столбец «photos.track_id» в «предложении where» (SQL: выберите * из photos, где photos.track_id = 1, а photos.track_id не является нулевым пределом 1)

@foreach($photos as $photo)
    {{ $photo->tracks }}
@endforeach

SQLSTATE[42S02]: базовая таблица или представление не найдено: 1146 Таблица iagomarta.photo_track не существует (SQL: выберите tracks.*, photo_track.photo_id как pivot_photo_id, photo_track.track_id как pivot_track_id из tracks внутреннего соединения photo_track по tracks. id = photo_track.track_id где photo_track.photo_id = 1)

Какие-либо предложения?


person user2744115    schedule 18.09.2015    source источник
comment
Это должно сработать. Ты это пробовал?   -  person samlev    schedule 18.09.2015
comment
Неа! Я еще не пробовал, но как должна выглядеть моя схема/миграция таблицы? Следуя документам, я подумал добавить поле track_id в таблицу «фотографии» (для работы с методом hasOne), что, вероятно, правильно, но... должен ли я создать сводную таблицу, чтобы удовлетворить метод containsToMany, когда я ' м, не пытаетесь ли вы установить отношения «многие ко многим»? Извините за беспорядок... Я из Испании, и мой английский, наверное, отстой.   -  person user2744115    schedule 18.09.2015
comment
В таблице tracks должно быть поле photo_id, потому что на трек приходится 1 фотография. Вам не нужно ничего добавлять в таблицу photos, потому что belongsToMany будет искать photo_id на tracks.   -  person samlev    schedule 18.09.2015
comment
@samlev Привет, я отредактировал свой вопрос, чтобы поделиться полученными ошибками. Заранее спасибо.   -  person user2744115    schedule 18.09.2015
comment
О, правильно - вы используете функции стиля "многие ко многим", для которых требуется сводная таблица. Ниже я ответил, как это сделать с отношениями «один ко многим».   -  person samlev    schedule 18.09.2015


Ответы (2)


// Track Model
public function cover_art() {
    return $this->belongsTo('App\Photo');
}

// Photo Model
public function tracks() {
    return $this->hasMany('App\Track');
}

Подумайте об этом так: «обложка»/«фото» находится вместо альбома, поэтому «альбом» (фото) содержит много треков, и все треки принадлежат одному альбому.

person samlev    schedule 18.09.2015
comment
Ничего себе, теперь работает как шарм! Отношение к отношениям как к простому решению проблемы «один ко многим»… Думаю, я стал жертвой собственной многословности… Спасибо, чувак! - person user2744115; 18.09.2015

Возможно, это просто опечатка, как показано ниже:

create_table_tracks_migration :

Schema::create('tracks', function (Blueprint $table) {
    $table->increments('id');
    $table->integer('photo_id')->unsigned();
    $table->string('path');
    $table->string('filename');
    $table->string('original_filename');
    $table->string('title');
    $table->string('slug')->unique();
    $table->string('caption')->nullable();
    $table->timestamps();
});

Schema::table('tracks', function(Blueprint $table)
        {
            $table->foreign('photo_id')
                ->references('id')
                ->on('photos')
                ->onDelete('cascade');
        });

Обычно рекомендуется устанавливать ссылку на внешний ключ таким образом, поскольку я сам столкнулся с некоторыми проблемами, не делая этого.

И, кстати, мне очень не нравится создавать внешние ключи, допускающие значение NULL, поскольку это может создать огромный беспорядок.

Также странно выглядит эта ошибка:

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'photos.track_id' in 'where clause' (SQL: select * from photos where photos.track_id = 1 and photos.track_id is not null limit 1)

И в любом случае у вас не должно быть столбца track_id в вашей таблице фотографий.

В дополнение к этому вы можете попробовать установить отношение ownTo(App\Photo) вместо hasOne. Это сработает, поскольку в треке может быть только одна фотография. Также вам не нужна сводная таблица, так как это отношение «один ко многим», а не отношение «многие ко многим».

person Croisciento    schedule 18.09.2015
comment
Спасибо за советы! Принимая проблему как простое отношение один ко многим, вы решаете проблему. - person user2744115; 18.09.2015