fndmiranda/simple-address

在多个API中通过邮编搜索地址,并可选择在搜索结果中使用谷歌地图获取地理编码。

1.2.2 2020-07-14 14:58 UTC

This package is auto-updated.

Last update: 2024-09-15 00:44:43 UTC


README

本文也可以在巴西葡萄牙语中阅读。

Laravel的简单地址

此包简化了在API中通过邮编搜索地址以及在数据库中管理地址的过程,您还可以创建自己的适配器用于API查询。

安装

composer require fndmiranda/simple-address

使用

使用Artisan命令vendor:publish发布包配置文件

php artisan vendor:publish --tag=simple-address-config

发布的配置文件address.php将被放置在您的config目录中。

搜索API

可用的API列表位于您的config/address.php文件中的apis部分,您可以按照以下方式删除或添加新的适配器

'apis' => [
    Fndmiranda\SimpleAddress\Adapters\ViaCepAdapter::class,
    Fndmiranda\SimpleAddress\Adapters\PostmonAdapter::class,
    Fndmiranda\SimpleAddress\Adapters\WidenetAdapter::class,
],

如果您将config/address.php中的force_priority更改为true,则搜索顺序将始终符合apis适配器列表,默认情况下此值为false,以便顺序是随机的。

使用Address外观的search方法,包将遍历API,直到找到请求的邮编,如下所示

$address = Address::search(38017170);

地理编码

您可以使用search方法返回的数据,通过外观Addressgeocoding方法获取地址的latitudelongitude,如下所示

$address = Address::search(38017170);

$geocode = Address::geocoding($address);

注意,要使用geocoding功能,您需要提供谷歌地图API的key,在您的.env文件中添加ADDRESS_GOOGLE_MAPS_KEY条目,如下所示

ADDRESS_GOOGLE_MAPS_KEY=YourMapsKey

数据库

此包附带一个完整的数据库结构,用于存储搜索到的地址。

注意,将创建一个多态性表,该表应该使用与您在表中使用的类型相同的列创建,您可以在config/address.php文件中将column_type设置为column_type,选项有integerbigIntegeruuid,然后使用migrate Artisan命令创建表

php artisan migrate

迁移自定义

如果您不打算使用SimpleAddress默认迁移,您应该在AppServiceProviderregister方法中调用Address::ignoreMigrations方法。您可以使用vendor:publish Artisan命令导出默认迁移

php artisan vendor:publish --tag=simple-address-migrations

如果您不想在数据库中管理地址,只想查询API,请将config/address.php文件中的manager_address更改为false

保存到数据库

供应商模型与地址多态性集成的示例。

<?php

namespace App\Supplier;

use Fndmiranda\SimpleAddress\Entities\Address;
use Illuminate\Database\Eloquent\Model;
use Fndmiranda\SimpleAddress\Pivot\AddressPivot;

class Supplier extends Model
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'document', 'is_active',
    ];

    /**
     * Get all of the addresses for the supplier.
     */
    public function addresses()
    {
        return $this->morphToMany(Address::class, 'addressable', 'address_addressables')
            ->withPivot(['number', 'complement', 'lat', 'lng', 'type'])
            ->using(AddressPivot::class)
            ->withTimestamps();
    }
}

然后您可以使用以下示例使用外观Addresssearchgeocoding方法将地址保存到供应商中

// Find a supplier
$supplier = \App\Supplier::find(1);

// Search a address by postcode
$address = Address::search(38017170);

// Get geocode of address
$geocode = Address::geocoding($address);

// Save an address to the supplier
$attributes = array_merge(['number' => 16, 'complement' => 'House'], $geocode);
$supplier->addresses()->save($address, $attributes);

// Or without geocode
$supplier->addresses()->save($address, ['number' => 16, 'complement' => 'House']);

// To update a supplier address
$supplier->addresses()->first()->pivot->update(['number' => 25, 'complement' => 'Store 10']);

或者在您的控制器中

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Response;
use App\Supplier;
use App\Http\Resources\SupplierResource;
use App\Repositories\SupplierRepository;
use Fndmiranda\SimpleAddress\Facades\Address;
use Fndmiranda\SimpleAddress\Repositories\AddressRepository;

class SupplierController extends Controller
{
    /**
     * The supplier repository instance.
     *
     * @var SupplierRepository
     */
    protected $supplierRepository;
    
    /**
     * The address repository instance.
     *
     * @var AddressRepository
     */
    protected $addressRepository;
    
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct(SupplierRepository $supplierRepository, AddressRepository $addressRepository)
    {
        $this->supplierRepository = $supplierRepository;
        $this->addressRepository = $addressRepository;
    }
    
