Domanda

Sto lavorando a un'applicazione che ha i dati importati da una fonte esterna (e completamente immutabile). Semplificherò alcune delle tabelle per spiegare il problema. Di seguito sono riportate le tabelle con le loro chiavi primarie.

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)

In questo modo puoi vedere che le fatture, le intestazioni e le consegne hanno relazioni uno a uno. Fatture-a-Transazioni e Fatture-a-Messaggi sono uno-a-molti.

Nell'importare queste tabelle nel mio database, ho modificato la chiave primaria esistente in una chiave univoca e ho aggiunto un campo di incremento automatico ( id ) su ogni tabella.

Ora il problema è impostare le relazioni in Cake, dal momento che in realtà non gestisce affatto le chiavi composite. Sono stato in grado di far funzionare le relazioni One-to-One in questo modo:

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

E questo funziona, perché le relazioni one-to-one vengono interrogate in una volta con un grande LEFT JOIN. Provando lo stesso metodo con una relazione uno-a-molti (ad esempio, con Fatture e Transazioni) muore, perché Cake fa due query: la prima per trovare tutte le Fatture corrispondenti, e poi la seconda per trovare tutte le Transazioni con un corrispondente estero chiave che corrisponde ai risultati della prima query: (ecco la query semplificata che sta tentando di eseguire)

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`

Puoi vedere che non si unisce alle fatture, quindi la query muore.

Qualche idea su come posso farlo funzionare?

È stato utile?

Soluzione

Scenario peggiore, puoi utilizzare il parametro finderQuery della hasMany relationship . Ti consente di sostituire completamente le query.

Potresti anche essere in grado di aggiungere un campo ID univoco che combina i campi dati rilevanti in uno. Un'istruzione UPDATE potrebbe correggere i dati esistenti e un TRIGGER potrebbe essere impostato per aggiornare nuovi record man mano che vengono aggiunti o modificati, supponendo che il database supporti i trigger.

Modifica: Con tutte le altre complessità, potresti essere meglio saltare la relazione hasMany del tutto e recuperare i record delle Transazioni in un find () separato. Se devi farlo in molti posti, puoi sempre inserirlo in una funzione nel modello di fattura come questa:

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

Se usi una funzione come quella nel modello, non dimenticare che Invoice avrebbe bisogno di una relazione definita con Transaction, anche se non la usi direttamente, in modo che $ this- > Transaction sia definita.

Inoltre, se preferisci che i dati vengano restituiti come una relazione hasMany, potresti sempre aggiungere un ciclo foreach per ricombinarli in quel modo.

Aggiorna C'è anche un SimpleResults in the Cake Bakery che consentirebbe di restituire facilmente quei risultati dall'altra tabella nel formato di una normale associazione hasMany.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top