Install the Package
composer require baks-dev/users-address
Ensure your composer.json specifies PHP 8.4+ and Laravel 10.x+.
Publish Required Assets Run the package’s asset installer to set up configurations, migrations, and views:
php artisan baks:assets:install
This generates:
config/users-address.php).Run Migrations Generate and apply database migrations:
php artisan doctrine:migrations:diff
php artisan doctrine:migrations:migrate
Verify the user_addresses table (or equivalent) exists in your database.
First Use Case: Create a User Address
Use the package’s UserAddress model to attach addresses to users:
use Baks\UsersAddress\Models\UserAddress;
use App\Models\User;
$user = User::find(1);
$address = UserAddress::create([
'user_id' => $user->id,
'address_type' => 'home', // e.g., 'home', 'work', 'billing'
'street' => '123 Main St',
'city' => 'Springfield',
'state' => 'IL',
'postal_code' => '62704',
'country' => 'US',
'is_default' => true,
]);
Fetch User Addresses Retrieve all addresses for a user:
$addresses = UserAddress::where('user_id', $user->id)->get();
Or use a relationship (if configured):
$user->addresses; // If User model has `hasMany(UserAddress::class)`
Validation The package includes built-in validation (e.g., required fields, country/state rules). Customize via:
// config/users-address.php
'validation' => [
'required_fields' => ['street', 'city', 'country'],
'country_rules' => [
'US' => ['state' => 'required'],
'GB' => ['postcode' => 'required'],
],
],
UserAddress model with validation:
$validated = request()->validate([
'street' => 'required|string|max:255',
'city' => 'required|string|max:100',
// ... other fields
]);
$user->addresses()->create($validated);
// Via relationship (if defined in User model)
$user->addresses()->where('is_default', true)->first();
// Direct query
UserAddress::with('user')->get();
$address = UserAddress::find($id);
$address->update(['street' => 'New Address', 'is_default' => false]);
$address->delete();
// Or soft-delete if configured
$address->forceDelete();
UserAddress::where('user_id', $user->id)
->update(['is_default' => false]);
$address->update(['is_default' => true]);
$addresses = UserAddress::where('user_id', $user->id)
->orderBy('is_default', 'desc')
->get();
The package supports geocoding via a configurable service. Extend the default provider:
// config/users-address.php
'geocoding' => [
'provider' => \Baks\UsersAddress\Services\GoogleGeocoding::class,
'api_key' => env('GOOGLE_GEOCODE_API_KEY'),
],
Use the service to geocode an address:
use Baks\UsersAddress\Services\GeocodingService;
$geocoding = app(GeocodingService::class);
$coordinates = $geocoding->geocode($address->toArray());
$address->update(['latitude' => $coordinates['lat'], 'longitude' => $coordinates['lng']]);
If the package includes API routes (check routes/web.php or routes/api.php after publishing assets), use them directly:
// Example: GET /api/user/{id}/addresses
Route::get('/user/{user}/addresses', [AddressController::class, 'index']);
Otherwise, build custom controllers:
use Baks\UsersAddress\Models\UserAddress;
class AddressController extends Controller {
public function index(User $user) {
return $user->addresses;
}
}
// app/Models/UserAddress.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Baks\UsersAddress\Models\UserAddress as BaseUserAddress;
class UserAddress extends Model {
protected $table = 'user_addresses';
protected $fillable = BaseUserAddress::getFillable();
// Override relationships if needed
}
class AddressRepository {
public function findByUser(User $user) {
return UserAddress::where('user_id', $user->id)->get();
}
}
Extend validation rules in the config:
// config/users-address.php
'validation' => [
'custom_rules' => [
'postal_code' => [
'US' => 'required|digits:5',
'GB' => 'required|regex:/^[A-Z]{1,2}\d[A-Z\d]? ?\d[A-Z]{2}$/',
],
],
],
Or create a custom validator:
use Illuminate\Validation\Rule;
$rules = [
'postal_code' => [
'required',
Rule::unique('user_addresses')->ignore($address->id),
function ($attribute, $value, $fail) {
if (!preg_match('/^\d{5}(-\d{4})?$/', $value)) {
$fail('Invalid US postal code.');
}
},
],
];
Listen to address events (if the package supports them):
// app/Providers/EventServiceProvider.php
protected $listen = [
\Baks\UsersAddress\Events\AddressCreated::class => [
\App\Listeners\LogAddressCreation::class,
],
];
Or use model observers:
use Baks\UsersAddress\Models\UserAddress;
use Illuminate\Database\Eloquent\Casts\Attribute;
class UserAddressObserver {
public function saving(UserAddress $address) {
if ($address->is_default && $address->user->addresses()->whereNotIn('id', [$address->id])->exists()) {
$address->user->addresses()->where('is_default', true)->update(['is_default' => false]);
}
}
}
Register the observer in a service provider:
UserAddress::observe(UserAddressObserver::class);
Run the package’s tests:
php artisan test --group=users-address
Write custom tests for your integration:
use Baks\UsersAddress\Models\UserAddress;
use Tests\TestCase;
class UserAddressTest extends TestCase {
public function test_create_address() {
$user = User::factory()->create();
$address = UserAddress::create([
'user_id' => $user->id,
'address_type' => 'home',
'street' => '123 Test St',
]);
$this->assertDatabaseHas('user_addresses', [
'id' => $address->id,
'user_id' => $user->id,
]);
}
}
php artisan vendor:publish --tag=users-address-views
Edit resources/views/vendor/users-address/... to match your theme.How can I help you explore Laravel packages today?