justbetter/laravel-magento-products
A Laravel integration for Magento products that lets you query and retrieve product data from a Magento store. It provides models, configuration, and a clean API to access product details, prices, and attributes directly within your Laravel application.
The package pulls Magento catalog products into Laravel as Eloquent models, so most day-to-day work is "install, configure credentials, run the import command, then react to events."
composer require justbetter/laravel-magento-productsphp artisan vendor:publish --provider="JustBetter\MagentoProducts\ServiceProvider"
php artisan migrate
.env (base URL, API token/credentials, store view) and confirm the generated config/magento-products.php points at the right store scope.php artisan list | grep magento — names shift slightly between minor versions), ideally queued and chunked.Where to look first:
config/magento-products.php — table name, queue connection, model overrides, API settings.src/Models/ — the product model and its scopes; this is what you'll query.src/Events/ — ProductCreated, ProductUpdated and friends; this is the main integration seam.src/Jobs/ and src/Commands/ — how fetching and persistence are batched.First real use case: get a SKU into Laravel and do something on arrival. Run the import for one SKU, then register a listener on the creation event and Event::fake() it in a test to confirm wiring. As of 1.9.2 the creation events are dispatched reliably, so this is now a safe hook point rather than an update-only one.
Event-driven fan-out (the primary pattern). Treat the package as a source of truth for "a product appeared/changed" and push side effects into queued listeners:
Event::listen(ProductCreated::class, SyncProductToStorefront::class);
Event::listen(ProductUpdated::class, SyncProductToStorefront::class);
Implement listeners as ShouldQueue so import runs stay fast and a slow downstream (search index, ERP, image pipeline) can't stall the sync. Route them onto a dedicated queue in config/magento-products.php rather than default.
Full sync on a schedule, targeted sync on demand. Schedule the bulk import command nightly in routes/console.php/Kernel, and dispatch the package's single-product update job for one-off SKUs — after a price change, from an admin action, or from a webhook receiver. Keep the on-demand path idempotent since it can race with the bulk run.
Mapping into your own domain. Don't scatter Magento field access through your app. Add one mapper/service that translates the package model into your local Product/Variant models, and keep custom columns on your own tables so package upgrades can't clobber them.
Scoping by store view. If you sell across websites, import per store view and key your local records by (sku, store_id). Doing a "global" import and then filtering by store in queries almost always ends in price/visibility bugs.
Testing. Use RefreshDatabase plus Event::fake() to assert listeners fire for both creation and update. For integration tests, bind a fake Magento client into the container rather than hitting the API; keep one or two contract tests against a recorded response fixture.
created_at sweeper, or a saved model observer), remove it — you'll otherwise double-process every new product.ProductUpdated only will silently miss initial imports. When you first enable the package, every product arrives as a creation. Audit existing listeners now that 1.9.2 fires them, and make sure your handler is safe to run for a product it has never seen.VARCHAR(64); Magento allows up to 64 chars plus edge cases like leading zeros and hyphens.retry_after that exceeds your listener's worst-case duration.sync in a local .env. If the event doesn't fire there, the problem is in configuration/model overrides, not your listener.How can I help you explore Laravel packages today?