Работа с моделями, которые не имеют ни одного внешнего ключа в CakePHP

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

Вопрос

Я работаю над приложением, в котором данные импортированы из иностранного (и полностью неизменяемого) источника.Я упрошу некоторые таблицы, чтобы объяснить проблему.Ниже приведены таблицы с их первичными ключами.

invoices     (doc_number, date_printed, batch_number)
headers      (doc_number, date_printed, batch_number)
deliveries   (doc_number, date_printed, batch_number)
transactions (doc_number, date_printed, batch_number, line_number)
messages     (doc_number, date_printed, batch_number, line_number)

Таким образом, вы можете видеть, что Счета-фактуры, Заголовки и Поставки имеют взаимно однозначные связи.Соотношение счетов-фактур к транзакциям и Счетов-фактур к сообщениям - Один ко многим.

При импорте этих таблиц в мою собственную базу данных я изменил существующий первичный ключ на уникальный и добавил поле auto_incrementing (id) на каждом столе.

Теперь проблема заключается в настройке отношений в Cake, поскольку на самом деле он вообще не обрабатывает составные ключи.Мне удалось добиться, чтобы отношения "Один к одному" работали следующим образом:

class Invoice extends AppModel {
    public $name = "Invoice"
         , $hasOne = array(
            "Header" => array(
                'foreignKey' => false,
                'conditions' => array(
                    "Invoice.doc_number = Header.doc_number",
                    "Invoice.date_printed = Header.date_printed",
                    "Invoice.batch_number = Header.batch_number"
                )
            )
         )
    ;
}

И это работает, потому что взаимно однозначные отношения запрашиваются за один раз с помощью большого ЛЕВОГО СОЕДИНЕНИЯ.Попытка использовать тот же метод с отношением "один ко многим" (например, со счетами-фактурами и транзакциями) заканчивается неудачей, потому что Cake выполняет два запроса:первый - для поиска всех совпадающих счетов-фактур, а затем второй - для поиска всех транзакций с соответствующим внешним ключом, который соответствует результатам первого запроса:(вот упрощенный запрос, который он пытается выполнить)

SELECT `Transaction`.* FROM `transactions` AS `Transaction`
WHERE `Invoice`.`doc_number` = `Transaction`.`doc_number`
AND `Invoice`.`date_printed` = `Transaction`.`date_printed`
AND `Invoice`.`batch_number` = `Transaction`.`batch_number`

Вы можете видеть, что он не присоединяется к счетам-фактурам, поэтому запрос завершается.

Есть какие-нибудь идеи о том, как я могу заставить это работать?

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

Решение

В худшем случае вы можете использовать параметр finderQuery для Имеет много отношений.Это позволяет вам полностью переопределять запросы.

Возможно, вы также сможете добавить поле уникального идентификатора, объединяющее соответствующие поля данных в одно целое.Инструкция UPDATE может исправлять существующие данные, и можно настроить ТРИГГЕР для обновления новых записей по мере их добавления или изменения, предполагая, что ваша база данных поддерживает триггеры.

Редактировать: Учитывая все остальные сложности, возможно, вам было бы лучше вообще пропустить отношение hasMany и извлекать записи транзакций в отдельном find().Если вам нужно сделать это в очень многих местах, вы всегда можете обернуть это в функцию в модели счета-фактуры, подобную этой:

<?php
class Invoice extends AppModel() {
    ...

    function getInvoice($conditions) {
        $invoice = $this->find('first', compact('conditions'));

        $conditions = array(
             'Transaction.doc_number' => $invoice['Invoice']['doc_number'],
             'Transaction.date_printed' => $invoice['Invoice']['date_printed'],
             'Transaction.batch_number' => $invoice['Invoice']['batch_number']);
        $invoice['transactions'] = $this->Transaction->find('all', compact('conditions'));

        return $invoice;
    }
}
?>

Если вы используете подобную функцию в модели, не забывайте, что для счета-фактуры потребуется определенная связь с транзакцией, даже если вы не используете ее напрямую, чтобы была определена $this-> Транзакция.

Кроме того, если вы предпочитаете, чтобы данные возвращались таким образом, каким было бы отношение hasMany, вы всегда можете добавить цикл foreach, чтобы рекомбинировать их таким образом.

Обновить Там также есть Простые результаты поведения в кондитерской это позволило бы легко возвращать эти результаты из другой таблицы в формате обычной ассоциации hasMany.

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