Installation
composer require luismarcelino/postal-pt:dev-master
Register Service Provider & Facade
Add to config/app.php:
'providers' => [
Luismarcelino\PostalPt\CodigosPostaisServiceProvider::class,
],
'aliases' => [
'PostalPt' => Luismarcelino\PostalPt\CodigosPostaisFacade::class,
]
Run Migration & Seed
php artisan postalpt:migration
php artisan migrate
php artisan postalpt:seed
First Query
use PostalPt;
$postalCode = PostalPt::find('1000-001'); // Returns district/freguesia data
PostalPt::find($code) for direct lookups.App\Models\PostCodePT (auto-registered) for Eloquent queries.database/migrations/ for table structure.Postal Code Validation
if (PostalPt::isValid('1000-001')) {
// Process valid Portuguese postal code
}
Freguesia/District Lookup
$data = PostalPt::find('1000-001');
// Returns: ['district' => 'Lisboa', 'freguesia' => 'Areeiro', ...]
Querying via Eloquent
$freguesias = \App\Models\PostCodePT::where('district', 'Lisboa')->get();
Bulk Validation
$codes = ['1000-001', '4000-000', '9999-999'];
$validCodes = array_filter($codes, fn($code) => PostalPt::isValid($code));
Form Validation: Use in Laravel's FormRequest:
public function rules() {
return ['postal_code' => 'required|postal_code_pt'];
}
(Requires custom validation rule; see Gotchas).
API Responses: Attach freguesia data to user addresses:
$user->address->postal_code = '1000-001';
$user->address->freguesia = PostalPt::find($user->address->postal_code)?->freguesia;
Geocoding: Combine with spatie/laravel-geocoder for latitude/longitude:
$geocode = Geocoder::geocode('Areeiro, Lisboa');
Hyphenated Format
1000-001 (not 1000001). The package expects hyphenated codes.$normalized = str_replace('-', '', $input); // Then validate
Missing Validation Rule
AppServiceProvider:
Validator::extend('postal_code_pt', function ($attribute, $value, $parameters, $validator) {
return PostalPt::isValid(str_replace('-', '', $value));
});
Seed Command Warning
postalpt:seed may time out for large databases. Run in chunks:
php artisan postalpt:seed --chunk=1000
db:seed with a custom seeder if the package’s command fails.Case Sensitivity
strtolower():
\App\Models\PostCodePT::where('district', strtolower('Lisboa'))->get();
php artisan tinker
>>> \App\Models\PostCodePT::count(); // Verify records exist
>>> \App\Models\PostCodePT::first(); // Inspect structure
if (!$postalCode = PostalPt::find('9999-999')) {
Log::warning("Invalid postal code: 9999-999");
}
Custom Fields
PostCodePT model to add computed properties:
public function getFullLocationAttribute() {
return "{$this->district}, {$this->freguesia}";
}
Autocomplete API
Route::get('/api/postal-codes', function () {
return \App\Models\PostCodePT::select('post_code', 'freguesia')
->where('post_code', 'like', request('q').'%')
->limit(10)
->get();
});
Local Overrides
php artisan vendor:publish --tag=postalpt-migrations
php artisan migrate
php artisan postalpt:seed
How can I help you explore Laravel packages today?