Esquerda juntar uma tabela em uma consulta de coleção

27

Estou fazendo o seguinte para obter alguns pedidos do sistema para exportação:

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

Preciso adicionar algo em que não exporte se o pedido entity_idestiver em uma tabela personalizada que possuo. Se eu estivesse usando SQL, faria:

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

Mas não tenho certeza de como modificar a consulta de coleção para fazer uma coisa semelhante.

Nota: eu tentei

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

mas isso muda, então é uma consulta e eu quero a coleção de pedidos / vendas devolvida.

Sinto que estou perdendo algo simples ...

EDITAR

Ok, eu tentei isso:

$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 eu ecoo, (string)$orders->getSelect()ele retorna a consulta que eu esperaria e não retorna resultados ao executá-lo. $ordersno entanto, ainda contém itens. Eu pensei que essa junção era para modificar a coleção neste momento?

webnoob
fonte

Respostas:

53

Para alterar a consulta, você pode fazer

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

Mas para ingressar em uma mesa, você pode simplesmente usar $collection->joinTable()

joinTablesó existe no Mage_Eav_Model_Entity_Collection, isso significa: produtos, categorias, pedidos, faturas, crédito, remessa, clientes. (Obrigado @Fra pelo comentário)

joinTable ()

Mas as coleções magento têm um método joinTable()que levou 45 minutos para fracassar em como é usado. Para evitar isso para você, eu compartilho.

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

Os parâmetros são:

public function joinTable($table, $bind, $fields = null, $cond = null, $joinType = 'inner')
  1. A tabela é fácil, é o namespace/entityformato magento , que você usa em sua configuração, modelos de recursos e coleção. Você pode usar uma matriz do formatoarray('alias' => 'namespace/entity')
  2. Vincular significa a instrução ON no seu SQL. Essa foi a parte mais difícil e explicarei em detalhes mais adiante. É importante ter sua mesa plana ANTES e sua mesa EAV APÓS o sinal de igual. Não use main_table.antes do atributo. Magento fará isso por você. Mais sobre isso mais tarde.
  3. Campos é uma matriz . Se você usar uma corda em vez disso, você recebe a seguinte: 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. Você pode usar uma matriz do formato array('field1', 'field2', '...')ouarray('alias' => 'field1', '...')
  4. Condição é um ** ONDE Condição ON ** no SQL.
  5. joinType. Espero que você saiba o que é isso. Mas você tem apenas a escolha entre ESQUERDA e INTERIOR .app/code/core/Mage/Eav/Model/Entity/Collection/Abstract.php:793

Mais sobre este tópico

Fabian Blechschmidt
fonte
11
Obrigado por essa ótima informação. Com base no seu primeiro ponto, não deve $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 os itens da minha lista atual?
Webnoob 4/11/13
Eu acho que você edita a coleção após o carregamento. apenas ligar para o seu script com xdebug e verificar a bandeira IsLoaded dentro do modelo
Fabian Blechschmidt
2
vale ressaltar que o método joinTable está disponível apenas para Mage_Eav_Model_Entity_Collection
Fra
1

Eu encontrei o motivo disso.

Eu queria uma contagem de valores antes de aplicar a junção esquerda, então adicionei

$totalOrderCount = count($orders);

no entanto, isso causou o carregamento da coleção, o que, por sua vez, significou que ignorava a junção esquerda que eu estava fazendo mais adiante. Durante a depuração, olhar para o var _isCollectionLoadedfoi uma boa dica de Fabian.

Agora, estou fazendo isso para obter a contagem da coleção:

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

Isso permite que eu conte os resultados sem carregar a $orderscoleção.

Nota: Por favor, aplique quaisquer upvotes aos Fabians postados acima, pois ele me guiou nisso, mas eu senti que a solução justificava sua própria resposta.

webnoob
fonte