Постраничная сортировка CakePHP при содержании данных

Это простое приложение для отслеживания увлечений пользователей. У пользователя может быть много увлечений, которые объединены в разные группы увлечений.

Итак, у меня есть 4 связанные таблицы: users, users_hobbies, hobbies, hobby_groups.

users - это отношение "имеет и принадлежит ко многим" к хобби через таблицу соединений users_hobbies. хобби принадлежит к хобби_группе, хобби_группа имеет много хобби

Имеет смысл, пока довольно просто.

В UsersHobbiesController у меня есть:

$paginate = [
    'contain' => [
        'Hobby' => [
            'fields' => ['id', 'name'],
            'HobbyGroup' => [
                'fields' => ['id', 'name']
            ]
        ]
    ]
];

Кроме того, в моей функции index() я строю разбиение на страницы.

$usersHobbies = $this->paginate('UsersHobby');
$this->set(compact('usersHobbies));

Когда я получаю доступ к переменной $usersHobbies в моем файле представления index.ctp, в нем есть данные, которые мне нужны для построения выходной таблицы. Это выглядит как:

array(
    (int) 0 => array(
        'UsersHobby' => array(...),
        'Hobby' => array(
            'id' => 'abc-def-ghi',
            'name' => 'Jet Skiing',
            'HobbyGroup' => array(
                'id' => 'oiuy-trew-qldf',
                'name' => 'Watersports'
            )
        )
    )
    ....
)

Чтобы отсортировать выходную таблицу, я добавил несколько столбцов сортировки:

<th><?php echo $this->Paginator->sort('Hobby.name', 'Hobby'); ?></th>
<th><?php echo $this->Paginator->sort('Hobby.HobbyGroup.id', 'Hobby'); ?></th>

Первый заголовок работает для сортировки по названию хобби. Но я не могу заставить второй заголовок сортироваться для HobbyGroup. Есть ли простой способ сделать это?

Я искал несколько часов в StackOverflow, но не могу найти ответ, который мне подходит. Спасибо.


person Zero Paskan    schedule 10.05.2018    source источник


Ответы (1)


Это не сработает, как вы ожидаете, из-за того, как CakePHP извлекает данные.

В зависимости от того, как вы настроите свои отношения, произойдет следующее: Cake сначала выберет хобби, а затем выполнит еще один запрос для групп хобби.

Таким образом, любая сортировка, которую вы применяете ко второму запросу, будет, как правило, бесполезной и потерянной, когда эти данные сопоставляются со списком хобби.

Так что у тебя есть

SELECT hobbies....

Затем будет выдан другой выбор

SELECT hooby_groups WHERE hobby_id IN [list of ids ] ORDER BY hobby_groups_id

Данные из второго выбора будут сопоставлены с первым, так что ваш заказ мало что сделал!

В зависимости от того, какую версию CakePHP вы используете, вы можете сделать несколько вещей:

  1. Определите отношения для использования стратегии INNER JOIN, чтобы избежать создания двух операторов SELECT. Таким образом, причина order by отсортирует все данные, как вы ожидаете. Предостережение заключается в том, что с INNER JOIN Хобби, которые не связаны ни с одной группой, никогда не будут выбраны при нумерации страниц.

  2. Если вы используете CakePHP 2.x, вы можете посмотреть Пользовательская разбивка на страницы запросов и создайте запрос таким, каким он вам нужен, чтобы он работал.

  3. Если вы используете CakePHP 3.x, у вас есть построитель запросов, и Paginator может разбить любой запрос на страницы, поэтому вы можете выполнять внутренние соединения там.

Чтобы помочь вам, вы можете использовать DebugKit из CakePHP, чтобы увидеть, какие фактические запросы выполняются и как настройка того или иного параметра влияет на то, как генерируется запрос. Вы увидите, где применяется order by и почему он может не работать.

В CakePHP 2.x вы можете использовать type для управления процессом соединения. Вам нужно использовать INNER

person Ilie Pandia    schedule 11.05.2018
comment
Спасибо за ваш ответ, он помог мне указать правильное направление. На самом деле я настроил свою переменную $paginate для использования левых объединений вместо содержания (я присоединил UserHobbies к Users, к Hobbies, к HobbyGroups слева), что позволило HobbyGroup быть непосредственно в возвращаемых результатах для сортировки. Мне также пришлось добавить массив всех столбцов для сортировки в качестве параметра белого списка при вызове функции paginate(), чтобы включить сортировку только по HobbyGroup.id, и все заработало. - person Zero Paskan; 12.05.2018