Shop catalog
Overview
- Scope
- Shop product-domain data and read/indexing services; excludes basket/order lifecycle
Key concepts
- Catalog Tree
- Adjacency-list catalog hierarchy materialized into lft, rgt, and depth values for nested-set reads.
- Offer
- Purchasable product variation with stock/pricing participation.
- Facet Entry
- Denormalized index row used to filter storefront catalog products.
- Facet Index Version
- Versioned facet representation produced by the indexer.
Structure
- Catalog Domain
- Tables
- shop_catalogs
- shop_catalog_translations
- shop_brands
- shop_brand_translations
- shop_units
- shop_unit_translations
- shop_products
- shop_product_translations
- shop_catalog_product
- shop_offers
- shop_offer_translations
- shop_product_relations
- Tables
- Commercial Data
- Tables
- shop_price_types
- shop_prices
- shop_warehouses
- shop_stock
- Tables
- Indexes
- Search
- shop_search_index
- shop_search_trigrams
- Facetsshop_facet_entries
- Search
- Services
- Catalog TreeModules/Shop/Services/Catalog/CatalogNestedSetService.php
- Search
- SearchService
- SearchIndexer
- FacetsModules/Shop/Services/Facet/
Facts
- Shop migrations create separate catalog, brand, unit, product, offer, translation, product-catalog pivot, and product-relation tables. authoritative
- Shop migrations create price types, prices, warehouses, and stock tables as distinct commerce data structures. authoritative
- CatalogNestedSetService rebuilds lft, rgt, and depth from catalog parent_id and sort within a database transaction. authoritative
- Catalog nested-set rebuilding has suspension and re-entrancy guards for bulk operations. authoritative
- The facet migration adds is_filterable to Shop custom fields and creates shop_facet_entries. authoritative
- FacetIndexer rebuilds active products in chunks, removes entries for missing/inactive products, and can rebuild a full or catalog-specific scope. authoritative
- FacetIndexer can defer product reindexing while its global enabled flag is false, supporting bulk import workflows. authoritative
- CatalogTreeFacetHelper::descendantIds reads anchor lft/rgt and selects descendant catalog ids with nested-set bounds instead of loading the full catalog tree into memory. authoritative
How-to guides
Rebuild Catalog Indexes
- finish catalog/product mutations
- rebuild nested-set boundaries when parentage or sort changed
- run the appropriate Shop search/facet index rebuild
- verify inactive products no longer have queryable facet rows
Rules
Architectural rule
Do not mutate parent_id or sort in bulk and assume nested-set boundaries remain valid; rebuild or deliberately control automatic rebuild behavior.
Architectural rule
Rebuild/remove facet entries when a product becomes inactive or when its filterable catalog data changes.
Examples
Index Rebuild Commands
php artisan shop:facet-index --fresh
php artisan shop:search-index
modules/Shop/Console/Commands/RebuildFacetIndexCommand.php
Catalog Facet Filter
$ids = app(CatalogTreeFacetHelper::class)->descendantIds($catalogId, includeSelf: true);
modules/Shop/Services/Catalog/CatalogTreeFacetHelper.php