Version 6 pre-stable
This version of Silverstripe CMS has not yet been given a stable release. See the release roadmap for more information. Go to documentation for the most recent stable version.

SearchFilter modifiers

The filter(), exclude(), and other related methods on DataList, ArrayList, and EagerLoadedList specify exact matches by default. However, when calling these methods, there are a number of suffixes that you can put on field names to change this behavior. These are represented as SearchFilter subclasses and include:

See SilverStripe\ORM\Filters in the API docs for a full list of SearchFilter classes available in silverstripe/framework.

An example of a SearchFilter in use:

// fetch any player whose first name starts with the letter 'S' and has a PlayerNumber greater than 10
$players = Player::get()->filter([
    'FirstName:StartsWith' => 'S',
    'PlayerNumber:GreaterThan' => '10',
]);

// fetch any player whose name contains the letter 'z'
$players = Player::get()->filterAny([
    'FirstName:PartialMatch' => 'z',
    'LastName:PartialMatch' => 'z',
]);

Notice the syntax - to invoke a SearchFilter in the filter()/filterAny()/find() or exclude()/excludeAny() methods, you add a colon after the field name, followed by the name of the filter (excluding the actual word "filter"). e.g. for a StartsWithFilter: 'FieldName:StartsWith'

Developers can define their own SearchFilter if needing to extend the ORM filter and exclude behaviors.

Modifiers

SearchFilters can also take modifiers. The modifiers currently supported are ":not", ":nocase", and ":case" (though you can implement custom modifiers on your own SearchFilter implementations). These negate the filter, make it case-insensitive and make it case-sensitive, respectively.

The default comparison uses the database's default case sensitivity. For MySQL and MSSQL, this is case-insensitive. For PostgreSQL, this is case-sensitive. But you can declare the default case sensitivity for your project by setting the default_case_sensitive configuration property on SearchFilter like so:

SilverStripe\ORM\Filters\SearchFilter:
  default_case_sensitive: false

Though note that for backwards compatibility reasons, ArrayList is explicitly case sensitive by default. To change that, you must set ArrayList.default_case_sensitive to false.

SilverStripe\Model\List\ArrayList:
  default_case_sensitive: false
// Fetch players that their FirstName is exactly 'Sam'
// Caution: This might be case in-sensitive if MySQL or MSSQL is used
$players = Player::get()->filter([
    'FirstName:ExactMatch' => 'Sam',
]);

// Fetch players that their FirstName is exactly 'Sam' (force case-sensitive)
$players = Player::get()->filter([
    'FirstName:ExactMatch:case' => 'Sam',
]);

// Fetch players that their FirstName is exactly 'Sam' (force NOT case-sensitive)
$players = Player::get()->filter([
    'FirstName:ExactMatch:nocase' => 'Sam',
]);

By default the :ExactMatch filter is applied, so we can shorthand the above to:

// Default DB engine behaviour
$players = Player::get()->filter('FirstName', 'Sam');
// case-sensitive
$players = Player::get()->filter('FirstName:case', 'Sam');
// NOT case-sensitive
$players = Player::get()->filter('FirstName:nocase', 'Sam');

Note that all search filters (e.g. :PartialMatch) refer to services registered with Injector within the DataListFilter. prefixed namespace. New filters can be registered using the below yml config:

SilverStripe\Core\Injector\Injector:
  DataListFilter.CustomMatch:
    class: MyVendor\Search\CustomMatchFilter

The following is a query which will return everyone whose first name starts with "S", either lowercase or uppercase:

$players = Player::get()->filter([
    'FirstName:StartsWith:nocase' => 'S',
]);

// use :not to get everyone whose first name does NOT start with "S"
$players = Player::get()->filter([
    'FirstName:StartsWith:not' => 'S',
]);

You can combine :not and either :nocase or :case. Note that the order doesn't matter - these two calls are equivalent:

$players = Player::get()->filter([
    'FirstName:StartsWith:nocase:not' => 'S',
]);
$players = Player::get()->filter([
    'FirstName:StartsWith:not:nocase' => 'S',
]);

API documentation