使用Eloquent将记录插入到具有多个外键的表中

时间:2013-05-30 19:56:56

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

我刚开始学习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 ...”错误。

1 个答案:

答案 0 :(得分:0)

好的,我没有对此进行过测试,但我会改变一些事情:

  • 我会将“语言”表格更改为包含以下字段:“ ID ”,“姓名首字母”和“显示名称”。
  • 然后我会将' translated_recipe '表中的' language_id '字段更改为无符号整数。

(在'语言'表中将主键设置为'id'真的很勇敢 - 而且这个词的松散含义甚至不是id!这可能是问题的原因。雄辩可能是期望你的主键是你没有的自动增量字段。)

此外,很高兴充分利用框架中提供的“免费”功能,以下列约定的相对较小的“费用”:

  1. 以复数形式(语言,食谱,翻译)命名表格
  2. 将主键设置为自动递增的字段(显然是整数)
  3. 您可以滚动到Dayle Rees Codehappy tutorial一对多部分,该部分适用于Laravel 3但适合我们的目的。如果你想学习框架的其他功能,或者为Laravel 4的CodeBright书预留一两块钱。 (我还没有)

    最后,您的'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');
      }
    }