Sinistra unisci una tabella su una query di raccolta


27

Sto facendo quanto segue per ottenere alcuni ordini dal sistema per l'esportazione:

$orders = Mage::getModel('sales/order')->getCollection()
    ->addFieldToFilter('status', $statusToExport)
    ->addFieldToFilter('store_id', $this->processingStoreId)
    ->addFieldToFilter('updated_at', array('gteq' => date('Y-m-d H:i:s', $lastSyncTime)));

Devo aggiungere qualcosa in cui non esporti se l'ordine entity_idè in una tabella personalizzata che ho. Se stessi usando SQL, farei:

left join myTable as mt on main_table.entity_id = mt.entity_id
where mt.entity_id is null

Ma non sono sicuro di come modificare la query di raccolta per fare una cosa simile.

Nota: ci ho provato

$orders = $orders->getSelect()
    ->joinLeft(
        array("t1" => $myTable),
        "main_table.entity_id = t1.entity_id",
        array("admin_field_id" => "t1.id")
    )
    ->where("t1.id is null")

ma questo lo cambia, quindi è una query e voglio che venga restituita la raccolta vendite / ordini.

Sento che mi manca qualcosa di semplice ...

MODIFICARE

Ok, ho provato questo:

$orders->getSelect()
    ->joinLeft(
        array("t1" => $myTable),
        "main_table.entity_id = t1.entity_id",
        array("admin_field_id" => "t1.id")
    )
    ->where("t1.id is null");

Quando echo (string)$orders->getSelect()restituisce la query che mi aspetto e non restituisce risultati quando la eseguo. $orderstuttavia, contiene ancora elementi. Ho pensato che questo join avrebbe dovuto modificare la raccolta a questo punto?

Risposte:


53

Per cambiare la query che puoi fare

$collection->getSelect()->doWhateverYouWantWithSelectObject();
foreach($collection as $order) {} // order collection

Ma per unirti a un tavolo, puoi semplicemente usare $collection->joinTable()

joinTableesiste solo su Mage_Eav_Model_Entity_Collection, questo significa: prodotti, categorie, ordini, fatture, creditmemo, spedizioni, clienti. (Grazie @Fra per il commento)

joinTable ()

Ma le raccolte di magento hanno un metodo joinTable()che mi ha impiegato 45 minuti per capire come viene utilizzato. Per evitarlo, lo condivido.

$productCollection->joinTable(
    array('bonus' => 'mycompany/bonus'), 'product_id=entity_id',
    array('bonus_id' => 'bonus_id')
);

I parametri sono:

public function joinTable($table, $bind, $fields = null, $cond = null, $joinType = 'inner')
  1. La tabella è semplice, è il namespace/entityformato magento , che si utilizza nella configurazione, nei modelli di risorse e nella raccolta. È possibile utilizzare una matrice del formatoarray('alias' => 'namespace/entity')
  2. Bind significa, l'istruzione ON nel tuo SQL. Questa è stata la parte più difficile e lo spiegherò in dettaglio più avanti. È importante avere il tavolo piatto PRIMA e il tavolo EAV DOPO il segno uguale. Non utilizzare main_table.prima dell'attributo. Magento lo farà per te. Più su questo più tardi.
  3. Fields è un array . Se si utilizza una stringa, invece, si ottiene questo: Warning: Invalid argument supplied for foreach() in /var/www/magento-1.6.2.0/app/code/core/Mage/Eav/Model/Entity/Collection/Abstract.php on line 775. È possibile utilizzare una matrice del formato array('field1', 'field2', '...')oarray('alias' => 'field1', '...')
  4. La condizione è un ** DOVE Condizione ON ** nell'SQL.
  5. joinType. Spero tu sappia di cosa si tratta. Ma hai solo la scelta tra SINISTRA e INTERNA .app/code/core/Mage/Eav/Model/Entity/Collection/Abstract.php:793

Maggiori informazioni su questo argomento


1
Grazie per l'ottima informazione. In base al tuo primo punto, non dovresti $orders->getSelect() ->joinLeft(array("t1" => $myTable), "main_table.entity_id = t1.entity_id", array("admin_field_id" => "t1.id")) ->where("t1.id is null")escludere gli articoli dal mio elenco attuale?
webnoob,

Penso che modifichi la raccolta dopo il caricamento. basta agganciare la tua sceneggiatura con xdebug e controllare la bandiera isLoaded all'interno del modello
Fabian Blechschmidt

2
vale la pena ricordare che il metodo joinTable è disponibile solo per Mage_Eav_Model_Entity_Collection
Fra

1

Ho trovato il motivo per questo.

Volevo un conteggio di valori prima di applicare il join sinistro, quindi ho aggiunto

$totalOrderCount = count($orders);

ciò tuttavia causò il caricamento della raccolta, il che a sua volta significava ignorare il join sinistro che stavo facendo più avanti. Durante il debug, guardare il var è _isCollectionLoadedstato un buon consiglio di Fabian.

Ora sto facendo questo invece per ottenere il conteggio della raccolta:

$countOrdersObjs = clone $orders;
$totalOrderCount = count($countOrdersObjs);
unset($countOrdersObjs);

Questo mi permette di contare i risultati senza caricare la $ordersraccolta.

Nota: si prega di applicare qualsiasi voto ai post di Fabians sopra mentre mi ha guidato su questo, ma ho sentito che la soluzione garantiva la propria risposta.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.