2016-09-13 100 views
0

真的不知道如何处理这一点,但我有entry_id(外键)和键/值这样的元表:Laravel 5 - firstOrCreate()并删除旧项目?

id | entry_id |  key  |  value  
------------------------------------------- 
1  4   Fruit 1  Apple 
2  4   Fruit 2  Banana 
3  4   Fruit 3  Cantaloupe 

我想关键的新列表更新entry_id 4 /值对Fruit 1/AppleFruit 4/Dragonfruit,这应该是这样的:

id | entry_id |  key  |  value  
------------------------------------------- 
1  4   Fruit 1  Apple 
4  4   Fruit 4  Dragonfruit 

因此,这里有3件事情应该发生:

  • Fruit 1/Apple没有改变,所以它应该保持不变。
  • Fruit 4/Dragonfruit是新增的,因此应该添加。
  • 新的更新列表没有Fruit 2/BananaFruit 3/Cantaloupe,所以应该删除它们。

我尝试使用firstOrCreate()这样的:

// $metas is an array of the new list 
foreach ($metas as $meta) { 
    $entry->entryMeta()->firstOrCreate([ 
    'entry_id' => $entry->id, 
    'key' => $meta->key, 
    'value' => $meta->value 
    ]); 
} 

这需要3件事情应该发生的第2个要点的照顾。删除不在新列表中的旧项目的最后一个要点不起作用(我知道它不是firstOrCreate()的一部分)。

任何想法如何照顾所有3个重点?

+0

您是否要求ID对于现有条目保持不变并且对新条目保持自动递增? – tam5

+0

此外,你只想改变那些你正在使用'entry_id'的行,而其他行将保持不变,请让我知道如果这是正确的,以确保我明白 – tam5

+0

@tam Yup,我老实说,关心ID很多,我只是不想重新插入那里的东西(也许每次更新项目时系统上会做更多的工作,只需擦拭干净并重新插入即可)?更正您的第二条评论,我一次只能处理属于单个'entry_id'的键/值行。 – Wonka

回答

1

既然你基本上是要替换表中有entry_id == x所有条目,最简单的解决办法可能是像这样的模型:

public function updateEntry(int $entryId, array $newFruits) 
{ 
    // delete old entries 
    self::where('entry_id', $entryId)->delete(); 

    // create new ones 
    foreach ($newFruits as $fruit) { 
     self::save($fruit); 
    } 
} 

如果因任何原因对现有的行存在着额外的数据您不打算替换,那么您可以修改此方法,检查$newFruits以查看它是否具有表示表中某些内容的值。在你的情况下,你会检查keyvalue,如果它们已经在db中成对存在,你不会删除它。但是,根据您提供的表结构,这似乎不是必要的,只是一个不必要的复杂因素。

+0

感谢@tam,很简单,我想我过于复杂这一个! – Wonka

0

我会做的是,获取新的水果数组的id,然后根据id做一个whereNotIn(假设你的id在两种情况下保持不变),并删除结果 例如,

$ updateArray = NewFruits-> get() - > lists('id') - > toArray();

$ deleteFruits = Fruit :: whereNotIn('id',$ updateArray) - > get();

的foreach($ deleteFruits为$ deleteFruit){

$ deleteFruit->删除();

}

+0

我认为唯一的问题是,我没有新的水果ID,因为ID字段只是表上的自动递增值。 – Wonka

0

好了,这似乎是一个经典的案例,你应该只截断该表第一,然后用你想保留条目运行查询。

DB::statement("SET foreign_key_checks = 0"); 

//Model::truncate(); 

Db::table('mytable')->truncate(); 

DB::statement('SET FOREIGN_KEY_CHECKS = 1'); 

然后再次运行您的代码与新的改进列表。让我知道这是否有帮助。

+0

我不能只截断整个表,因为在其他键/值的同一个表中也有其他条目。 – Wonka