Получение рекурсивных данных с помощью функции чтения в CakePHP

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

В настоящее время я использую функцию чтения в своем действии «просмотр» на контроллере для получения всех данных.

Отношения между моделями уже созданы (belongTo, hasMany... и т.д.)

Когда вызывается представление входа, я получаю что-то вроде этого:

['Entry'] => Array
    (
        [id] => 1
        [body] => 'xxxxxx'
        [...] => ...
    )

[Comment] => Array
    (
        [0] => Array
            (
                [id] => 1
                [user_id] => 1
                [body] => This is an example of a comment guys!
                [created] => 0000-00-00 00:00:00
            )

        [1] => Array
            (
                [id] => 2
                [user_id] => 1
                [body] => This is the 2nd comment!!!
                [created] => 0000-00-00 00:00:00
            )
    )

Есть ли способ с помощью функции чтения получить также «рекурсивные» данные комментариев, такие как пользовательские данные, связанные с user_id? (чтобы узнать их имена и т.д.)

Я ожидаю что-то вроде этого:

['Entry'] => Array
    (
        [id] => 1
        [body] => xxxxxx
        [...] => ...
    )

[Comment] => Array
    (
        [0] => Array
            (
              [Comment] => Array
                   (
                      [id] => 1
                      [user_id] => 1
                      [body] => This is an example of a comment guys!
                      [created] => 0000-00-00 00:00:00  
                   )

              [User] => Array
                   (
                      [id] => 1
                      [username] => myusername
                      [created] => 0000-00-00 00:00:00  
                   )
            )

        [1] => Array
            (
              [Comment] => Array
                   (
                      [id] => 1
                      [user_id] => 2
                      [body] => fasdfasfaT
                      [created] => 0000-00-00 00:00:00  
                   )

              [User] => Array
                   (
                      [id] => 2
                      [username] => myusername2
                      [created] => 0000-00-00 00:00:00  
                   )
            )
    )

Спасибо.


person Alvaro    schedule 24.09.2012    source источник


Ответы (1)


Да это так.

Глубину ассоциаций можно контролировать с помощью атрибута recursive. , или, скорее, используйте поведение containable, чтобы указать, какие именно модели, которые вы хотите включить. Я всегда включаю это поведение для всех моделей в AppModel.php ($actsAs = array('Containable');). Затем используйте его следующим образом:

$this->Entry->find('all', array(
    ...
    'contain' => array('Comment' => 'User')
));

Результат будет выглядеть так:

['Entry'] => Array
(
    [id] => 1
    [body] => xxxxxx
    [...] => ...
)

[Comment] => Array
(
    [0] => Array
        (
          [id] => 1
          [user_id] => 1
          [body] => This is an example of a comment guys!
          [created] => 0000-00-00 00:00:00  
          [User] => Array
               (
                  [id] => 1
                  [username] => myusername
                  [created] => 0000-00-00 00:00:00  
               )
        )

)

По моему опыту, Cake не очень эффективен в поиске глубоких ассоциаций. В вашем случае он будет генерировать запрос для каждого Comment, чтобы получить его User. Я бы избежал этого, позволив Cake извлекать только комментарии, затем извлекать идентификаторы пользователей из комментариев, получать всех пользователей с этими идентификаторами в одном запросе, а затем добавлять эту информацию о пользователе к исходному результату.

person ori    schedule 24.09.2012
comment
В CakePHP 2.2 нет такого параметра для метода поиска: book.cakephp.org/2.0/en/models/retrieving-your-data.html#find - person Alvaro; 24.09.2012
comment
Вам необходимо включить поведение Containable. - person ori; 24.09.2012
comment
@ Стив, да, есть. @ori указал лучший метод - какой Containable содержит набор результатов для набора моделей/таблиц, которые вы определяете. Технически это переопределяет привязки модели на лету. Это то же самое, что и при использовании $this->Model->bindModel() или $this->Model->unbindModel() — на самом деле они используются. В противном случае да, установка $this->Model->recursive на значения выше 1 (единственный другой вариант — 2) будет медленным. - person Borislav Sabev; 25.09.2012