Как мне объединить две таблицы в третьем отношении n ..n (hasAndBelongsToMany) в CakePHP?

StackOverflow https://stackoverflow.com/questions/112730

Вопрос

У меня есть n...n структура для двух таблиц, makes и models.Пока никаких проблем.

В третьей таблице (products) нравится:

id
make_id
model_id
...

Моя проблема заключается в создании представления для продуктов одного конкретного типа. make внутри моего ProductsController содержащий только то, что создает модели:

Я думал, это может сработать:

var $uses = array('Make', 'Model');

$this->Make->id = 5; // My Make

$this->Make->find(); // Returns only the make I want with it's Models (HABTM)
$this->Model->find('list'); // Returns ALL models
$this->Make->Model->find('list'); // Returns ALL models

Итак, если я хочу использовать list чтобы перейти к моему представлению для создания переключателей, мне нужно будет выполнить foreach() в моем make массив для поиска названий всех моделей, создания нового массива и отправки на просмотр через $this->set().

$makeArray = $this->Make->find();
foreach ($makeArray['Model'] as $model) {
    $modelList[] = $model['title'];
}
$this->set('models', $models)

Есть ли какой-нибудь более простой способ получить этот список, не подчеркивая make Массив.Разработка таких сценариев в моих приложениях будет обычной задачей.

Заранее спасибо за любую подсказку!

Это было полезно?

Решение 5

Решение может быть достигнуто с помощью with операция в массиве habtm над моделью.

Используя with вы можете определить "среднюю" таблицу следующим образом:

$habtm = " ...
  'with' => 'MakeModel',
   ... ";

И внутренне, в Модели или контроллере, вы можете выдавать условия для find способ.

Видишь: http://www.cricava.com/blogs/index.php?blog=6&title=modelizing_habtm_join_tables_in_cakephp_&more=1&c=1&tb=1&pb=1

Другие советы

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

SELECT * FROM makes, models, products WHERE make_id = 5

Вы не принимаете во внимание взаимосвязи (если только Cake автоматически не понимает взаимосвязи таблиц)

Вероятно, вы ищете что-то, что объединяет эти вещи воедино:

SELECT models.title FROM models 
INNER JOIN products 
  ON products.model_id = models.model_id 
  AND products.make_id = 5

Надеюсь, это толчок в правильном направлении?

Судя по вашему комментарию, вы спрашиваете, как получить результаты от определенной модели, где условие находится в модели, связанной с HABTM.То есть.то, что вы обычно делаете с оператором JOIN в необработанном SQL.
В настоящее время это одно из немногих слабых мест Cake.Существуют различные стратегии, чтобы справиться с этим.

  • Попросите связанную модель B вернуть все идентификаторы возможных кандидатов для модели A, затем выполните второй запрос для модели A.То есть.:

    $this->ModelB->find('first', array('conditions' => array('field' => $condition)));
    array(
        ['ModelB'] => array( ... ),
        ['ModelA'] => array(
            [0] => array(
                'id' => 1
            )
    )
    

    Теперь у вас есть массив всех идентификаторов ModelA, принадлежащих ModelB, который соответствует вашим условиям, который вы можете легко извлечь с помощью Set::extract() .По сути, эквивалент SELECT model_a.id FROM model_b JOIN model_a WHERE model_b.field = xxx.Далее вы ищете модель:

     $this->ModelA->find('all', array('conditions' => array('id' => $model_a_ids)));
    

    Это приведет к SELECT model_a.* FROM model_a WHERE id IN (1, 2, 3), что является обходным способом выполнения инструкции JOIN .Если вам нужны условия для более чем одной связанной модели, повторяйте до тех пор, пока у вас не будут все идентификаторы для ModelA, SQL будет использовать пересечение всех идентификаторов (WHERE id IN (1, 2, 3) AND id IN (3, 4, 5)).

  • Если вам нужно только одно условие для ModelB, но вы хотите получить ModelA, просто найдите ModelB.Cake автоматически извлекет для вас соответствующие модели (см. Выше).Возможно, вам потребуется установить ::extract() их снова, но этого уже может быть достаточно.

  • Вы можете использовать описанный выше метод и комбинировать его с Сдерживаемое поведение чтобы получить больше контроля над результатами.

  • Если все остальное не удается или описанные выше методы просто приводят к слишком большим накладным расходам, вы все равно можете написать свой собственный необработанный SQL с помощью $this->Model->query().Если вы придерживаетесь стандартных стандартов SQL (правильное именование таблиц с FROM model_as AS ModelA) Cake по-прежнему будет корректно обрабатывать ваши результаты после обработки.

Надеюсь, это направит вас в правильном направлении.

Все ваши различные вызовы Make->find() и Model-> find() полностью независимы друг от друга.Даже если Make-> Model-> find() совпадает с Model-> find(), Cake никоим образом не запоминает и не учитывает то, что вы уже нашли в других моделях.То, что вы ищете, это что-то вроде:

$this->Product->find('all', array('conditions' => array('make_id' => 5)));

Проверьте метод Set::extract() для получения списка названий моделей из результатов $this->Make->find()

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top