如何在PHP中实现分类、品牌与产品的左右分栏Algolia自动补全
实现Algolia自动补全左右分栏布局
我正在开发一个PHP项目,集成Algolia自动补全功能以提供分类、品牌和产品的建议,希望自动补全界面分为左右两栏:左侧展示分类和品牌,右侧展示产品建议,效果类似下图:

当前代码
以下是初始化Algolia并设置自动补全的JavaScript代码:
<script type="text/javascript"> const ALGOLIA_APP_ID = 'my app id'; const ALGOLIA_API_KEY = 'my key'; const ALGOLIA_INDEX_NAME_1 = 'shop_PRODUCTS'; const ALGOLIA_INDEX_NAME_2 = 'shop_CATEGORY'; const ALGOLIA_INDEX_NAME_3 = 'shop_BRANDS'; const ALGOLIA_PRODUCT_URL = '<?php echo base_url('product'); ?>/'; const ALGOLIA_CATEGORY_URL = '<?php echo base_url('category'); ?>/'; const ALGOLIA_BRAND_URL = '<?php echo base_url('products/brand'); ?>/'; const ALGOLIA_IMAGE_PREFIX = '<?php echo CDN_LINK; ?>/cpanel/assets/uploads/product/'; // Initialize Algolia client const client = algoliasearch(ALGOLIA_APP_ID, ALGOLIA_API_KEY); const index1 = client.initIndex(ALGOLIA_INDEX_NAME_1); const index2 = client.initIndex(ALGOLIA_INDEX_NAME_2); const index3 = client.initIndex(ALGOLIA_INDEX_NAME_3); autocomplete('#search-input', {}, [ { source: autocomplete.sources.hits(index1, { hitsPerPage: 5 }), displayKey: 'prd_name', templates: { header: '<div class="suggestion-header"><h3 class="gcom__typeahead-results-heading"><span class="gcom__typeahead-results-heading-label">Suggestions</span></h3></div>', suggestion: function(suggestion) { return '<a class="atagproduct" href="'+ ALGOLIA_PRODUCT_URL + suggestion.prd_slug + '"><div class="suggestion-item">' + '<img class="suggestion-image" src="'+ ALGOLIA_IMAGE_PREFIX + suggestion.prd_image + '" />' + '<div class="sugges-text-column">' + '<span class="suggestion-name">' + suggestion._highlightResult.prd_name.value + '</span>' + '<span class="suggestion-description">' + suggestion._highlightResult.prd_description.value + '</span>' + '</div>' + '</div></a>'; } } }, { source: autocomplete.sources.hits(index2, { hitsPerPage: 5 }), displayKey: 'cat_title', templates: { header: '<div class="suggestion-header"><h3 class="gcom__typeahead-results-heading"><span class="gcom__typeahead-results-heading-label">Category</span></h3></div>', suggestion: function(suggestion) { return '<a class="atagproduct" href="'+ ALGOLIA_CATEGORY_URL + suggestion.cat_slug + '"><div class="suggestion-item">' + '<span class="suggestion-name">' + suggestion._highlightResult.cat_title.value + '</span>' + '</div></a>'; } } }, { source: autocomplete.sources.hits(index3, { hitsPerPage: 5 }), displayKey: 'brd_title', templates: { header: '<div class="suggestion-header"><h3 class="gcom__typeahead-results-heading"><span class="gcom__typeahead-results-heading-label">Brands</span></h3></div>', suggestion: function(suggestion) { return '<a class="atagproduct" href="'+ ALGOLIA_BRAND_URL + suggestion.brd_slug + '"><div class="suggestion-item">' + '<span class="suggestion-name">' + suggestion._highlightResult.brd_title.value + '</span>' + '</div></a>'; } } } ]); </script>
需求布局
- 分类和品牌显示在左侧
- 产品建议显示在右侧
修改方案
要实现左右分栏布局,需要自定义Algolia Autocomplete的容器结构,并通过CSS控制布局,同时指定不同数据源的渲染位置。
1. 修改JavaScript代码
调整autocomplete的配置,添加自定义容器模板,并为每个数据源指定对应的渲染区域:
<script type="text/javascript"> const ALGOLIA_APP_ID = 'my app id'; const ALGOLIA_API_KEY = 'my key'; const ALGOLIA_INDEX_NAME_1 = 'shop_PRODUCTS'; const ALGOLIA_INDEX_NAME_2 = 'shop_CATEGORY'; const ALGOLIA_INDEX_NAME_3 = 'shop_BRANDS'; const ALGOLIA_PRODUCT_URL = '<?php echo base_url('product'); ?>/'; const ALGOLIA_CATEGORY_URL = '<?php echo base_url('category'); ?>/'; const ALGOLIA_BRAND_URL = '<?php echo base_url('products/brand'); ?>/'; const ALGOLIA_IMAGE_PREFIX = '<?php echo CDN_LINK; ?>/cpanel/assets/uploads/product/'; // Initialize Algolia client const client = algoliasearch(ALGOLIA_APP_ID, ALGOLIA_API_KEY); const indexProducts = client.initIndex(ALGOLIA_INDEX_NAME_1); const indexCategories = client.initIndex(ALGOLIA_INDEX_NAME_2); const indexBrands = client.initIndex(ALGOLIA_INDEX_NAME_3); autocomplete('#search-input', { // 自定义下拉框整体容器 templates: { container: () => ` <div class="autocomplete-container"> <div class="autocomplete-left"> <div class="left-section" id="category-section"></div> <div class="left-section" id="brand-section"></div> </div> <div class="autocomplete-right" id="product-section"></div> </div> ` } }, [ // 产品数据源(渲染到右侧) { source: autocomplete.sources.hits(indexProducts, { hitsPerPage: 5 }), displayKey: 'prd_name', templates: { header: '<div class="suggestion-header"><h3 class="gcom__typeahead-results-heading"><span class="gcom__typeahead-results-heading-label">Suggestions</span></h3></div>', suggestion: (suggestion) => ` <a class="atagproduct" href="${ALGOLIA_PRODUCT_URL}${suggestion.prd_slug}"> <div class="suggestion-item"> <img class="suggestion-image" src="${ALGOLIA_IMAGE_PREFIX}${suggestion.prd_image}" /> <div class="sugges-text-column"> <span class="suggestion-name">${suggestion._highlightResult.prd_name.value}</span> <span class="suggestion-description">${suggestion._highlightResult.prd_description.value}</span> </div> </div> </a> `, // 指定产品结果插入到右侧区域 container: () => document.getElementById('product-section') } }, // 分类数据源(渲染到左侧) { source: autocomplete.sources.hits(indexCategories, { hitsPerPage: 5 }), displayKey: 'cat_title', templates: { header: '<div class="suggestion-header"><h3 class="gcom__typeahead-results-heading"><span class="gcom__typeahead-results-heading-label">Category</span></h3></div>', suggestion: (suggestion) => ` <a class="atagproduct" href="${ALGOLIA_CATEGORY_URL}${suggestion.cat_slug}"> <div class="suggestion-item"> <span class="suggestion-name">${suggestion._highlightResult.cat_title.value}</span> </div> </a> `, // 指定分类结果插入到左侧分类区域 container: () => document.getElementById('category-section') } }, // 品牌数据源(渲染到左侧) { source: autocomplete.sources.hits(indexBrands, { hitsPerPage: 5 }), displayKey: 'brd_title', templates: { header: '<div class="suggestion-header"><h3 class="gcom__typeahead-results-heading"><span class="gcom__typeahead-results-heading-label">Brands</span></h3></div>', suggestion: (suggestion) => ` <a class="atagproduct" href="${ALGOLIA_BRAND_URL}${suggestion.brd_slug}"> <div class="suggestion-item"> <span class="suggestion-name">${suggestion._highlightResult.brd_title.value}</span> </div> </a> `, // 指定品牌结果插入到左侧品牌区域 container: () => document.getElementById('brand-section') } } ]); </script>
2. 添加CSS样式
通过Flexbox实现左右分栏布局,调整各区域的样式:
/* 自动补全容器 */ .autocomplete-container { display: flex; min-width: 700px; background: #fff; border: 1px solid #e0e0e0; border-radius: 4px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } /* 左侧栏 */ .autocomplete-left { flex: 1; padding: 12px; border-right: 1px solid #f0f0f0; } /* 右侧栏 */ .autocomplete-right { flex: 2; padding: 12px; } /* 左侧区域间距 */ .left-section { margin-bottom: 16px; } /* 建议项样式 */ .suggestion-item { display: flex; align-items: center; padding: 8px 0; border-bottom: 1px solid #f5f5f5; cursor: pointer; } .suggestion-item:hover { background-color: #fafafa; } /* 产品图片样式 */ .suggestion-image { width: 48px; height: 48px; object-fit: cover; border-radius: 4px; margin-right: 10px; } /* 建议标题样式 */ .suggestion-header { margin-bottom: 8px; } .gcom__typeahead-results-heading { font-size: 14px; font-weight: 600; color: #666; margin: 0; } /* 建议文本样式 */ .suggestion-name { display: block; font-size: 14px; color: #333; } .suggestion-description { display: block; font-size: 12px; color: #999; margin-top: 4px; }
关键说明
- 自定义容器模板:通过
templates.container创建左右分栏的DOM结构,为分类、品牌、产品分别预留独立的渲染节点。 - 指定数据源容器:每个数据源的
templates.container函数返回对应的DOM元素,确保不同类型的搜索结果渲染到正确的区域。 - Flexbox布局:使用Flexbox实现左右分栏,通过
flex属性调整左右栏的宽度比例,同时添加样式优化交互体验。
内容的提问来源于stack exchange,提问作者Martin
相关产品推荐
相关产品推荐

