PHPackages                             eliel-elie/laravel-fluent-viacep - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. eliel-elie/laravel-fluent-viacep

ActiveLibrary[API Development](/categories/api)

eliel-elie/laravel-fluent-viacep
================================

A fluent ViaCEP API wrapper for Laravel

v1.0.1(1mo ago)02MITPHPPHP ^8.2CI passing

Since Feb 17Pushed 3mo agoCompare

[ Source](https://github.com/eliel-elie/laravel-fluent-viacep)[ Packagist](https://packagist.org/packages/eliel-elie/laravel-fluent-viacep)[ RSS](/packages/eliel-elie-laravel-fluent-viacep/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (1)Dependencies (16)Versions (3)Used By (0)

Fluent ViaCEP Wrapper for Laravel
=================================

[](#fluent-viacep-wrapper-for-laravel)

[![Latest Version on Packagist](https://camo.githubusercontent.com/d0d65434d47badc7a99753f9d6dbc3a8214be0b2d08576c5944e7a7b0b39e499/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f656c69656c2d656c69652f6c61726176656c2d666c75656e742d7669616365702e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/eliel-elie/laravel-fluent-viacep)[![Total Downloads](https://camo.githubusercontent.com/bd77aca693446a381c6cae629b6d15acc707cf382a933d46dc355ddab7001993/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f656c69656c2d656c69652f6c61726176656c2d666c75656e742d7669616365702e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/eliel-elie/laravel-fluent-viacep)[![License](https://camo.githubusercontent.com/a41e9a1d1d444b4368051ea9a9806d02ab50ff9a3de855db5d5ef8b77ecf57c8/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f656c69656c2d656c69652f6c61726176656c2d666c75656e742d7669616365702e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/eliel-elie/laravel-fluent-viacep)

A modern, fluent, and highly customizable wrapper for the ViaCEP API, designed specifically for Laravel applications. Built with PHP 8.2+ features and following best practices for production-ready Laravel packages.

> **ViaCEP** is a free Brazilian postal code (CEP) lookup service that provides address information based on postal codes or vice-versa.

✨ Features
----------

[](#-features)

- 🚀 **Fluent Interface**: Intuitive and readable chainable API for building requests
- 📦 **Multiple Formats**: Full support for JSON, XML, Piped, and JSONP response formats
- 💾 **Smart Caching**: Built-in Laravel Cache integration with customizable TTL and cache keys
- 🔄 **Automatic Retries**: Configurable retry mechanism with exponential backoff for resilience
- 🏗️ **Immutable DTO**: Type-safe `Address` object using PHP 8.2+ readonly properties
- 🔍 **Dual Search Modes**: Search by CEP or by full address (State/City/Street)
- 📦 **Bulk Requests**: Fetch multiple CEPs in a single call with automatic error handling
- 🛠️ **CEP Utilities**: Built-in validation, formatting, and cleaning helpers
- 🎨 **Custom Transformers**: Apply custom data transformations via closures
- ⚙️ **Fully Configurable**: Every aspect configurable via config file or method chaining
- 🧪 **Fully Tested**: Comprehensive test coverage using Pest PHP
- 🎯 **Laravel Native**: Built specifically for Laravel 10, 11, and 12
- 🔒 **Type Safe**: Full type hints and return types for IDE autocompletion
- 🌐 **Raw Response Support**: Access raw API responses when needed

📋 Requirements
--------------

[](#-requirements)

- PHP 8.2 or higher
- Laravel 10.x, 11.x, or 12.x
- Guzzle HTTP Client 7.8+

📦 Installation
--------------

[](#-installation)

You can install the package via composer:

```
composer require elielelie/laravel-fluent-viacep
```

The service provider will automatically register itself.

You can publish the config file with:

```
php artisan vendor:publish --tag="viacep-config"
```

⚙️ Configuration
----------------

[](#️-configuration)

You can publish the config file with:

```
php artisan vendor:publish --tag="viacep-config"
```

This is the contents of the published config file (`config/viacep.php`):

```
return [
    // Base URL for ViaCEP API
    'base_url' => env('VIACEP_BASE_URL', 'https://viacep.com.br/ws'),

    // Request timeout in seconds
    'timeout' => env('VIACEP_TIMEOUT', 10),

    // Number of retry attempts on failure
    'retry' => env('VIACEP_RETRY', 3),

    // Enable/disable caching
    'cache_enabled' => env('VIACEP_CACHE_ENABLED', true),

    // Cache TTL in seconds (1 hour default)
    'cache_ttl' => env('VIACEP_CACHE_TTL', 3600),

    // Cache key prefix
    'cache_prefix' => env('VIACEP_CACHE_PREFIX', 'viacep'),

    // Default response format (json, xml, piped, jsonp)
    'default_format' => env('VIACEP_DEFAULT_FORMAT', 'json'),
];
```

### Environment Variables

[](#environment-variables)

Add these to your `.env` file to customize the package behavior:

```
VIACEP_BASE_URL=https://viacep.com.br/ws
VIACEP_TIMEOUT=10
VIACEP_RETRY=3
VIACEP_CACHE_ENABLED=true
VIACEP_CACHE_TTL=3600
VIACEP_CACHE_PREFIX=viacep
VIACEP_DEFAULT_FORMAT=json
```

📖 Usage
-------

[](#-usage)

### Quick Start

[](#quick-start)

```
use ViaCep\Facades\ViaCep;

// Simple CEP lookup
$address = ViaCep::cep('01001000')->get();

echo $address->logradouro; // Praça da Sé
echo $address->localidade; // São Paulo
echo $address->uf;         // SP
```

### 🔍 Search Methods

[](#-search-methods)

#### Search by CEP (Postal Code)

[](#search-by-cep-postal-code)

```
// Basic search
$address = ViaCep::cep('01001000')->get();

// With formatting
$address = ViaCep::cep('01001-000')->get(); // Automatically cleans formatting

// CEP validation is automatic
try {
    $address = ViaCep::cep('invalid')->get();
} catch (\ViaCep\Exceptions\InvalidCepException $e) {
    // Handle invalid CEP
}
```

#### Search by Address (State/City/Street)

[](#search-by-address-statecitystreet)

Search for multiple addresses matching your criteria:

```
// Returns array of Address objects
$addresses = ViaCep::state('SP')
    ->city('São Paulo')
    ->street('Praça da Sé')
    ->get();

foreach ($addresses as $address) {
    echo $address->cep . PHP_EOL;
}
```

**Requirements for address search:**

- `state()`: Required - 2-letter state code (UF)
- `city()`: Required - City name
- `street()`: Required - Minimum 3 characters

### 📦 Bulk Requests

[](#-bulk-requests)

Fetch multiple CEPs efficiently in a single call:

```
$ceps = ['01001000', '20040-020', '30130-100'];

$results = ViaCep::bulk($ceps)->get();

// Results are indexed by CEP
foreach ($results as $cep => $address) {
    echo "{$cep}: {$address->localidade}" . PHP_EOL;
}
```

**Features:**

- Automatic error handling (invalid CEPs are skipped)
- Maintains cache settings for all requests
- Returns associative array indexed by CEP

### 📄 Response Formats

[](#-response-formats)

The package supports all ViaCEP API response formats:

#### JSON (Default)

[](#json-default)

```
$address = ViaCep::cep('01001000')->asJson()->get();
// Returns: Address DTO object
```

#### XML

[](#xml)

```
$address = ViaCep::cep('01001000')->asXml()->get();
// Returns: Address DTO object parsed from XML
```

#### Piped Format

[](#piped-format)

```
$address = ViaCep::cep('01001000')->asPiped()->get();
// Returns: Address DTO object parsed from piped string
```

#### JSONP

[](#jsonp)

```
$response = ViaCep::cep('01001000')
    ->asJsonp('myCallback')
    ->raw(); // Returns JSONP string

// Or using alias
$response = ViaCep::cep('01001000')
    ->jsonp('handleAddress')
    ->raw();
```

### 🔄 Raw Responses

[](#-raw-responses)

Get the raw API response without DTO parsing:

```
// Get raw JSON string
$jsonString = ViaCep::cep('01001000')->asJson()->raw();

// Get raw XML string
$xmlString = ViaCep::cep('01001000')->asXml()->raw();

// Get raw piped string
$pipedString = ViaCep::cep('01001000')->asPiped()->raw();
```

### 💾 Caching

[](#-caching)

#### Enable Caching with Custom TTL

[](#enable-caching-with-custom-ttl)

```
// Cache for 1 hour (3600 seconds)
$address = ViaCep::cep('01001000')
    ->cache(3600)
    ->get();

// Cache for 24 hours
$address = ViaCep::cep('01001000')
    ->cache(86400)
    ->get();

// With custom cache key
$address = ViaCep::cep('01001000')
    ->cache(3600, 'my-custom-key')
    ->get();
```

#### Disable Caching

[](#disable-caching)

```
// Disable cache for this request only
$address = ViaCep::cep('01001000')
    ->withoutCache()
    ->get();
```

**Cache Key Structure:**

- Default: `{cache_prefix}:md5(url)`
- Custom: `{cache_prefix}:{custom_key}`
- Prefix from config: `viacep` (configurable)

### 🔄 Retry and Timeout Configuration

[](#-retry-and-timeout-configuration)

Control resilience and performance:

```
$address = ViaCep::cep('01001000')
    ->timeout(5)    // Set timeout to 5 seconds
    ->retry(3)      // Retry up to 3 times on failure
    ->get();

// Combine with caching for maximum resilience
$address = ViaCep::cep('01001000')
    ->timeout(10)
    ->retry(5)
    ->cache(7200)
    ->get();
```

**Default values:**

- Timeout: 10 seconds
- Retry: 3 attempts
- Retry delay: 100ms between attempts

### 🎨 Custom Transformers

[](#-custom-transformers)

Apply custom transformations to the response:

```
$customData = ViaCep::cep('01001000')
    ->transform(function ($response) {
        $data = json_decode($response, true);

        return [
            'postal_code' => $data['cep'],
            'full_address' => "{$data['logradouro']}, {$data['localidade']}",
            'custom_field' => 'my custom value'
        ];
    })
    ->get();

// Use with any format
$transformed = ViaCep::cep('01001000')
    ->asXml()
    ->transform(function ($xmlString) {
        $xml = simplexml_load_string($xmlString);
        return (array) $xml;
    })
    ->get();
```

### 🛠️ CEP Utility Helpers

[](#️-cep-utility-helpers)

Built-in static methods for CEP manipulation:

```
// Validate CEP format
ViaCep::validate('01001-000');  // true
ViaCep::validate('01001000');   // true
ViaCep::validate('12345');      // false

// Format CEP (add hyphen)
ViaCep::formatCep('01001000');  // 01001-000
ViaCep::formatCep('12345');     // 12345 (invalid, returns as-is)

// Clean CEP (remove formatting)
ViaCep::clean('01001-000');     // 01001000
ViaCep::clean('01.001-000');    // 01001000
```

### 🔧 Advanced Configuration

[](#-advanced-configuration)

#### Custom Base URL

[](#custom-base-url)

Override the API base URL (useful for testing):

```
$address = ViaCep::cep('01001000')
    ->setBaseUrl('https://custom-api.example.com/ws')
    ->get();
```

#### Method Chaining

[](#method-chaining)

All configuration methods return `$this` for fluent chaining:

```
$address = ViaCep::cep('01001000')
    ->asJson()
    ->cache(3600, 'custom-key')
    ->timeout(15)
    ->retry(5)
    ->get();

// Address search with full configuration
$addresses = ViaCep::state('SP')
    ->city('São Paulo')
    ->street('Avenida Paulista')
    ->timeout(20)
    ->cache(7200)
    ->retry(3)
    ->get();
```

📦 Address DTO
-------------

[](#-address-dto)

The `Address` Data Transfer Object provides a type-safe, immutable representation of address data.

### Properties

[](#properties)

All properties are **readonly** and publicly accessible:

```
$address->cep;         // string: CEP (postal code)
$address->logradouro;  // string: Street name
$address->complemento; // string: Complement
$address->bairro;      // string: Neighborhood
$address->localidade;  // string: City name
$address->uf;          // string: State (UF)
$address->ibge;        // string: IBGE code
$address->gia;         // string: GIA code
$address->ddd;         // string: Area code
$address->siafi;       // string: SIAFI code
```

### Methods

[](#methods)

#### `getFullAddress(): string`

[](#getfulladdress-string)

Returns a complete formatted address:

```
$address = ViaCep::cep('01001000')->get();
echo $address->getFullAddress();
// Output: "Praça da Sé, lado ímpar, Sé, São Paulo, SP, 01001-000"
```

#### `getFormattedCep(): string`

[](#getformattedcep-string)

Returns CEP with formatting (hyphen):

```
echo $address->getFormattedCep(); // 01001-000
```

#### `getCity(): string`

[](#getcity-string)

Alias for `localidade`:

```
echo $address->getCity(); // Same as $address->localidade
```

#### `getState(): string`

[](#getstate-string)

Alias for `uf`:

```
echo $address->getState(); // Same as $address->uf
```

#### `getStreet(): string`

[](#getstreet-string)

Alias for `logradouro`:

```
echo $address->getStreet(); // Same as $address->logradouro
```

#### `getNeighborhood(): string`

[](#getneighborhood-string)

Alias for `bairro`:

```
echo $address->getNeighborhood(); // Same as $address->bairro
```

#### `getIbgeCode(): string`

[](#getibgecode-string)

Returns the IBGE municipal code:

```
echo $address->getIbgeCode(); // Same as $address->ibge
```

#### `isComplete(): bool`

[](#iscomplete-bool)

Checks if the address has all main fields populated:

```
if ($address->isComplete()) {
    echo "Address is complete";
}
// Checks: logradouro, bairro, localidade, and uf
```

#### `toArray(): array`

[](#toarray-array)

Converts the Address to an associative array:

```
$data = $address->toArray();
/*
[
    'cep' => '01001-000',
    'logradouro' => 'Praça da Sé',
    'complemento' => 'lado ímpar',
    'bairro' => 'Sé',
    'localidade' => 'São Paulo',
    'uf' => 'SP',
    'ibge' => '3550308',
    'gia' => '1004',
    'ddd' => '11',
    'siafi' => '7107'
]
*/
```

#### `toJson(int $options = 0): string`

[](#tojsonint-options--0-string)

Converts the Address to JSON:

```
$json = $address->toJson();
$prettyJson = $address->toJson(JSON_PRETTY_PRINT);
```

#### `__toString(): string`

[](#__tostring-string)

String representation returns full address:

```
echo $address; // Calls getFullAddress()
```

### Creating Address Instances

[](#creating-address-instances)

#### From Array

[](#from-array)

```
$address = \ViaCep\DTO\Address::fromArray([
    'cep' => '01001-000',
    'logradouro' => 'Praça da Sé',
    'complemento' => 'lado ímpar',
    'bairro' => 'Sé',
    'localidade' => 'São Paulo',
    'uf' => 'SP',
    'ibge' => '3550308',
    'gia' => '1004',
    'ddd' => '11',
    'siafi' => '7107'
]);
```

### JSON Serialization

[](#json-serialization)

The Address DTO implements `JsonSerializable`:

```
$address = ViaCep::cep('01001000')->get();

// Direct JSON encoding
$json = json_encode($address);

// In Laravel responses
return response()->json($address);

// In Laravel collections
$addresses = collect([$address1, $address2]);
return $addresses->toJson();
```

🚨 Exception Handling
--------------------

[](#-exception-handling)

The package throws specific exceptions for different error scenarios:

### Exception Types

[](#exception-types)

#### `InvalidCepException`

[](#invalidcepexception)

Thrown when CEP format is invalid:

```
use ViaCep\Exceptions\InvalidCepException;

try {
    $address = ViaCep::cep('invalid')->get();
} catch (InvalidCepException $e) {
    // Handle invalid CEP format
    echo "Invalid CEP: " . $e->getMessage();
}
```

#### `CepNotFoundException`

[](#cepnotfoundexception)

Thrown when CEP is not found in the database:

```
use ViaCep\Exceptions\CepNotFoundException;

try {
    $address = ViaCep::cep('99999999')->get();
} catch (CepNotFoundException $e) {
    // Handle CEP not found
    echo "CEP not found";
}
```

#### `UnsupportedFormatException`

[](#unsupportedformatexception)

Thrown when an unsupported response format is requested:

```
use ViaCep\Exceptions\UnsupportedFormatException;

try {
    $address = ViaCep::cep('01001000')
        ->format('invalid-format')
        ->get();
} catch (UnsupportedFormatException $e) {
    // Handle unsupported format
}
```

#### `ViaCepException`

[](#viacepexception)

Base exception class for all package exceptions:

```
use ViaCep\Exceptions\ViaCepException;

try {
    $address = ViaCep::cep('01001000')->get();
} catch (ViaCepException $e) {
    // Catches all package-specific exceptions
    Log::error('ViaCEP Error: ' . $e->getMessage());
}
```

### Exception Hierarchy

[](#exception-hierarchy)

```
Exception
└── ViaCepException (base)
    ├── InvalidCepException
    ├── CepNotFoundException
    └── UnsupportedFormatException

```

### Best Practices

[](#best-practices)

```
use ViaCep\Facades\ViaCep;
use ViaCep\Exceptions\InvalidCepException;
use ViaCep\Exceptions\CepNotFoundException;
use Illuminate\Support\Facades\Log;

try {
    $address = ViaCep::cep($userInput)
        ->timeout(5)
        ->retry(2)
        ->get();

    // Process address
    return $address;

} catch (InvalidCepException $e) {
    // Handle validation error
    return response()->json([
        'error' => 'Invalid CEP format'
    ], 422);

} catch (CepNotFoundException $e) {
    // Handle not found
    return response()->json([
        'error' => 'CEP not found'
    ], 404);

} catch (\RuntimeException $e) {
    // Handle network/API errors
    Log::error('ViaCEP API Error', ['error' => $e->getMessage()]);
    return response()->json([
        'error' => 'Service temporarily unavailable'
    ], 503);
}
```

💡 Usage Examples
----------------

[](#-usage-examples)

### Laravel Controller Example

[](#laravel-controller-example)

```
