Объединение таблиц БД с помощью ассоциации hasMany — сохранение в массиве

#mysql #sql #cakephp #jointable

#mysql #sql #cakephp #Присоединиться

Вопрос:

В приложении CakePHP, которое я создаю, профиль может иметь несколько местоположений; таблицы называются «профили» и «местоположения», а в классах моделей я определил отношение hasMany. Теперь я хочу, чтобы пользователь мог искать профили на основе их местоположений. После прочтения некоторых вопросов здесь и кулинарной книги CakePHP я решил, что мне нужно использовать SQL joins (на самом деле задействовано больше таблиц, и результат поиска должен основываться на условиях, касающихся разных таблиц).

Я написал следующую функцию внутри моей модели профиля:

 public function findProfiles($long, $lat){

$options['joins'] = array(
    array('table' => 'locations',
          'alias' => 'Location',
          'type' => 'Inner',
          'conditions' => array('Location.profile_id = Profile.id'))
    );


$options['order'] = array('Location.lng ASC'); //this is just as trial

return $this->find('all',$options);
}
  

Код работает, но я получаю копию профиля для каждого местоположения, которым он обладает. То есть, если профиль содержит 5 позиций, я получаю пять экземпляров этого профиля (каждый экземпляр содержит все пять позиций!)

Как я могу этого добиться?

[править]

например. предположим, у меня есть только один профиль с двумя позициями. Я получаю:

 result[0][Profile]
         [Position][0]
                   [1]
      [1][Profile]
         [Position][0]
                   [1]
  

Где данные в result[0] и result [1] идентичны.

Комментарии:

1. не могли бы вы опубликовать пример того, какой массив вы получаете и что вы хотите? может быть, это потому, что сейчас утро, но я вас не совсем понимаю…

2. Ха-ха, хороший вопрос. Оказывается, что каждый экземпляр, который я получаю, на самом деле содержит все позиции в массиве, как я и хочу. Но если профиль имеет несколько позиций, я получаю несколько копий профиля, каждая копия содержит все позиции (т. Е. все копии идентичны). Отредактировал вопрос

3. и какова ваша $recursive ценность для моделей профилей и местоположений? если для него не установлено значение -1 , это, вероятно, ваша проблема

4. забудьте об этом, я вас понял 🙂 Хм, это ваше внутреннее объединение. вы посмотрели на результирующий запрос, протестировали его в своей базе данных и получили ожидаемый результат? попробуйте изменить соединение на ‘left’ или выполнить a group by Profile.id и посмотреть, решит ли это или изменит ваш массив на нечто похожее на то, что вы хотите.

5. Ах, круто! строка «group by» сделала свое дело. Однако в одном вопросе в Кулинарной книге явно сказано: «Помните, что вам нужно установить для рекурсии значение -1, чтобы это работало: $this-> Channel-> recursive = -1;» в разделе, посвященном объединенным таблицам. Но сейчас мое приложение зависит от рекурсивного поиска. Это рискованно?

Ответ №1:

Проблема возникает из-за используемого типа соединения. С помощью inner join вы получите этот возврат с вашим запросом

 profile_id      location_id
---------------------------
     1               2
     1               3
  

И cake понимает это как две записи профиля, поэтому вы получаете повторяющиеся профили с одной и той же информацией.

Если бы это была вся ваша проблема, я бы сказал «перейти к сдерживаемому поведению и забыть объединения», но поскольку вы сказали, что задействовано больше таблиц, возможно, тип соединения изменить нельзя. Итак, чтобы получить уникальный профиль без повторений, вам нужно будет СГРУППИРОВАТЬ ПО запросу, чтобы получить

 profile_id      location_id
---------------------------
     1               2 amp; 3
  

с помощью кода, подобного этому

 $options['joins'] = array(
    array('table' => 'locations',
          'alias' => 'Location',
          'type' => 'Inner',
          'conditions' => array('Location.profile_id = Profile.id')),
          'group' => 'Profile.id'
    );
  

и вы избавитесь от повторений. Для решения подобных проблем в будущем лучше всего сначала проверить фактический запрос, который отправляется в БД, проверьте себя, соответствует ли результат, который дает вам БД, тому, что вы хотите, а если нет, посмотрите, что вы можете сделать в cake, чтобы изменить его.