多对多 Laravel 5.3 不会覆盖模型的列名称

Many to many Laravel 5.3 is not overriding column name for a model

我有这个 tables:

我有这个模型:

Video 
Category

我正在尝试查询多对多关系以获取属于某一特定类别的所有视频。

我有一条路线 domain.dev/category/{category} 指向我的 CategoryController 和他各自的观点。我是通过 $request.

收到的

我试图从控制器中的模型中获取数据(与 php 相呼应)并将变量传递给视图并执行:

@foreach ($category->videos as $video) {
    {{ $video->title }}
}
@endforeach

但是当 Laravel 执行查询时它抛出异常,并显示查询:

QueryException in Connection.php line 769:
    SQLSTATE[42S22]: Column not found: 1054 Unknown column 'videos.id' in 'on clause' (SQL: select `videos`.*, `videos_categories`.`category_id` as `pivot_category_id`, `videos_categories`.`video_id` as `pivot_video_id` from `videos` inner join `videos_categories` on `videos`.`id` = `videos_categories`.`video_id` where `videos_categories`.`category_id` is null)

看起来 videos.id 列没有被覆盖(因为我在 videos 中没有 id 字段,我使用 videos_id 正如你在迁移和模型中。我明确覆盖了模型中的键,以及关系中的键。

我不知道对枢轴 tables 使用字母顺序是一种常见的做法...我的枢轴 table 是 videos_categories 而不是 categories_videos 因为它应该 "by convention",所以我也覆盖了关系中的 table 名称。

我不知道我做错了什么,或者为什么 laravel 使用 videosid 所以我需要一些帮助。在编写自己的之前,我也尝试搜索其他 Q/A,但我没有找到任何解决方案。

这是类别控制器:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Category;

class CategoryController extends Controller
{
    /**
     * Shows the Category page
     *
     * @return Response
     */
    public function index(Request $request)
    {
        $category = Category::where('category', $request->category)->first();
        // THINGS I TRIED
        /*
        $videos = $category->videos()->get();

        foreach ($category->videos as $video) {
            echo $video->title;
        }
        */

        return view('category.index', ['category' => $category]);
    }
}

迁移

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateVideosTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('videos', function (Blueprint $table) {
            $table->engine = 'InnoDB';

            $table->increments('video_id')->unique();
            $table->string('title', 255);
            $table->string('embed_code', 255);
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('videos');
    }
}

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateCategoriesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('categories', function (Blueprint $table) {
            $table->engine = 'InnoDB';

            $table->increments('category_id')->unique();
            $table->string('category', 45);
            $table->string('thumbnail');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('categories');
    }
}

枢轴迁移 tables

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateVideosCategoriesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('videos_categories', function (Blueprint $table) {
            $table->engine = 'InnoDB';

            $table->integer('video_id')->unsigned()->nullable();
            $table->integer('category_id')->unsigned()->nullable();

            $table->foreign('video_id')
                ->references('video_id')
                ->on('videos')
                ->onUpdate('cascade')
                ->onDelete('cascade');

            $table->foreign('category_id')
                ->references('category_id')
                ->on('categories')
                ->onUpdate('cascade')
                ->onDelete('cascade');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('videos_categories', function (Blueprint $table) {
            $table->dropForeign(['video_id', 'category_id']);
            $table->dropColumn('video_id');
            $table->dropColumn('category_id');
        });
        Schema::dropIfExists('videos_categories');
    }
}

型号

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Video extends Model
{
    protected $table = 'videos';
    protected $primarykey = 'video_id';

    public function categories() {
        return $this->belongsToMany('App\Category', 'videos_categories', 'video_id', 'category_id');
    }
    public function tags() {
        return $this->belongsToMany('App\Tag', 'videos_tags', 'video_id', 'tag_id');
    }
}

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Category extends Model
{
    protected $table = 'categories';
    protected $primarykey = 'category_id';
    public $timestamps = false;

    public function videos()
    {
        return $this->belongsToMany('App\Video', 'videos_categories', 'category_id', 'video_id');
    }
}

模型中的 属性 必须是 $primaryKey 而不是 $primarykey

顺便说一下,默认值是 id 而不是 model_id 是有原因的,因为这是命名列的标准方式,我建议不要没有充分理由就违反这些约定,不仅是因为您面临的原因,而且还因为它会简化与其他开发人员的最终协作。