Laravel中如何检测重复标题并避免重复数据存入数据库
解决Laravel中第三方API数据标题去重入库问题
原代码存在的核心问题
getTitle方法返回的是查询结果集合(get()),无法直接与字符串标题做相等比较- 多余的
json_decode($limit)操作:$i->take(20)返回的已是Laravel集合,无需二次解码 dd()语句会强制中断循环,导致仅能处理第一条数据- 重复判断逻辑错误,未正确校验数据库中是否存在对应标题
修正方案及完整代码
1. 优化重复校验方法
直接使用exists()判断标题是否已存在,返回布尔值,高效简洁
2. 移除无效解码操作
直接遍历take(20)后的集合即可
3. 移除中断循环的dd()
改用continue跳过重复条目,确保所有数据都能被处理
4. 增加异常处理
对API请求失败的情况做基础处理,避免程序报错
public function titleExists($title) { // 直接判断数据库中是否存在该标题,返回布尔值 return $this->posts->where('title', $title)->exists(); } public function getApi(Request $request) { $url = "https://newsapi.org/v2/top-headlines?sources=techcrunch&apiKey=87384f1c2fe94e11a76b2f6ff11b337f"; $response = Http::get($url); // 校验API请求是否成功 if (!$response->successful()) { return redirect()->route('posts.index')->with('error', 'API请求失败'); } $data = $response->json(); // 提取文章列表并取前20条 $articles = collect($data['articles'])->take(20); foreach ($articles as $article) { // 标题已存在则跳过当前条目 if ($this->titleExists($article['title'])) { continue; } // 组装入库数据,处理可能为空的字段 $dataPost = [ 'title' => $article['title'], 'description' => $article['description'], 'content' => $article['content'], 'topic_id' => 1, 'post_type' => $request->type, 'user_id' => 1, 'enable' => 1, 'feature_image_path' => $article['urlToImage'] ?? null ]; // 存入数据库 $this->posts->create($dataPost); } return redirect()->route('posts.index')->with('success', '数据同步完成'); }
额外优化建议
- 数据库层面防重复:在
posts表的title字段添加唯一索引,从根源杜绝重复数据,同时避免并发插入时的重复问题// 在迁移文件中添加该字段约束 $table->string('title')->unique(); - 批量插入提升效率:若数据量较大,可先收集所有需要插入的有效数据,再执行批量插入
$insertData = []; foreach ($articles as $article) { if (!$this->titleExists($article['title'])) { $insertData[] = [ 'title' => $article['title'], 'description' => $article['description'], 'content' => $article['content'], 'topic_id' => 1, 'post_type' => $request->type, 'user_id' => 1, 'enable' => 1, 'feature_image_path' => $article['urlToImage'] ?? null ]; } } if (!empty($insertData)) { $this->posts->insert($insertData); }
内容的提问来源于stack exchange,提问作者MaditionSky
相关产品推荐
相关产品推荐

