Chuyển tới nội dung chính

2. Template Hooks: Product List (Trang Danh Sách Sản Phẩm)

Trang danh sách sản phẩm (danh mục, thương hiệu, tìm kiếm) sử dụng class \Ecommerce\Template\ProductsIndex. Hooks được đăng ký trong bootstrap/template-index.php.


Sơ Đồ Hook​

content_products_index (priority 10)
└── ProductsIndex::index()
└── page_products_index_view
├── 10 → sort() Thanh sắp xếp/lọc
├── 40 → products() Lưới sản phẩm
└── 50 → pagination() Phân trang

Danh Sách Hook Render (page_products_index_view)​

Class \Ecommerce\Template\ProductsIndex chỉ có bốn method: index, sort, products, pagination. Ba trong số đó được gắn vào page_products_index_view:

Hook NamePriorityHandler mặc địnhMô Tả
page_products_index_view10ProductsIndex::sortThanh Sort (giá tăng/giảm, mới nhất...)
page_products_index_view40ProductsIndex::productsLưới sản phẩm chính
page_products_index_view50ProductsIndex::paginationThanh phân trang

[!NOTE] Các khoảng priority 20, 30, 60 đang trống — không có handler mặc định nào. Đây là chỗ dành sẵn cho plugin/theme chèn nội dung (banner, tab danh mục con, text SEO cuối trang). Không tồn tại method contentTop(), category() hay contentBottom() trên ProductsIndex.


Ví Dụ Thực Tế​

💡 Thêm Banner Khuyến Mãi ngay dưới thanh Sort​

add_action('page_products_index_view', function() {
$category = Cms::getData('category');
if(!empty($category->image)) {
echo '<div class="promo-banner">';
echo Image::large($category->image, $category->name)->html();
echo '</div>';
}
}, 20); // sau sort (10), trước lưới sản phẩm (40)

💡 Thêm Bộ Lọc Theo Giá​

add_action('page_products_index_view', function() {
echo '<div class="price-range-filter">';
echo '<input type="range" name="price_min" min="0" max="10000000"/>';
echo '</div>';
}, 11); // Ngay sau sort (10)

💡 Ẩn Thanh Sort Mặc Định​

remove_action('page_products_index_view', [\Ecommerce\Template\ProductsIndex::class, 'sort'], 10);

Khi gỡ handler bằng remove_action, priority truyền vào phải trùng với priority lúc đăng ký, nếu không sẽ không gỡ được.


Hooks Controller (Sửa Query Sản Phẩm)​

Các filter này chạy trong helper dựng danh sách sản phẩm (plugins/sicommerce/app/helpers/helpers.php) trước khi render.

Hook NameTham SốMô Tả
controllers_product_index_args$querySửa query builder ban đầu
controllers_product_index_count$countOverride tổng số kết quả dùng để phân trang
controllers_product_index_paging$paginationSửa object pagination
controllers_product_index_query$query, $requestSửa query cuối cùng (sau khi áp sort/limit)
controllers_product_index_objects$objectsSửa/lọc kết quả sản phẩm
controllers_product_index_data$data, $idSửa mảng dữ liệu dựng khối danh sách sản phẩm

controllers_product_index_objects được dùng lại ở nhiều nơi: trang danh sách, trang bộ sưu tập (ProductController::collection) và trang tìm kiếm (ProductSearch). Hook vào đây là ảnh hưởng cả ba.

// Chỉ lấy sản phẩm đang còn hàng
add_filter('controllers_product_index_args', function($query) {
$query->where('in_stock', 1);
return $query;
});

// Loại bỏ sản phẩm hết hạn khỏi kết quả
add_filter('controllers_product_index_objects', function($products) {
return $products->filter(function($product) {
$expiry = Product::getMeta($product->id, 'expiry_date', true);
return empty($expiry) || strtotime($expiry) > time();
});
});

Hooks Template Breadcrumb & Layout​

Hook NameHandler mặc địnhPriorityMô Tả
theme_breadcrumb_products_index_dataBreadcrumb::productsIndex20Breadcrumb trang danh sách
theme_breadcrumb_products_detail_dataBreadcrumb::productsDetail20Breadcrumb trang chi tiết
template_layout_products_indexLayout::getCategoryLayout10Layout trang danh sách sản phẩm
template_view_products_indexLayout::getCategoryView10View trang danh sách sản phẩm
template_layout_products_allLayout::getCategoryLayout10Layout trang tất cả sản phẩm
template_view_products_allLayout::getCategoryView10View trang tất cả sản phẩm
template_layout_products_detailLayout::getProductLayout10Layout trang chi tiết
template_view_products_detailLayout::getProductView10View trang chi tiết
template_layout_products_collectionLayout::getCollectionLayout10Layout trang bộ sưu tập
template_view_products_collectionLayout::getCollectionView10View trang bộ sưu tập

Không có hook template_layout_products_category / template_view_products_category — tên đúng là ..._products_index (hoặc ..._products_all).