tastyigniter/ti-ext-local
Adds location-based features to TastyIgniter: manage multiple locations, let customers find nearby stores, define delivery zones and charges, set opening hours, enable location reviews, and store custom location settings.
Installation:
composer require tastyigniter/ti-ext-local
Publish the extension’s assets and configurations:
php artisan vendor:publish --provider="TastyIgniter\Local\LocalServiceProvider"
First Use Case:
Location model’s built-in query scopes:
use TastyIgniter\Local\Models\Location;
$nearestLocation = Location::nearBy($latitude, $longitude, $distanceInKm)
->where('status', 'active')
->first();
$location = Location::find($locationId);
$isInDeliveryArea = $location->isInDeliveryArea($customerLatitude, $customerLongitude);
Where to Look First:
app/Models/TastyIgniter/Local/Location.php for core functionality (e.g., nearBy(), isInDeliveryArea()).database/migrations/ for schema changes (e.g., delivery area boundaries, opening hours).Location-Based Queries:
nearBy() scope with optional filters:
Location::nearBy($lat, $lng, 10) // 10km radius
->with(['reviews', 'deliveryAreas']) // Eager load relationships
->get();
$cart = Cart::with('items')->find($cartId);
foreach ($cart->items as $item) {
$location = $item->location;
if (!$location->isInDeliveryArea($customerLat, $customerLng)) {
throw new \Exception("Item not available for delivery in this area.");
}
}
Opening Hours Logic:
$location = Location::find($id);
$isOpen = $location->isOpenNow(); // Uses Carbon for time comparison
$location->openingHours()->update([
'monday_open' => '09:00',
'monday_close' => '18:00',
// ... other days
]);
Geocoder Integration:
.env:
LOCAL_GEOCODE_DRIVER=google // or 'osm'
GOOGLE_MAPS_API_KEY=your_key_here
$geocoder = app(\TastyIgniter\Local\Services\Geocoder::class);
$result = $geocoder->geocode('1600 Amphitheatre Parkway, Mountain View');
Custom Location Fields:
Location model with custom attributes:
// In a service provider or model observer
Location::created(function ($location) {
$location->custom_fields = json_encode([
'has_wifi' => true,
'parking_available' => false,
]);
$location->save();
});
Admin Workflow:
SettingsEditor to configure location-specific settings (e.g., delivery fees, opening hours) via the TastyIgniter admin panel.LocationArea model:
$location->deliveryAreas()->create([
'name' => 'Downtown Zone',
'radius' => 5, // km
'fee' => 2.99,
'color' => '#FF0000', // For UI visualization
]);
Frontend Integration:
@foreach($nearbyLocations as $location)
<div data-lat="{{ $location->latitude }}" data-lng="{{ $location->longitude }}">
{{ $location->name }}
</div>
@endforeach
const locations = @json($nearbyLocations);
locations.forEach(loc => {
L.marker([loc.latitude, loc.longitude]).addTo(map)
.bindPopup(`<b>${loc.name}</b><br>Distance: ${loc.distance} km`);
});
Performance Optimization:
Location::with(['reviews', 'deliveryAreas'])->nearBy($lat, $lng, 20)->get();
latitude, longitude) for faster geospatial queries.Event Listeners:
Location::updated(function ($location) {
if ($location->isDirty('opening_hours')) {
event(new \TastyIgniter\Local\Events\OpeningHoursUpdated($location));
}
});
API Endpoints:
Route::get('/api/locations/nearby', function (Request $request) {
$lat = $request->query('lat');
$lng = $request->query('lng');
$distance = $request->query('distance', 10);
return Location::nearBy($lat, $lng, $distance)->get();
});
Testing:
$this->partialMock(\TastyIgniter\Local\Services\Geocoder::class, function ($mock) {
$mock->shouldReceive('geocode')
->once()
->andReturn(['lat' => 37.422, 'lng' => -122.084]);
});
Caching:
$nearby = Cache::remember("nearby_locations_{$lat}_{$lng}", now()->addHours(1), function () use ($lat, $lng) {
return Location::nearBy($lat, $lng, 10)->get();
});
Namespace References:
Location model references to use short class names (e.g., Location instead of \App\Models\Location). If your code explicitly uses fully qualified namespaces, it may break.// Before (may break)
$location = new \App\Models\Location;
// After (recommended)
$location = new \TastyIgniter\Local\Models\Location;
Geocoder Driver Configuration:
LOCAL_GEOCODE_DRIVER is not set in .env, the package will throw an exception. Ensure the driver (e.g., google, osm) and corresponding API keys are configured..env:
LOCAL_GEOCODE_DRIVER=google
GOOGLE_MAPS_API_KEY=your_api_key_here
Delivery Area Validation:
isInDeliveryArea() method may return false positives if the geocoding service (e.g., Google Maps) provides imprecise coordinates.$isInArea = $location->isInDeliveryArea($lat, $lng, 0.1); // Add 100m buffer
Opening Hours Edge Cases:
isOpenNow() method assumes 24-hour time format and may fail if opening_hours data is malformed (e.g., missing values for certain days).if (!$location->openingHours->isFilled()) {
throw new \InvalidArgumentException("Opening hours not fully configured.");
}
Custom Fields Serialization:
protected $casts = [
'custom_fields' => 'array',
];
$ge
How can I help you explore Laravel packages today?