diff --git a/en/02_Developer_Guides/00_Model/11_Scaffolding.md b/en/02_Developer_Guides/00_Model/11_Scaffolding.md index 88c8a0225..6f16442e7 100644 --- a/en/02_Developer_Guides/00_Model/11_Scaffolding.md +++ b/en/02_Developer_Guides/00_Model/11_Scaffolding.md @@ -25,6 +25,7 @@ use SilverStripe\ORM\DataObject; class MyDataObject extends DataObject { + // ... private static $db = [ 'IsActive' => 'Boolean', 'Title' => 'Varchar', @@ -226,9 +227,10 @@ use SilverStripe\ORM\DataObject; class MyDataObject extends DataObject { + // ... private static $searchable_fields = [ - 'Name', - 'ProductCode', + 'Name', + 'ProductCode', ]; } ``` @@ -251,6 +253,7 @@ use SilverStripe\ORM\DataObject; class MyDataObject extends DataObject { + // ... private static $searchable_fields = [ 'Name', 'BirthDate' => [ @@ -283,6 +286,7 @@ use SilverStripe\ORM\DataObject; class MyDataObject extends DataObject { + // ... private static string $general_search_field_name = 'my_general_field_name'; } ``` @@ -317,6 +321,7 @@ use SilverStripe\ORM\Filters\EndsWithFilter; class MyDataObject extends DataObject { + // ... private static string $general_search_field_filter = EndsWithFilter::class; } ``` @@ -350,6 +355,7 @@ use SilverStripe\ORM\DataObject; class MyDataObject extends DataObject { + // ... private static bool $general_search_split_terms = false; } ``` @@ -368,6 +374,7 @@ use SilverStripe\ORM\DataObject; class MyDataObject extends DataObject { + // ... private static $searchable_fields = [ 'Name', 'JobTitle', @@ -388,6 +395,7 @@ use SilverStripe\ORM\DataObject; class MyDataObject extends DataObject { + // ... private static $searchable_fields = [ 'Price', 'Description', @@ -405,6 +413,7 @@ use SilverStripe\ORM\DataObject; class MyDataObject extends DataObject { + // ... private static $general_search_field = 'Title'; } ``` @@ -433,15 +442,18 @@ use SilverStripe\ORM\DataObject; class MyDataObject extends DataObject { + // ... private static $searchable_fields = [ 'Name' => 'PartialMatchFilter', - 'ProductCode' => NumericField::class, + 'ProductCode' => [ + 'field' => NumericField::class, + ], ]; } ``` -If you assign a single string value, you can set it to be either a [FormField](api:SilverStripe\Forms\FormField) or [SearchFilter](api:SilverStripe\ORM\Filters\SearchFilter). To specify -both or to combine this with other configuration, you can assign an array: +If you assign a single string value, you can set it to be a [`SearchFilter`](api:SilverStripe\ORM\Filters\SearchFilter) class. To specify a specific [`FormField`](api:SilverStripe\Forms\FormField) to use or +specify both a form field *and* a filter - or to combine this with other configuration - you can assign an array: ```php namespace App\Model; @@ -452,6 +464,7 @@ use SilverStripe\ORM\DataObject; class MyDataObject extends DataObject { + // ... private static $searchable_fields = [ 'Name' => [ 'field' => TextField::class, @@ -466,6 +479,62 @@ class MyDataObject extends DataObject } ``` +#### Using `WithinRangeFilter` {#searchable-fields-withinrangefilter} + +If you want users to be able to filter by a field using a range, specify the [`WithinRangeFilter`](api:SilverStripe\ORM\Filters\WithinRangeFilter). This works out of the box with the numeric, date, datetime, and time fields that come in Silverstripe framework. + +```php +namespace App\Model; + +use SilverStripe\ORM\DataObject; +SilverStripe\ORM\Filters\WithinRangeFilter + +class MyDataObject extends DataObject +{ + // ... + private static array $db = [ + 'Price' => 'Currency', + ]; + + private static array $searchable_fields = [ + 'Price' => [ + 'filter' => WithinRangeFilter::class, + ], + ]; +} +``` + +This configuration will duplicate the form field, providing one form field for the "from" value, and another for the "to" value. Users can then filter within a range using the filters in the CMS. + +![filter by price within a range](../../_images/withinrangefilter.png) + +If a user fills in only the "from" or "to" field, the other will be populated with the minimum or maximum value defined by the relevant `DBField` class in [`getMinValue()`](api:SilverStripe\ORM\FieldType\DBField::getMinValue()) or [`getMaxValue()`](api:SilverStripe\ORM\FieldType\DBField::getMaxValue()) + +This can also be used with other field types, but you need to define what the default "from" and "to" values should be. You can do this with the `rangeFromDefault` and `rangeToDefault` keys as shown below. + +```php +namespace App\Model; + +use SilverStripe\ORM\DataObject; +SilverStripe\ORM\Filters\WithinRangeFilter + +class MyDataObject extends DataObject +{ + // ... + private static array $db = [ + 'Title' => 'Varchar', + ]; + + private static array $searchable_fields = [ + 'Title' => [ + 'filter' => WithinRangeFilter::class, + 'rangeFromDefault' => 'a', + 'rangeToDefault' => 'z', + ], + ]; +} +``` + ### Searching on relations To include relations (`$has_one`, `$has_many` and `$many_many`) in your search, you can use a dot-notation. @@ -477,6 +546,7 @@ use SilverStripe\ORM\DataObject; class Team extends DataObject { + // ... private static $db = [ 'Title' => 'Varchar', ]; @@ -499,6 +569,7 @@ use SilverStripe\ORM\DataObject; class Player extends DataObject { + // ... private static $db = [ 'Name' => 'Varchar', 'Birthday' => 'Date', @@ -515,7 +586,7 @@ class Player extends DataObject Use a single search field that matches on multiple database fields with `'match_any'`. This also supports specifying a `FormField` and a filter, though it is not necessary to do so. > [!CAUTION] -> If you don't specify a `FormField`, you must use the name of a real database field as the array key instead of a custom name so that a default field class can be determined. +> If you don't specify `field` or `dataType`, you must use the name of a real database field as the array key instead of a custom name so that a default field class can be determined. ```php namespace App\Model; @@ -524,6 +595,7 @@ use SilverStripe\Forms\TextField; class Order extends DataObject { + // ... private static $db = [ 'Name' => 'Varchar', ]; @@ -537,6 +609,8 @@ class Order extends DataObject 'CustomName' => [ 'title' => 'First Name', 'field' => TextField::class, + // Instead of defining "field" above, you could set "dataType" to a DBField instance like so: + // 'dataType' => DBVarchar::class, 'match_any' => [ // Searching with the "First Name" field will show Orders matching either // Name, Customer.FirstName, or ShippingAddress.FirstName @@ -549,6 +623,8 @@ class Order extends DataObject } ``` +You can also allow users to filter `match_any` with a range, using the configuration specified in [using `WithinRangeFilter`](#searchable-fields-withinrangefilter). + ## Summary fields Summary fields can be used to show a quick overview of the data for a specific [DataObject](api:SilverStripe\ORM\DataObject) record. The most common use @@ -561,6 +637,7 @@ use SilverStripe\ORM\DataObject; class MyDataObject extends DataObject { + // ... private static $db = [ 'Name' => 'Text', 'OtherProperty' => 'Text', @@ -585,6 +662,7 @@ use SilverStripe\ORM\DataObject; class OtherObject extends DataObject { + // ... private static $db = [ 'Title' => 'Varchar', ]; @@ -598,6 +676,7 @@ use SilverStripe\ORM\DataObject; class MyDataObject extends DataObject { + // ... private static $db = [ 'Name' => 'Text', 'Description' => 'HTMLText', @@ -626,6 +705,7 @@ use SilverStripe\ORM\DataObject; class MyDataObject extends DataObject { + // ... private static $db = [ 'Name' => 'Text', ]; @@ -652,6 +732,7 @@ use SilverStripe\ORM\DataObject; class MyDataObject extends DataObject { + // ... private static $db = [ 'Name' => 'Text', ]; diff --git a/en/08_Changelogs/6.0.0.md b/en/08_Changelogs/6.0.0.md index 966d70e94..148d2b5c7 100644 --- a/en/08_Changelogs/6.0.0.md +++ b/en/08_Changelogs/6.0.0.md @@ -20,6 +20,7 @@ title: 6.0.0 (unreleased) - [Changes to default cache adapters](#caching) - [Changes to scaffolded form fields](#scaffolded-fields) - [`SiteTree` uses form field scaffolding](#sitetree-scaffolding) + - [Filter within a range with `searchable_fields`](#searchable-withinrange) - [Changes to the templating/view layer](#view-layer) - [Changes to `LeftAndMain` and its subclasses](#leftandmain-refactor) - [Changes to password validation](#password-validation) @@ -596,6 +597,40 @@ SilverStripe\UserForms\Model\UserDefinedForm: +### Filter within a range with `searchable_fields` {#searchable-withinrange} + +Using the `searchable_fields` configuration, you can now declare that a field should be filtered using a range. This works out of the box with the numeric, date, datetime, and time fields that come in Silverstripe framework. + +> [!TIP] +> You can also provide ranges for other field types, but it requires some additional configuration. + +```php +namespace App\Model; + +use SilverStripe\ORM\DataObject; +use SilverStripe\ORM\Filters\WithinRangeFilter; + +class MyDataObject extends DataObject +{ + // ... + private static array $db = [ + 'Price' => 'Currency', + ]; + + private static array $searchable_fields = [ + 'Price' => WithinRangeFilter::class, + ]; +} +``` + +This configuration will duplicate the form field, providing one form field for the "from" value, and another for the "to" value. Users can then filter within a range using the filters in the CMS. + +![filter by price within a range](../_images/withinrangefilter.png) + +If a user fills in only the "from" or "to" field, the other will be populated with the minimum or maximum value defined by the relevant `DBField` class in [`getMinValue()`](api:SilverStripe\ORM\FieldType\DBField::getMinValue()) or [`getMaxValue()`](api:SilverStripe\ORM\FieldType\DBField::getMaxValue()) + +See the [searchable fields documentation](/developer_guides/model/scaffolding/#searchable-fields-withinrangefilter) for more details. + ### Changes to the templating/view layer {#view-layer} Note that the `SilverStripe\View\ViewableData` class has been renamed to [`SilverStripe\Model\ModelData`](api:SilverStripe\Model\ModelData). We will refer to it as `ModelData` in the rest of these change logs. diff --git a/en/_images/changelogs/5.2.0/elemental-badge.png b/en/_images/changelogs/5.2.0/elemental-badge.png deleted file mode 100644 index 9a2480ee3..000000000 Binary files a/en/_images/changelogs/5.2.0/elemental-badge.png and /dev/null differ diff --git a/en/_images/withinrangefilter.png b/en/_images/withinrangefilter.png new file mode 100644 index 000000000..ae9fc2f6e Binary files /dev/null and b/en/_images/withinrangefilter.png differ