У меня ArrayDataProvider с полем типа DateTime — дата рождения.
Я использую этот поставщик данных для вида сетки в разделе просмотра.
Поскольку даты рождения включают год рождения, сортировка работает не так, как ожидалось.
Есть ли способ как-то сказать механизму сортировки не учитывать годы, а сортировать только по месяцам и дням? Пользовательская функция сортировки возможно?
Редактировать: Что-то вроде sort
в C ++, где вы можете передать функцию сравнения.
Отредактировано текущее описание решения:
Мое решение в настоящее время состоит в том, чтобы включить год рождения в качестве отдельного поля в массиве, а годы рождения установлены на текущий год. Теперь даты с того же года и сортировка работает. Но отдельное поле для года рождения не кажется правильным. Я хотел бы получить все необходимые данные из одного объекта даты.
Это отдельное поле размалывает мои механизмы. Это не идеально.
Редактировать:
Ох, и его Yii2
Обновить
Есть также функции сортировки массивов PHP, которые принимают обратный вызов сравнения — например, uasort, который можно использовать в ассоциативных массивах, таких как мой:
uasort($persons, function($a, $b){
return strcasecmp( $b['date']->format('m-d'), $a['date']->format('m-d') );
});
Теперь мне нужно найти способ реализовать его в ArrayDataProvider. Есть идеи здесь?
Если у вас есть поставщик данных массива, вы, конечно, не можете использовать сортировку базы данных.
Чтобы разрешить сортировку по какому-либо выражению, необходимо предварительно рассчитать значение и настроить сортировку для атрибута, чтобы использовать вычисленное значение вместо исходного:
// assuming $data contains your data and 'birthdate' is the value you want to use for sorting
foreach($data as $key => $value) {
$data[$key]['sort_birthdate'] = date('m-d', strtotime($value['birthdate']));
}
$dataProvider = new \yii\data\ArrayDataProvider([
'allModels' => $data,
'sort' => [
'attributes' => [
'birthdate' => [
'asc' => [
'sort_birthdate' => SORT_ASC,
],
'desc' => [
'sort_birthdate' => SORT_DESC,
],
'label' => 'Date',
'default' => SORT_ASC
],
// list all other attributes here
],
]
]);
Если вам нужна пользовательская функция сравнения, вы должны расширить класс Yii для поддержки этого.
Вы можете создать кастом ArrayDataProvider
класс, который происходит от того, который поставляется с Yii и переопределить sortModels ()-метод.
Вы должны попробовать что-то вроде
use yii\db\Expression;
$dataProvider->setSort([
'attributes' => [
................................
'birthday' => [
'asc' => [
new Expression('DATE_FORMAT(birthday, "%m%d")') => SORT_ASC,
],
'desc' => [
new Expression('DATE_FORMAT(birthday, "%m%d")') => SORT_DESC,
],
'label' => 'Birthday',
'default' => SORT_ASC
],
................................
]
]);
Я не пробовал это.
Что работает наверняка, это сделать что-то вроде этого
$query->select([
new Expression('DATE_FORMAT(birthday, "%m%d") as show_date'),
.................................
]);
затем
/**
* Setup your sorting attributes
* Note: This is setup before the $this->load($params)
* statement below
*/
$dataProvider->setSort([
'attributes' => [
'id',
'show_date' => [
'asc' => [
'sort_date' => SORT_ASC,
],
'desc' => [
'sort_date' => SORT_DESC,
],
'label' => 'Date',
'default' => SORT_ASC
],
'price',
'gst',
'cost',
'quantity',
'profit',
]
]);