You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 11消费第三方API最佳实践:Google Maps自动补全场景

Laravel 11 消费第三方API的最佳实践(以Google Maps自动补全为例)

核心思路:用服务类封装第三方API逻辑

你的Livewire组件应该专注于UI交互和数据绑定,API调用、结果格式化这类逻辑属于服务层职责,单独抽离到服务类是Laravel的标准最佳实践,比塞在组件、Model或ServiceProvider里更合理。

具体实现步骤

1. 创建Google Maps服务类

在app/Services目录下新建GoogleMapsAutocompleteService.php(如果Services目录不存在,直接创建即可):

<?php

namespace App\Services;

use Illuminate\Support\Facades\Http;

class GoogleMapsAutocompleteService
{
    protected $apiKey;

    public function __construct()
    {
        $this->apiKey = env('GOOGLE_MAPS_API_KEY');
    }

    // 封装自动补全查询逻辑
    public function getPredictions(string $input): array
    {
        if (empty($input)) {
            return [];
        }

        $response = Http::get('https://maps.googleapis.com/maps/api/place/autocomplete/json', [
            'key' => $this->apiKey,
            'type' => 'political',
            'components' => 'country:us|country:ca',
            'input' => $input
        ]);

        // 处理请求失败或无结果的情况
        if (!$response->successful() || !isset($response->object()->predictions)) {
            return [];
        }

        // 格式化返回结果为需求的格式
        return collect($response->object()->predictions)->map(function ($prediction) {
            $nameParts = [];
            $termsCount = count($prediction->terms);
            $nameParts[] = $prediction->terms[0]->value;

            if ($termsCount > 3) {
                $nameParts[] = $prediction->terms[$termsCount - 3]->value;
                $nameParts[] = $prediction->terms[$termsCount - 2]->value;
            } else {
                $nameParts[] = $prediction->terms[1]->value;
            }

            return [
                'id' => $prediction->place_id,
                'name' => implode(', ', $nameParts)
            ];
        })->toArray();
    }
}

2. 改造Livewire组件

通过Laravel的自动依赖注入,在组件中调用服务类的方法,简化组件逻辑:

<?php

namespace App\Livewire;

use Livewire\Component;
use App\Services\GoogleMapsAutocompleteService;

class LocationSearch extends Component
{
    public $location = '';
    public $results = [];
    #[Modelable]
    public $selected = [];

    public function updatedLocation($value, GoogleMapsAutocompleteService $service)
    {
        $this->reset('results');
        // 直接调用服务类的方法获取格式化后的结果
        $this->results = $service->getPredictions($value);
    }

    public function valueSelected($id, $name)
    {
        $this->location = $name;
        $this->selected = [
            'id' => $id,
            'name' => $name
        ];
        $this->reset('results');
    }

    public function render()
    {
        return view('livewire.location-search');
    }
}

为什么选服务类而不是其他?

  • Model:Model是对应数据库表的实体类,和第三方API逻辑完全不相关,违背单一职责原则。
  • ServiceProvider:ServiceProvider的作用是注册服务到容器、加载配置/路由等,不是用来封装业务逻辑的。只有当你的服务需要复杂初始化(比如多个依赖、自定义绑定)时才需要用它,这里自动注入已经足够。
  • 服务类的优势:逻辑集中便于维护、可单独编写单元测试(比如模拟Http请求)、其他模块需要调用Google自动补全时可以直接复用,符合代码复用和分离关注点的设计原则。

内容的提问来源于stack exchange,提问作者Yev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 13:35:09