Overview
A Product Listing Page (PLP) displays a grid or list of products within a collection (category). Customers browse products, filter by attributes, sort results, and click through to individual product pages. This guide walks through building a PLP using Lunar’s models and facades. The examples below use standard Laravel controllers and Blade templates. The same concepts apply whether the storefront is built with Livewire, Inertia, or a headless API.Resolving a Collection from a URL
Like products, collections use Lunar’sUrl model for slug-based lookups.
Define the Route
Resolve the Collection
Displaying Collection Information
Collection names and descriptions are stored as attribute data, accessed with theattr() method.
Collection Image
Collections support media through Spatie MediaLibrary, just like products.Breadcrumbs
Collections form a nested hierarchy. Thebreadcrumb attribute returns the translated names of all ancestor collections, which is useful for building breadcrumb navigation.
Querying Products
Theproducts() relationship on a Collection returns products ordered by the collection’s configured position pivot column.
Basic Query
Filtering by Channel
Products can be scheduled against channels. Use thechannel scope to return only products that are active on the current channel.
Filtering by Customer Group
Similarly, use thecustomerGroup scope to return only products visible to the current customer group.
Sorting
Products in a collection have a default sort order determined by the collection’ssort field. The products() relationship already orders by the position pivot column, which reflects this configured sort.
The available sort options built into Lunar are:
The
position values on the pivot table are automatically recalculated when the collection’s sort field is changed. For example, setting sort to min_price:asc triggers a background job that reorders the position values by price.Custom Sort on the Query
To let customers choose a sort order at browse time, override the default pivot ordering on the query.Filtering
Product filtering depends on the storefront’s requirements. Below are some common filtering approaches.Filtering by Brand
Filtering by Price Range
Prices are stored as integers in the lowest denomination (e.g., cents). Multiply the customer-facing price by 100 (or the currency’s factor) before comparing.
Filtering by Product Availability
Displaying Products
Product Grid
Pagination
Laravel’s built-in pagination works directly with the collection product query.withQueryString() preserves any active filter and sort parameters in the pagination links.
Child Collections
Collections can contain child collections (subcategories). Display them to help customers navigate deeper into the catalog.Putting It All Together
Here is a complete controller that prepares all the data a PLP needs:Next Steps
- Review the Collections reference for the full list of model fields, relationships, and sort options.
- Review the Products reference for product scopes and variant details.
- Review the Storefront Session reference to manage channel, currency, and customer group context.
- Review the Product Display Page guide for displaying individual products after a customer clicks through from the listing.