baks-dev/products-favorite
Laravel/PHP module for managing product favorites (wishlist): add/remove products to a user’s favorites, store and retrieve favorite lists, and integrate into e-commerce product pages. Requires PHP 8.4+.
Installation:
composer require baks-dev/products-favorite
Add the service provider to config/app.php:
BaksDev\ProductsFavorite\ProductsFavoriteServiceProvider::class,
Publish Config/Views (if needed):
php artisan vendor:publish --tag=products-favorite-config
php artisan vendor:publish --tag=products-favorite-views
Run Migrations (if new tables are introduced):
php artisan migrate
First Use Case: Toggle a product favorite for the authenticated user:
use BaksDev\ProductsFavorite\Facades\Favorite;
// Add to favorites
Favorite::toggle($productId);
// Check if product is favorited
$isFavorited = Favorite::isFavorited($productId);
app/Facades/Favorite.php for core methods (toggle(), isFavorited()).src/ProductsFavoriteServiceProvider.php for bindings and events.src/Models/Favorite.php for relationships and business logic.database/migrations/ for schema changes (if any).tests/Feature/ProductsFavoriteTest.php for usage examples.Basic CRUD:
// Add/remove a product from favorites
Favorite::toggle($productId);
// List all user favorites
$favorites = Favorite::forUser()->get();
// Check if a product is favorited
if (Favorite::isFavorited($productId)) { ... }
Event-Driven Extensions: Listen for favorite events to trigger side effects (e.g., notifications):
// In EventServiceProvider
protected $listen = [
\BaksDev\ProductsFavorite\Events\FavoriteAdded::class => [
\App\Listeners\SendFavoriteNotification::class,
],
];
API Integration: Use Laravel’s built-in API resources or create custom endpoints:
Route::post('/favorites/{product}', [FavoriteController::class, 'toggle']);
Frontend Integration:
axios.get(`/api/favorites/${productId}`).then(response => {
const isFavorited = response.data.is_favorited;
});
Auth::user() is bound in middleware (e.g., auth:api).Favorite model if your Product or User models differ:
use BaksDev\ProductsFavorite\Models\Favorite as BaseFavorite;
class Favorite extends BaseFavorite {
public function product() {
return $this->belongsTo(Product::class, 'product_id');
}
}
Cache::remember("user_{$userId}_favorites", now()->addHours(1), function () use ($userId) {
return Favorite::forUser($userId)->pluck('product_id');
});
app/Providers/AppServiceProvider.php:
Favorite::extend(function ($favorite) {
$favorite->validate(function ($data) {
return Validator::make($data, [
'product_id' => 'required|exists:products,id',
]);
});
});
Model Assumptions:
User and Product models exist with id fields. Customize if your schema differs.Favorite model to match your relationships.Authentication Bypass:
Route::middleware('auth')->post('/favorites/{product}', ...);
Duplicate Favorites:
toggle() method:
Favorite::firstOrCreate([
'user_id' => auth()->id(),
'product_id' => $productId,
]);
Missing Events:
FavoriteRemoved may not be published by default.toggle() method or extend the service.Database Locking:
toggle().DB::transaction(function () use ($productId) {
Favorite::toggle($productId);
});
php artisan event:listen BaksDev\ProductsFavorite\Events\FavoriteAdded
\Log::debug('Favorite toggle called for product', ['product_id' => $productId]);
--pretend to preview schema changes:
php artisan migrate --pretend
auth middleware is applied to routes:
php artisan route:list | grep favorites
Custom Validation:
Favorite::extend(function ($favorite) {
$favorite->validate(function ($data) {
return Validator::make($data, [
'product_id' => 'required|exists:products,id|not_in:blacklisted_products',
]);
});
});
Add Metadata:
Extend the Favorite model to store additional fields (e.g., created_at notes):
Schema::table('favorites', function (Blueprint $table) {
$table->text('notes')->nullable();
});
API Resources: Create a custom resource for API responses:
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class FavoriteResource extends JsonResource {
public function toArray($request) {
return [
'product_id' => $this->product_id,
'created_at' => $this->created_at->format('Y-m-d'),
'notes' => $this->notes,
];
}
}
Real-Time Updates: Use Laravel Echo/Pusher to broadcast favorite changes:
broadcast(new FavoriteUpdated($productId, $isFavorited));
Bulk Operations: Add methods to the facade for batch processing:
Favorite::extend(function ($favorite) {
$favorite->bulkToggle(array $productIds) {
// Implement logic
}
});
php artisan vendor:publish --tag=products-favorite-config
php artisan vendor:publish --tag=products-favorite-lang
php artisan queue:work
How can I help you explore Laravel packages today?