如何在Magento 2中实现免费的搜索栏拼写纠错功能?
Hey John, great question—dealing with misspelled searches from less tech-savvy customers is such a common pain point, and since you can’t use third-party extensions, building this directly into Magento 2 via custom code is the perfect approach. Let’s walk through how to implement this step by step, using the method you referenced:
We’ll modify Magento’s native search logic to add spell checking. The core idea is to compare the user’s misspelled query against your product catalog (names, SKUs, etc.) using a similarity algorithm (like Levenshtein Distance) to find the closest matching valid term, then surface that as a suggestion or auto-redirect to the correct results.
Always use a custom module instead of modifying core files—it keeps your changes upgrade-safe. Here’s how to build it:
Step 1: Set Up the Custom Module Structure
Create a new module in app/code/YourVendor/SpellCorrection (replace YourVendor with your actual vendor name):
registration.php:<?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, 'YourVendor_SpellCorrection', __DIR__ );etc/module.xml:<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="YourVendor_SpellCorrection" setup_version="1.0.0"> <sequence> <module name="Magento_CatalogSearch"/> <module name="Magento_Search"/> </sequence> </module> </config>
Step 2: Override the Search Query Model
We’ll override Magento’s native Query model to add our spell-checking logic.
etc/di.xml:<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd"> <preference for="Magento\Search\Model\Query" type="YourVendor\SpellCorrection\Model\Query"/> </config>Model/Query.php:
This is where the magic happens—we’ll add a method to find the closest matching product term using Levenshtein Distance:<?php namespace YourVendor\SpellCorrection\Model; use Magento\Search\Model\Query as OriginalQuery; use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory; use Magento\Framework\App\ResourceConnection; class Query extends OriginalQuery { protected $productCollectionFactory; protected $resourceConnection; public function __construct( \Magento\Framework\Model\Context $context, \Magento\Framework\Registry $registry, \Magento\Search\Model\ResourceModel\Query $resource, \Magento\Search\Model\ResourceModel\Query\Collection $resourceCollection, \Magento\Search\Model\QueryFactory $queryFactory, \Magento\Framework\Session\SessionManagerInterface $session, \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig, \Magento\Framework\Stdlib\DateTime\DateTime $dateTime, CollectionFactory $productCollectionFactory, ResourceConnection $resourceConnection, array $data = [] ) { $this->productCollectionFactory = $productCollectionFactory; $this->resourceConnection = $resourceConnection; parent::__construct( $context, $registry, $resource, $resourceCollection, $queryFactory, $session, $scopeConfig, $dateTime, $data ); } public function getSuggestedQuery() { $originalQuery = $this->getQueryText(); if (empty($originalQuery)) { return parent::getSuggestedQuery(); } // Find the closest matching term from our product catalog $suggestedQuery = $this->findClosestMatchingTerm($originalQuery); if ($suggestedQuery && $suggestedQuery !== $originalQuery) { return $suggestedQuery; } // Fall back to Magento's native suggestion if no match is found return parent::getSuggestedQuery(); } protected function findClosestMatchingTerm($searchTerm) { $connection = $this->resourceConnection->getConnection(); $productTableName = $connection->getTableName('catalog_product_entity_varchar'); $nameAttributeId = $this->getAttributeId('name'); // Fetch all product names from the database $select = $connection->select() ->from($productTableName, ['value']) ->where('attribute_id = ?', $nameAttributeId) ->where('value IS NOT NULL'); $productNames = $connection->fetchCol($select); $closestTerm = null; $minDistance = PHP_INT_MAX; // Ignore very short search terms to avoid false matches $minSearchLength = 3; if (strlen($searchTerm) < $minSearchLength) { return null; } foreach ($productNames as $name) { if (strlen($name) < $minSearchLength) { continue; } // Calculate similarity between search term and product name $distance = levenshtein(strtolower($searchTerm), strtolower($name)); // Adjust these thresholds based on your users' typical spelling errors if ($distance < $minDistance && $distance <= 2 && abs(strlen($name) - strlen($searchTerm)) <= 3) { $minDistance = $distance; $closestTerm = $name; } } return $closestTerm; } protected function getAttributeId($attributeCode) { $connection = $this->resourceConnection->getConnection(); $eavAttributeTable = $connection->getTableName('eav_attribute'); $select = $connection->select() ->from($eavAttributeTable, ['attribute_id']) ->where('entity_type_id = ?', 4) // 4 is the entity ID for products ->where('attribute_code = ?', $attributeCode); return $connection->fetchOne($select); } }
Now we need to show the "Did you mean?" message on the search results page or mini search bar.
Edit your theme’s search template (e.g., app/design/frontend/YourTheme/Magento_Search/templates/result.phtml or form.mini.phtml) and add this code:
<?php $query = $block->getQuery(); ?> <?php if ($suggestedQuery = $query->getSuggestedQuery()): ?> <div class="search-spell-suggestion"> <?= __('Did you mean:') ?> <a href="<?= $block->getSearchUrl($suggestedQuery) ?>"><?= $suggestedQuery ?></a> </div> <?php endif; ?>
- Add Full-Text Indexing: For large catalogs, add a FULLTEXT index to the product name column in MySQL to speed up similarity checks.
- Cache Suggestions: Store computed search term suggestions in Magento’s cache to avoid repeating database queries.
- Expand to More Fields: Modify the
findClosestMatchingTermmethod to include SKUs, descriptions, or other product attributes.
Enable the module and compile the code:
bin/magento module:enable YourVendor_SpellCorrection bin/magento setup:upgrade bin/magento setup:di:compile bin/magento cache:clean
内容的提问来源于stack exchange,提问作者John

