Laravel+Saloon实现分批调用带ID参数的外部API
分块调用API解决方案
核心思路
用Laravel集合的chunk()方法把75个事件ID按每组10个拆分,循环每个分组调用API。同时调整Saloon的Request类,让它支持外部传入ID列表,替代原来硬编码的数据库查询,确保每次循环能传递不同的ID块。
1. 修改Saloon请求类
调整BetThreeSixtyFiveUpcomingSoccerEventsOdds类,让它通过构造函数接收外部传入的ID数组,不再自行查询数据库:
<?php namespace App\Http\Integrations\BetsApi\Requests; use App\Http\Integrations\BetsApi\BetsApiConnector; use Saloon\Enums\Method; use Saloon\Http\Request; class BetThreeSixtyFiveUpcomingSoccerEventsOdds extends Request { protected ?string $connector = BetsApiConnector::class; protected Method $method = Method::GET; protected string $description = 'Fetch a list of ODDS for upcoming soccer events from Bet365'; private array $eventIds; // 构造函数接收外部传入的ID数组 public function __construct(array $eventIds) { $this->eventIds = $eventIds; } public function resolveEndpoint(): string { return '/v3/bet365/prematch'; } protected function defaultQuery(): array { $eventIdsString = implode(',', $this->eventIds); return [ 'FI' => $eventIdsString, 'token' => config('services.BetsApi.token') ]; } }
2. 调整控制器逻辑
在控制器中实现分块、循环调用API、处理响应数据的完整流程:
<?php namespace App\Http\Controllers\BetsApi; use App\Http\Controllers\Controller; use App\Http\Integrations\BetsApi\BetsApiConnector; use App\Http\Integrations\BetsApi\Requests\BetThreeSixtyFiveUpcomingSoccerEventsOdds; use App\Models\BetsApi\UpcomingSoccerEvents; use App\Models\BetsApi\UpcomingSoccerEventsOdds; use Filament\Notifications\Notification; class UpcomingSoccerEventsOddsController extends Controller { public function getupcomingsoccereventsodds() { $connector = new BetsApiConnector(); // 从数据库获取所有事件ID,按10个一组拆分 $eventIdChunks = UpcomingSoccerEvents::pluck('api_event_id')->chunk(10); $totalSaved = 0; foreach ($eventIdChunks as $chunk) { // 将当前组的ID数组传入Request实例 $request = new BetThreeSixtyFiveUpcomingSoccerEventsOdds($chunk->toArray()); $response = $connector->send($request); $responseArray = json_decode($response, true); // 处理API返回的数据(根据实际响应结构调整,此处假设数据在data字段下) if (!empty($responseArray['data']) && is_array($responseArray['data'])) { foreach ($responseArray['data'] as $item) { // 用updateOrCreate避免重复插入相同event_id的数据 UpcomingSoccerEventsOdds::updateOrCreate( ['event_id' => $item['event_id']], [ 'FI' => $item['FI'] ?? null, 'asian_lines' => $item['asian_lines'] ?? null, 'goals' => $item['goals'] ?? null, 'half' => $item['half'] ?? null, 'main' => $item['main'] ?? null, 'schedule' => $item['schedule'] ?? null, ] ); $totalSaved++; } } // 可选:添加延迟,避免触发API频率限制,可根据实际情况调整时长 sleep(1); } Notification::make() ->title("成功保存 {$totalSaved} 条赛事赔率数据") ->success() ->duration(3000) ->send(); return redirect()->back(); } }
关键细节说明
- 自动分块:
chunk(10)会自动处理剩余不足10个的ID,75个ID会被分成8组(前7组10个,最后一组5个) - 请求复用:Request类改为接收外部ID,可适配不同场景的ID分组请求
- 数据去重:
updateOrCreate确保同一个赛事ID不会重复插入,只会更新现有数据 - 频率控制:
sleep(1)可根据API的频率限制调整,防止被临时封禁
内容的提问来源于stack exchange,提问作者Priyank
相关产品推荐
相关产品推荐

