【问题标题】:Inserting records into a table with multiple foreign keys with Eloquent使用 Eloquent 将记录插入具有多个外键的表中
【发布时间】:2013-05-26 12:59:33
【问题描述】:

我刚刚开始学习 Laravel 4,遇到了一个小问题,我很好奇是否有解决方案。我有一个多语言食谱数据库,简而言之,我的数据库建模如下:

Schema::create('language', function(Blueprint $table) {
    $table->string('id', 2)->primary();
    $table->string('display_name');
    $table->timestamps();
});

Schema::create('recipe', function(Blueprint $table) {
    $table->increments('id');
    $table->string('name');
    $table->string('slug')->unique();
    $table->timestamps();
});

Schema::create('translated_recipe', function(Blueprint $table) {
    $table->increments('id');
    $table->integer('recipe_id')->unsigned();
    $table->foreign('recipe_id')->references('id')->on('recipe')->onDelete('cascade');
    $table->string('language_id', 2);
    $table->foreign('language_id')->references('id')->on('language');
    $table->string('translated_name')
    $table->timestamps();
});

我的模型如下所示:

class Language extends Eloquent {
    protected $table = 'language';
    public function translatedRecipes() {
        return $this->hasMany('TranslatedRecipe');
    }
}

class Recipe extends Eloquent { 
    protected $table = 'recipe';
    public function translations() {
        return $this->hasMany('TranslatedRecipe');
    }
}

class TranslatedRecipe extends Eloquent {
    protected $table = 'translated_recipe';
    public function recipe() {
        return $this->belongsTo('Recipe');
    }
}

然后我有一些基本的播种:

Language::create(array('id' => 'en', 'display_name' => 'English'));
Recipe::create(array('name' => 'First Recipe', 'slug' => 'first_recipe'));

这里是棘手的部分。如何使用 Eloquent 插入翻译后的食谱?我已经走到这一步了:

$recipe = Recipe::all()->first();
$lang = Language::all()->first();
$translatedRecipe = new TranslatedRecipe;
$translatedRecipe->translated_name = $lang->display_name.' '.$recipe->name;

我可以使用查询生成器轻松地进行 INSERT:

DB::table('translated_recipe')->insert(
    array(
        'recipe_id' => $recipe->id, 
        'language_id' => $lang->id,
        'translated_name' => $translatedRecipe->translated_name
    )
);

它没有设置时间戳,因为我猜这是 Eloquent 的一个特性。有没有办法让它 100% 雄辩?我不能这样做:

$translatedRecipe = $recipe->translations()->save($translatedRecipe);

...因为缺少第二个外键,SQL 抛出“完整性约束违规:1452...”错误。

【问题讨论】:

    标签: php foreign-keys laravel laravel-4 eloquent


    【解决方案1】:

    好的,我还没有对此进行测试,但有几件事我会改变:

    • 我会将“language”表更改为包含以下字段:“id”、“initials”和“显示名称'。
    • 然后我会将“translated_recipe”表中的“language_id”字段更改为无符号整数。

    (在 'language' 表中将主键设置为 'id' 真的很勇敢 - 从单词的松散含义来看,它甚至不是 id!这可能是问题的原因。Eloquent 可能是期望您的主键是您没有的自动递增字段。)

    此外,最好以相对较小的“费用”来充分利用框架中提供的“免费”功能,例如:

    1. 以复数形式(语言、食谱、翻译)命名您的表格
    2. 将主键设置为自动递增字段(显然是整数)

    您可以滚动到 Dayle Rees Codehappy tutorial一对多 部分,该部分适用于 Laravel 3,但适合我们的目的。如果你想学习框架的其他特性,或者花一两块钱买他的CodeBright Laravel 4 书。 (我还没有)

    最后,您的“translated_recipe”表中没有“short_description”和“description”字段!它的工作是一个奇迹!

            Schema::create('languages', function($table) 
        {
            $table->engine = 'InnoDB';
    
            $table->increments('id');
            $table->string('initials', 2)->unique();
            $table->string('display_name');
            $table->timestamps();
        });
    
        Schema::create('recipes', function($table) 
        {
            $table->engine = 'InnoDB';
    
            $table->increments('id');
            $table->string('name');
            $table->string('slug')->unique();
            $table->timestamps();
        });
    
        Schema::create('translations', function($table) 
        {
            $table->engine = 'InnoDB';
    
            $table->increments('id');
            $table->integer('recipe_id')->unsigned();
            $table->integer('language_id')->unsigned();
            $table->string('translated_name');
            $table->timestamps();
    
            $table->foreign('recipe_id')->references('id')->on('recipe')->onDelete('cascade');
            $table->foreign('language_id')->references('id')->on('language')->onDelete('cascade');          
        });
    

    模型

    class Language extends Eloquent {
      public function translations() 
      {
        return $this->hasMany('Translation');
      }
    }
    
    class Recipe extends Eloquent { 
      public function translations() 
      {
        return $this->hasMany('Translation');
      }
    }
    
    class Translation extends Eloquent {
      public function recipe() 
      {
         return $this->belongsTo('Recipe');
      }
    
      public function language() 
      {
         return $this->belongsTo('Language');
      }
    }
    

    【讨论】:

    • 感谢关于列名和id的建议!我不明白的一件事。我对数据库建模很陌生,所以请耐心等待。为什么我需要额外的表和多对多关系?一份食谱可以有多个已翻译食谱,一份已翻译食谱属于一份食谱。一个 translate_recipe 只能属于一种语言,一种语言可以有多个 translate_recipe。还是我在这里遗漏了一些基本的东西?
    • 你完全正确! (我会编辑我的答案)。你实际上不需要第四张桌子。
    猜你喜欢
    • 1970-01-01
    • 2016-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-25
    • 2019-09-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多