Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save victorkurauchi/5542a7a8421612add2456397b0c90841 to your computer and use it in GitHub Desktop.
Save victorkurauchi/5542a7a8421612add2456397b0c90841 to your computer and use it in GitHub Desktop.
Example of how to create a custom search feature for the Bolt CMS, by making a local extension
<?php
namespace Bolt\Extension\DesignSpike\ExampleSearch;
use Bolt\Extension\SimpleExtension;
use Bolt\Routing\ControllerCollection;
use Doctrine\DBAL\Query\QueryBuilder;
use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class ExampleSearchExtension extends SimpleExtension
{
protected function registerFrontEndRoutes(ControllerCollection $collection)
{
$collection->get('/search', [$this, 'callbackProductSearch']);
}
protected function callbackProductSearch(Application $app, Request $request)
{
$number = trim($request->query->get('number'));
$name = trim($request->query->get('name'));
$cas = trim($request->query->get('cas'));
$formula = trim($request->query->get('formula'));
$general = trim($request->query->get('q'));
$results = [];
if ($number or $name or $cas or $formula or $general) {
$repo = $app['storage']->getRepository('products');
/** @var $qb QueryBuilder */
$qb = $repo->createQueryBuilder();
}
// search for the provided word in any of the main fields
if ($general) {
$qb->orWhere("number LIKE CONCAT('%', :general, '%')");
$qb->orWhere("cas LIKE CONCAT('%', :general, '%')");
$qb->setParameter('general', $general);
// get an array of all words entered in the visitor's search
$terms = array_filter(array_map('trim', explode(' ', $general)));
// name - search for items where every word in the search is found in the name field
$nameAndX = $qb->expr()->andX();
foreach ($terms as $index => $term) {
$param_name = "term".$index;
$nameAndX->add("name LIKE CONCAT('%', :".$param_name.", '%')");
$qb->setParameter($param_name, $term);
}
$qb->orWhere($nameAndX);
// synonyms - search for items where every word in the search is found in the synonyms field
$synonymsAndX = $qb->expr()->andX();
foreach ($terms as $index => $term) {
$param_name = "term".$index;
$synonymsAndX->add("synonyms LIKE CONCAT('%', :".$param_name.", '%')");
$qb->setParameter($param_name, $term);
}
$qb->orWhere($synonymsAndX);
}
if ($number) {
$qb->andWhere("number LIKE CONCAT('%', :number, '%')");
$qb->setParameter('number', $number);
}
if ($name) {
// this is where we should start the stuff about synonyms
$terms = array_filter(array_map('trim', explode(' ', $name)));
foreach ($terms as $index => $term) {
$param_name = "nameterm".$index;
$qb->andWhere("name LIKE CONCAT('%', :".$param_name.", '%') OR synonyms LIKE CONCAT('%', :".$param_name.", '%')");
$qb->setParameter($param_name, $term);
}
}
if ($cas) {
$qb->andWhere("cas LIKE CONCAT('%', :cas, '%')");
$qb->setParameter('cas', $cas);
}
if ($formula) {
// search for chemical formula - in mysql this requires binary search for case sensitivity
$qb->andWhere("formula REGEXP BINARY
CONCAT(
'(>|[[:<:]]|[[:lower:]]|[[:upper:]]|[[:digit:]]|\\\(|\\\))',
:formula,
'(<|[[:>:]]|[[:upper:]]|[[:digit:]]|\\\(|\\\))'
)");
// ensure that user-inputted special characters aren't parsed as regex characters
$escaped_formula = preg_quote($formula);
$qb->setParameter('formula', $escaped_formula);
}
if (isset($qb)) {
$results = $qb->execute()->fetchAll();
}
$html = $app['twig']->render('product_search.twig', [
'results' => $results
]);
return new Response($html);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment