Search provides a search module for CakePHP applications.
- CakePHP 3.0.0 or greater.
- Install the plugin with composer from your CakePHP Project's ROOT directory (where composer.json file is located)
php composer.phar require friendsofcake/search
- Load the plugin by running command
./bin/cake plugin load Search
or adding following to your config/bootstrap.php
Plugin::load('Search');
The plugin has three main parts which you will need to configure and include in your application.
There are three tasks during setup in your table class. Firstly you must add a
use
statement for the Search\Manager
. Next you need to attach the Search
behaviour to your table class. Then you have two options to work with the search
filters:
The first way is the prefered way as it works the same as many core classes as
well. In your table classes initialize()
method call the searchManager()
method, it will return a search manager instance. You can now add filters to the
manager by chaining them. The first arg of the add()
method is the field, the
second the filter using the dot notation of cake to load filters from plugins.
The third one is an array of filter specific options.
use Search\Manager;
class ExampleTable extends Table {
public function initialize(array $config)
{
parent::initialize();
// Add the behaviour to your table
$this->addBehavior('Search.Search');
// Setup search filter using search manager
$this->searchManager()
->value('author_id')
// Here we will alias the 'q' query param to search the `Articles.title`
// field and the `Articles.content` field, using a LIKE match, with `%`
// both before and after.
->add('q', 'Search.Like', [
'before' => true,
'after' => true,
'mode' => 'or',
'comparison' => 'LIKE',
'wildcardAny' => '*',
'wildcardOne' => '?'
'field' => [$this->aliasField('title'), $this->aliasField('content')]
])
->add('foo', 'Search.Callback', [
'callback' => function ($query, $args, $filter) {
// Modify $query as required
}
]);
}
You can use SearchManager::add()
method to add filter or use specific methods
like value()
, like()
etc. for in built filters.
In order for the Search plugin to work it will need to process the query params
which are passed in your URL. So you will need to edit your index
method to
accommodate this.
public function index()
{
$query = $this->Articles
// Use the plugins 'search' custom finder and pass in the
// processed query params
->find('search', ['_search' => $this->request->query])
// You can add extra things to the query if you need to
->contain(['Comments'])
->where(['title IS NOT' => null]);
$this->set('articles', $this->paginate($query));
}
The search
finder is dynamically provided by the Search
behavior.
Then add the Search Prg component to the necessary methods in your controller.
public function initialize()
{
parent::initialize();
$this->loadComponent('Search.Prg', [
// This is default config. You can modify "actions" as needed to make
// the PRG component work only for specified methods.
'actions' => ['index', 'lookup']
]);
}
The Search.Prg
component will allow your filtering forms to be populated using
the data in the query params. It uses the Post, redirect, get pattern.
Once you have completed all the setup you can now filter your data by passing
query params in your index method. Using the Article
example given above, you
could filter your articles using the following.
example.com/articles?q=cakephp
Would filter your list of articles to any article with "cakephp" in the title
or content
field. You might choose to make a get
form which posts the filter
directly to the URL, but if you're using the Search.Prg
component, you'll want
to use POST
.
In most cases you'll want to add a form to your index view which will search your data.
echo $this->Form->create();
// You'll need to populate $authors in the template from your controller
echo $this->Form->input('author_id');
// Match the search param in your table configuration
echo $this->Form->input('q');
echo $this->Form->button('Filter', ['type' => 'submit']);
echo $this->Html->link('Reset', ['action' => 'index']);
echo $this->Form->end();
If you are using the Search.Prg
component the forms current values will be
populated from the query params.
The Search plugin comes with a set of predefined search filters that allow you to easily create the search results you need. Use:
value
to limit results to exact matcheslike
to produce results containing the search query (LIKE
orILIKE
)finder
to produce results using a (custom) findercompare
to produce results requiring operator comparison (>
,<
,>=
and<=
)callback
to produce results using your own custom callable function
Sometimes you might want to search your data based on two of three inputs in
your form. You can use the filterEmpty
search option to ignore any empty fields.
// ExampleTable::initialize()
$searchManager->value('author_id', [
'filterEmpty' => true
]);
Be sure to allow empty in your search form, if you're using one.
echo $this->Form->input('author_id', ['empty' => 'Pick an author']);