More

Creating a Custom SearchEngine

This enhancement is only available in SuiteCRM from version 7.11 onwards.

At the core of the SearchFramework there is the customisable nature of the SearchEngine class.
In order to make a SearchEngine sub-class that will be detected by the SearchWrapper
all you need to do is create a file in the custom/Extension/SearchEngines folder that
extends the SearchEngine class and implements the search(SearchQuery $query) method.

Customising view example

It is possible to customise how the search engine builds the interface by overriding the
displayForm() and displayResults() methods. If you need a higher degree of control,
you can override the searchAndDisplay() method entirely.

By default, displayForm() (displaying the search bar) and displayResults()
(displaying results and errors) call SearchFormController and SearchResultsController
respectively to create the views. These two classes are intended to be used and customised by custom search engines.

In the example below we will override the displayResults() method for the class above, and tell
the engine to load a different template file. The template file is a custom one placed in the same
folder as the engine, and it will show a table view with three columns: bean name, shipping address and billing address.
The said smarty template file can be found just after the code for the class.

use SuiteCRM\Search\SearchEngine;
use SuiteCRM\Search\SearchQuery;
use SuiteCRM\Search\SearchResults;
use SuiteCRM\Search\UI\SearchResultsController;
class CitySearchWithView extends SearchEngine
{
public function search(SearchQuery $query) { // Same as example above. }
public function displayResults(SearchQuery $query, SearchResults $results)
{
// Override the displayResults() method to change how the `SearchWrapper` will show the results.
// I have used an anonymous class just for simplicity in the example.
// The extended controller can be normally placed in a separate file.
$controller = new class($query, $results) extends SearchResultsController
{
public function __construct(SearchQuery $query, SearchResults $results)
{
parent::__construct($query, $results);
// Let us load a custom template file.
$this->view->setTemplateFile(__DIR__ . '/citysearch.tpl');
}
};
// Finally ask the Controller to render the view.
$controller->display();
}
}

Throwing errors

You can safely throw exceptions at any point while writing your own SearchEngine. Errors will be caught
by the SearchThrowableHandler class and a friendly message will be shown to the user.

If your SuiteCRM instance is in developer mode a detailed exception page will be shown, making it easier for you to
debug.

In the example below the same erroneous query is shown with developer mode on (left) and off (right).

If you wish to directly show an error message to the user, you can throw a SearchUserFriendlyException. Remember to
use the translation framework if you want the error to be localised, and never show details that are (too) technical.

Example of throwing a user-friendly error message:

throw new SearchUserFriendlyException(translate('LBL_ERROR_MESSAGE_INVALID_QUERY'));

Conclusions

To learn more about the Search Framework, do not be afraid to look at the code in lib\Search.
It is intended to be simple, readable and well-documented.