Frage

Ich arbeite an einer Anwendung, die zu importierenden Daten aus einer fremden (und ganz unveränderlich) Quelle hat. Ich werde einige der Tabellen vereinfachen, um das Problem zu erklären. Im Folgenden sind die Tabellen mit ihrem Primärschlüssel.

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)

Sie können also sehen, dass Rechnungen, Kopf- und Lieferungen One-to-One-Beziehungen haben. Rechnungen zu Transaktionen und Rechnungen zu Nachrichten sind One-to-Many.

diese Tabellen zu meiner eigenen Datenbank In dem Import, ich habe den vorhandenen Primärschlüssel geändert ein eindeutiger Schlüssel zu sein, und fügte eine auto_incrementing Feld (id) auf jeden Tisch.

Nun das Problem ist, die Beziehungen in Kuchen einrichten, da sie nicht wirklich überhaupt zusammengesetzte Schlüssel behandeln. Ich habe in der Lage gewesen, wie diese arbeiten, um die One-to-One-Beziehungen zu erhalten:

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"
                )
            )
         )
    ;
}

Und das funktioniert, weil die Eins-zu-eins-Beziehungen in einem Rutsch mit einem großen LEFT JOIN abgefragt. Der Versuch, die gleiche Methode mit einer Eins-zu-viele-Beziehung (zB mit Rechnungen und Transaktionen) stirbt, weil Kuchen zwei Abfragen tut: die ersten alle den passenden Rechnungen zu finden, und dann die zweiten, alle Transaktionen mit einem entsprechenden ausländischen zu finden Schlüssel, die die Ergebnisse aus der ersten Abfrage entspricht: (hier ist die vereinfachte Abfrage, um sie auszuführen versucht)

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`

Sie können sehen, dass es nicht auf Rechnungen verbinden so die Abfrage stirbt.

Irgendwelche Ideen, wie ich diese Arbeit machen kann?

War es hilfreich?

Lösung

Im schlimmsten Fall können Sie den finderQuery Parameter des hasMany Beziehung . Es ermöglicht Ihnen, vollständig die Abfragen außer Kraft setzen.

Sie können auch eine eindeutige ID-Feld hinzufügen können, die die entsprechenden Datenfelder in einem vereint. Eine Update-Anweisung vorhandene Daten beheben konnte und ein TRIGGER eingerichtet werden könnte neue Datensätze zu aktualisieren, da sie hinzugefügt oder geändert wird, unter der Annahme, dass Ihre Datenbank unterstützt Trigger.

Edit: Mit all den anderen Komplexitäten, könnten Sie die hasMany Beziehung zusammen und Abrufen der Transaktionsaufzeichnungen in einem separaten Fund besser dran, das Überspringen (). Wenn Sie es sehr viele Orte zu tun haben, können Sie immer wickeln Sie es in einer Funktion in dem Rechnungsmodell wie diese:

<?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;
    }
}
?>

Wenn Sie eine Funktion wie die im Modell verwenden, vergessen Sie nicht, dass die Rechnung würde eine definierte Beziehung zu der Transaktion benötigen, auch wenn Sie es nicht direkt verwenden, so dass $ this-> Transaktion definiert ist.

Auch wenn Sie die Daten lieber die Art und Weise eine hasMany Beziehung wäre zurückgegeben werden, man konnte immer eine foreach-Schleife hinzufügen, um sie auf diese Weise rekombinieren.

Aktualisieren Es gibt auch ein SimpleResults Verhalten im Kuchen Bäckerei , die es ermöglicht leicht, diese Ergebnisse aus der anderen Tabelle im Format eines regulären hasMany Verbandes zurück.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top