Blog / Advanced search forms with Bolt CMS

While developing a site with Bolt, it’s possible you’ll run into a situation where Bolt’s built-in search functions don’t go far enough. For example: product search or other multi-faceted searches.

For situations like this, you can use the Bolt extension system to add the exact search features you need. You can do things like:

  • Write custom SQL queries
  • Collect the result data into whatever formats you need
  • Display the results in a custom format

Continue reading for details on how to do the above.

Example code

Here’s some sample code that shows everything discussed here, along with some advanced QueryBuilder gymnastics:

https://gist.github.com/use/9cfbf26db7795da664e93a2bd793f69d

Step 1: Routing

To set up routing, you’ll use the registerFrontendRoutes method of the SimpleExtension object that your extension extends. You most likely only need to add one route.


protected function registerFrontEndRoutes(ControllerCollection $collection)
{
    $collection->get('/search', 'callbackProductSearch');
}

Please note that the string ‘callbackProductSearch’ in this example refers to the name of another method (which we’ll create below) on this extension object. But, it could’ve also been an anonymous function.

Step 2: Creating a callback

Next, we need to create the method that will be called when the ‘/search’ route is visited. We’ll pass in the application container ($app) and the request data ($request) via the method signature.

protected function callbackProductSearch(Application $app, Request $request)
{
    // stuff goes here
}

Side note: the $app container

The $app container is practically a global variable that gives you access to all the infrastructure inside Bolt. In this case, we’ll be using it to query the database. Bolt uses the Silex Application class, which in turn is based on the Pimple dependency injection container.

Step 3: Accessing request variables

Since the callback method has access to the $request variable, we can access Bolt’s GET parameters (AKA: the query string) like this:

$number = $request->query->get('number');

And here is how you can access POST variables:

$number = $request->request->get('number');

Step 4: Custom contenttype query

You can connect to the Bolt content store with code like this:


$repo = $app['storage']->getRepository('products');
$qb = $repo->createQueryBuilder();

$qb is an instance of Doctrine’s QueryBuilder class. It has a wealth of features and can be used to construct queries safely and programmatically. For example, if your products table has a “number” field, you can search it like this:


$repo = $app['storage']->getRepository('products');
$qb = $repo->createQueryBuilder();
$qb->andWhere("number = :number");
$qb->setParameter('number', $number);

This will safely escape the value of $number, while automatically constructing your SQL statement with valid syntax. See the full example code for more details.

Step 5: Fetch and output search results

$results = $qb->execute()->fetchAll();

$html = $app['twig']->render('product_search.twig', [
    'results'  => $results
]);

return new Response($html);

In your custom search results twig template, you can do something like this:

<table>
    {% for product in results %}
        {% set link = "/product/" ~ product.slug %}
        <tr>
            <td><a href="{{ link }}">{{ product.name }}</a></td>
            <td>{{ product.number }}</td>
        </tr>
    {% endfor %}
</table>

Closing thoughts

As you can see, Bolt provides an easy way to tie into its internal MVC architecture to create custom search features for your websites. It’s as simple as querying the database, and displaying the results. For a complex cart example, see our article about creating a custom cart for Bolt.

Will

Web developer

More Posts

Follow Me:
Twitter