    /**
     * Store a newly created resource in storage.
     *
     * @param SupplierRequest $request
     * @return Response
     */
    public function store(SupplierRequest $request)
    {
        $attributes = $request->all();
        
        $entity = $this->addressRepository->create($attributes);
        
        if (!empty($attributes['address'])) {
            if (!empty(config('address.google_maps_key'))) {
                $address = $this->addressRepository->find($attributes['address']['address_id']);
                $geocode = Address::geocoding($address, $attributes['address']);
                if (!empty($geocode)) {
                    array_merge($attributes['address'], $geocode);
                }
            }

            $entity->addresses()->sync([$attributes['address']['address_id'] => $attributes['address']]);
        }
        
        $data = SupplierResource::make($entity);
        return response()->json(['data' => $data], Response::HTTP_CREATED);
    }

    /**
     * Update the specified resource in storage.
     *
     * @param SupplierRequest $request
     * @param string $id
     * @return AccountResource
     */
    public function update(SupplierRequest $request, $id)
    {
        $attributes = $request->all();
        
        $entity = $this->supplierRepository->find($id);
        
        if (!empty($attributes['address'])) {
            if (!empty(config('address.google_maps_key'))) {
                $address = $this->addressRepository->find($attributes['address']['address_id']);
                $geocode = Address::geocoding($address, $attributes['address']);
                if (!empty($geocode)) {
                    array_merge($attributes['address'], $geocode);
                }
            }

            $entity->addresses()->sync([$attributes['address']['address_id'] => $attributes['address']]);
        }

        $entity->update($attributes);
        
        return SupplierResource::make($entity);
    }
}

请求体示例

{
  "name": "Name of supplier",
  "email": "email@domain.com",
  "document": "11111111111",
  "is_active": true,
  "address": {
  	"address_id": "0fdecea5-9f99-47ea-87a9-3dc191839008",
  	"number": 16,
  	"complement": "House"
  }
}

创建您自己的自定义适配器

您可以为不在列表中的API创建自己的自定义适配器来查询,您可以使用simple-address:make Artisan命令生成适配器

php artisan simple-address:make YourApiAdapter

此命令将在app/SimpleAddress/Adapters/YourApiAdapter.php处生成适配器。

该文件将包含空的searchprepare方法,因此您可以按照以下示例的文件结构进行适配

<?php

namespace App\SimpleAddress\Adapters;

use Fndmiranda\SimpleAddress\Contracts\AdapterContract;

class YourApiAdapter implements AdapterContract
{
    /**
     * Search external address by postcode.
     *
     * @param $postcode
     * @return array|bool
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function search($postcode)
    {
        $client = new \GuzzleHttp\Client();
        $request = new \GuzzleHttp\Psr7\Request('GET', 'https://api.postmon.com.br/v1/cep/'.$postcode.'?format=json');
        $response = $client->send($request);

        if ($response->getStatusCode() != 200) {
            return false;
        }

        $data = json_decode((string) $response->getBody(), true);

        return $this->prepare($data);
    }

    /**
     * Prepare address data.
     *
     * @param $data
     * @return array
     */
    public function prepare($data)
    {
        return [
            'postcode' => $data['cep'],
            'address' => $data['logradouro'],
            'neighborhood' => $data['bairro'],
            'city' => $data['cidade'],
            'state' => $data['estado'],
        ];
    }
}

按照以下方式将您的适配器添加到config/address.php文件中的apis列表中

'apis' => [
    Fndmiranda\SimpleAddress\Adapters\ViaCepAdapter::class,
    Fndmiranda\SimpleAddress\Adapters\PostmonAdapter::class,
    Fndmiranda\SimpleAddress\Adapters\WidenetAdapter::class,
    App\SimpleAddress\Adapters\YourApiAdapter::class, // Your custom Api adapter
],

如果您创建了一个新的API适配器,我将非常感激您通过添加适配器并将其映射到包的config/address.php文件中的apis列表来发起一个pull request。

搜索方法

搜索方法将请求发送到端点以查询邮政编码,并使用 prepare 方法将获取的数据转换为标准数组,然后返回这些数组或如果找不到 postcode 或 API 不响应,则返回 false 以自动查询下一个 API adapter

prepare 方法

prepare 方法将 API 返回的数据转换为具有 postcodeaddressneighborhoodcitystate 键的标准 array

安全

如果您发现任何与安全相关的问题,请通过电子邮件 fndmiranda@gmail.com 联系,而不是使用问题跟踪器。

许可证

MIT 许可证 (MIT)。有关更多信息,请参阅 许可证文件