【问题标题】:Laravel 4.2 many to many relation, use something else then the default IDLaravel 4.2 多对多关系,使用其他东西而不是默认 ID
【发布时间】:2015-11-23 23:46:32
【问题描述】:

我有 2 个模型,它们都没有使用表中的 ID,而是使用字段 internal_id。所以我定制了我的数据透视模式,但我被困在连接它们上。我得到了错误:

General error: 1215 Cannot add foreign key constraint (SQL: alter table `seoshop_category_product` add constraint seoshop_category_product_category_id_foreign foreign key   
  (`category_id`) references `seoshop_categories` (`internal_id`) on delete cascade)                                                                                                            

迁移的代码是:

Schema::create('seoshop_category_product', function(Blueprint $table)
        {
            $table->increments('id');
            $table->integer('category_id')->unsigned()->index();
            $table->foreign('category_id')->references('internal_id')->on('seoshop_categories')->onDelete('cascade');
            $table->integer('product_id')->unsigned()->index();
            $table->foreign('product_id')->references('internal_id')->on('seoshop_products')->onDelete('cascade');
            $table->timestamps();
        });

seoshop_products.internal_id 和 seoshop_categories.internal_id 这两个字段都存在,列类型都是 int(11)。

谁能告诉我出了什么问题?

迁移表 seoshop_categories 和 seoshop_products

//seoshop_products
public function up()
    {
        Schema::create('seoshop_products', function(Blueprint $table)
        {
            $table->increments('id');
            $table->integer('shop_id');
            $table->integer('internal_id')->signed()->index();
            $table->integer('internal_variant_id');
            $table->string('visible');
            $table->string('tags');
            $table->timestamps();
        });
    }


//Table seoshop_categories
public function up()
    {
        Schema::create('seoshop_categories', function(Blueprint $table)
        {
            $table->increments('id');
            $table->integer('internal_id')->signed()->index();
            $table->datetime('seoshop_created_at');
            $table->datetime('seoshop_updated_at');
            $table->text('full_description');
            $table->timestamps();
        });
    }

好的,现在我已经创建了我的表,它的工作方式应该是这样的。我需要让我的产品带有类别(many-2-many)。所以我用

SEOshopProduct::find(1)->with('categories')->get();

在 dd() 之后,类别为空,我查看了我的查询如何调用它:

[8] array(3) {
["query"] "select `seoshop_categories`.*, `seoshop_category_product`.`product_id` as `pivot_product_id`, `seoshop_category_product`.`category_id` as `pivot_category_id` from `seoshop_categories` inner join `seoshop_category_product` on `seoshop_categories`.`id` = `seoshop_category_product`.`category_id` where `seoshop_category_product`.`product_id` in (?)"
["bindings"] array(1) {
[0] 8
}
["time"] 0.37
}

产品和类别的 internal_id 都大于 10.000,我在查询中看不到它。

我的模型:

产品:

public function categories(){
        return $this->belongsToMany('SEOshopCategory', 'seoshop_category_product', 'product_id', 'category_id');
    }

分类:

public function products(){
        return $this->belongsToMany('SEOshopCategory', 'seoshop_category_product', 'category_id', 'product_id');
    }

【问题讨论】:

    标签: php mysql laravel many-to-many


    【解决方案1】:

    要设置外键约束,字段定义需要完全匹配。但是,在这种情况下,seoshop_category_product.category_id 字段被定义为 UNSIGNED INT,但引用的 seoshop_categories.internal_id 字段被定义为 SIGNED INT。您的产品的外键也是如此。

    因此,您可以将类别和产品表上的 internal_id 字段更新为未签名,也可以将数据透视表上的外键字段更新为签名。

    【讨论】:

    • 谢谢帕特里克斯,这是有道理的。但是我需要如何设置或编辑新迁移?
    • 将添加 ->signed()->index();对于我的 seoshop_products.internal_id 和类别的迁移是否足够?
    • @DonnyvanV 如果您想更改新的数据透视表以匹配现有表,只需在您的 category_id 和 product_id 字段中删除对 ->unsigned() 的调用。
    • 可以参考this link as well
    • @DonnyvanV 请将此作为单独的问题发布。这将帮助未来寻找答案的人,并帮助您更多地关注您面临的问题。
    【解决方案2】:

    当你在模型中定义关系时,你可以告诉 Laravel 本地和外键是什么...

    class Product extends Eloquent
    {
        public function categories() {
            return $this->hasMany('Category', 'internal_id', 'id');
        }
    }
    
    class Category extends Eloquent
    {
        public function products() {
            return $this->hasMany('Product', 'internal_id', 'id');
        }
    }
    

    【讨论】:

    • 是的,我知道,但它不是关联 model.php 文件,而是绘制我的表结构...使用迁移然后运行 ​​artisan migrate 让我遇到上述错误的麻烦
    • 我只是想弄清楚为什么当 Laravel 为您提供了一种在模型中使用备用外键的方法时,您为什么要尝试将这些定义为数据库中的外键?
    • 如果事情真的很糟糕,这不是一个额外的安全细节来防止它,到那时我的意思是真的很糟糕:P
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-07
    • 1970-01-01
    • 1970-01-01
    • 2020-05-05
    • 2011-05-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多