Izquierda unirse a una tabla en una consulta de colección

27

Estoy haciendo lo siguiente para obtener algunos pedidos del sistema para la exportación:

$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)));

Necesito agregar algo en donde no se exporta si el pedido entity_idestá en una tabla personalizada que tengo. Si estuviera usando SQL, haría:

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

Pero no estoy seguro de cómo modificar la consulta de recopilación para hacer algo similar.

Nota: lo intenté

$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")

pero esto lo cambia, por lo que es una consulta y quiero que se devuelva la colección de ventas / pedidos.

Siento que me falta algo simple ...

EDITAR

Ok, he intentado esto:

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

Cuando hago eco (string)$orders->getSelect(), devuelve la consulta que esperaría y no devuelve ningún resultado cuando la ejecuto. $ordersSin embargo, todavía contiene elementos. ¿Pensé que esta unión estaba destinada a modificar la colección en este momento?

webnoob
fuente

Respuestas:

53

Para cambiar la consulta puedes hacer

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

Pero para unirte a una mesa, solo puedes usar $collection->joinTable()

joinTablesolo existe en Mage_Eav_Model_Entity_Collection, esto significa: productos, categorías, pedidos, facturas, crédito conmemorativo, envío, clientes. (Gracias @Fra por el comentario)

joinTable ()

Pero las colecciones de magento tienen un método joinTable()que me tomó 45 minutos para descifrar cómo se usa. Para evitar esto por ti, lo comparto.

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

Los parámetros son:

public function joinTable($table, $bind, $fields = null, $cond = null, $joinType = 'inner')
  1. La tabla es fácil, es el namespace/entityformato magento , que utiliza en su configuración, modelos de recursos y la colección. Puedes usar una matriz del formatoarray('alias' => 'namespace/entity')
  2. Enlace significa, la declaración ON en su SQL. Esta fue la parte más difícil y lo explicaré en detalle más adelante. Es importante tener su mesa plana ANTES y su mesa EAV DESPUÉS del signo igual. No use main_table.antes del atributo. Magento hará esto por ti. Más sobre esto más tarde.
  3. Fields es una matriz . Si utiliza una cadena en lugar, se obtiene lo siguiente: 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. Puede usar una matriz del formato array('field1', 'field2', '...')oarray('alias' => 'field1', '...')
  4. La condición es una ** DÓNDE Condición ON ** en el SQL.
  5. joinType. Espero que sepas lo que es. Pero solo tienes la opción entre IZQUIERDA e INTERIOR .app/code/core/Mage/Eav/Model/Entity/Collection/Abstract.php:793

Más sobre este tema

Fabian Blechschmidt
fuente
1
Gracias por esa gran información. Según su primer punto, ¿no debería $orders->getSelect() ->joinLeft(array("t1" => $myTable), "main_table.entity_id = t1.entity_id", array("admin_field_id" => "t1.id")) ->where("t1.id is null")excluir los elementos de mi lista actual?
webnoob el
Creo que editas la colección después de cargarla. simplemente conéctese a su script con xdebug y verifique la bandera isLoaded dentro del modelo
Fabian Blechschmidt
2
Vale la pena mencionar que el método joinTable solo está disponible para Mage_Eav_Model_Entity_Collection
Fra
1

Encontré la razón de esto.

Quería un recuento de valores antes de aplicar la combinación izquierda, así que agregué

$totalOrderCount = count($orders);

Sin embargo, esto hizo que la colección se cargara, lo que a su vez significaba que ignoraba la unión izquierda que estaba haciendo más adelante. Mientras se depuraba, mirar a la var _isCollectionLoadedfue un buen consejo de Fabian.

Ahora estoy haciendo esto para obtener el recuento de la colección:

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

Esto me permite contar los resultados sin cargar la $orderscolección.

Nota: Aplique cualquier voto a favor a las publicaciones de Fabians arriba, ya que él me guió en esto, pero sentí que la solución justificaba su propia respuesta.

webnoob
fuente