[Zend Framework/Magento] Meerdere selects bij SQL query

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • DAMAGE
  • Registratie: December 2001
  • Laatst online: 31-05 16:23

DAMAGE

a.k.a. Rice_NL

Topicstarter
Ik begin het Zend Framework waar Magento op draait redelijk te snappen, alleen soms komt het nog wel eens voor dat ik iets wil doen waarvan ik het weet dat het kan, maar ik er maar gewoon niet uit kom. Het probleem is alsvolgd:

Ik heb een SQL query binnen Magento gedaan middels het Zend Framework. Deze werkt perfect, ik krijg de juiste collection terug, en mijn JOIN die ik gedaan heb met een andere tabel is ook prima gegaan. Nu wil ik echter de data uit de gejoinde tabel ook meegeven aan mijn select, en daar gaat het fout. Deze query geeft namelijk alleen de data uit de eerste tabel mee met de select, en niet die van de tweede tabel. Ik heb de hele middag gegoogled en geprobeerd, maar ik ben nog niet tot de juiste oplossing gekomen.

Ik heb geprobeerd doormiddel van een array meerdere selects mee te geven, maar dat werkte ook niet zoals ik verwacht had. Wat doe ik verkeerd?

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    public function getProductsByManufacturer($manufacturerId, $storeId)
    {
        $resource = Mage::getResourceModel('catalogindex/attribute');
        $select = $resource->getReadConnection()->select();

        $select->from(''.$resource->getMainTable().'', 'entity_id')
//Dit is de select waar het om draait. Hier select hij alles van de maintable, dit gaat goed. Maar hoe ik hier een extra select uit een andere tabel aan mee geef ik mij niet duidelijk.
        
            ->distinct(true)
            
            //Model toevoegen aan de product collectie.
            ->join(
                array('catalog_product_flat_'.$storeId.'' => 'catalog_product_flat_'.$storeId.''),
                ''.$resource->getMainTable().'.entity_id = catalog_product_flat_'.$storeId.'.entity_id'
                //array('store_id')
            )
            
            
            ->where('store_id = ?', $storeId)
            ->where('attribute_id = ?', Mage::helper('aitmanufacturers')->getAttributeId())
            ->where('value = ?', $manufacturerId);
            
            
        
        return $resource->getReadConnection()->fetchCol($select);


    }


Zoals te zien is word er een join gedaan met de tabel: catalog_product_flat_'.$storeId.' oftewel: catalog_product_flat_4. Dit gaat prima, ik had al gezien dat de join goed werkt. Nu moet hij de data dus ook nog selecten. In een MySQL query is dit makkelijk gepiept, echter in Zend Framework is het mij even te moeilijk momenteel...

Is hier wellicht iemand die mij een zetje in de goede richting wil geven?

[ Voor 7% gewijzigd door DAMAGE op 20-10-2011 21:34 ]

Lian Li O11 Dynamic EVO | Corsair HX1500i | Intel i9 13900K | ASUS Maximus HERO Z790 | 32GB GSkill Trident Z5 7200 DDR5 | Samsung 980 Pro 2TB | RTX 4080 | Simucube 2 Pro wheel


Acties:
  • 0 Henk 'm!

  • SoulWar1
  • Registratie: Augustus 2004
  • Laatst online: 14-06 18:59
Ik ben niet zo bekend met Zend_Db's query builder, maar als ik ff vluchtig door de documentatie kijk is het 3e argument van de join functie de kolommen die in de select komen. Een leeg array geeft alle kolommen. In jou geval is dat regel 15 (wat nu gecommentarieerd is).

Hm, geen derde argument zou wel moeten werken :X

code:
1
2
3
4
5
6
7
8
9
10
// Build this query:
//   SELECT p."product_id", p."product_name", l.*
//   FROM "products" AS p JOIN "line_items" AS l
//     ON p.product_id = l.product_id
 
$select = $db->select()
             ->from(array('p' => 'products'),
                    array('product_id', 'product_name'))
             ->join(array('l' => 'line_items'),
                    'p.product_id = l.product_id');


edit: Die fetchcol wat Cartman! zei zal het probleem wel zijn, die haalt natuurlijk maar 1 kolom op. Dat had ik over het hoofd gezien. :>

[ Voor 54% gewijzigd door SoulWar1 op 20-10-2011 22:06 ]

Know Thyself


Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Wat SoulWar1 zegt klopt, je 3e argument zijn de velden die je wilt ophalen, als je bij een join geen velden opgeeft krijg je niks terug.

Trouwens, haal je loze lege strings uit je from() :)

edit: als je gewoon de documentatie van Zend_Db erbij pakt dan had je t naar mijn idee wel aardig snel kunnen vinden, had je die wel bekeken?

edit 2: waarom gebruik je fetchCol()? Ik ben bekend met fetchAll() en fetchRow().

[ Voor 39% gewijzigd door Cartman! op 20-10-2011 21:47 ]


Acties:
  • 0 Henk 'm!

  • DAMAGE
  • Registratie: December 2001
  • Laatst online: 31-05 16:23

DAMAGE

a.k.a. Rice_NL

Topicstarter
Ik heb het hele internet afgestruind naar oplossingen, ik dacht dit moet vast vaker gevraagd zijn. Kwam ook wel verschillende "oplossingen" tegen maar die werkten voor mij niet. Uiteraard heb ik ook op de Zend site gekeken, maar kon niet de juiste pagina vinden, waarschijnlijk omdat ik gewoon verkeerd zocht.

code:
1
2
3
4
            //Model toevoegen aan de product collectie.
            ->join(array('attributes' => 'catalog_product_flat_'.$storeId.''),
                ''.$resource->getMainTable().'.entity_id = attributes.entity_id'
                ,array('attributes.model_value')


Ik heb de join aangepast naar bovenstaande, maar mag niet baten. Ik krijg wel resultaat zonder foutmeldingen, maar ik krijg model_value niet terug te zien in mijn result helaas...

Op het moment ben ik druk bezig deze manual door te spitten: http://framework.zend.com/manual/1.11/en/zend.db.select.html

Als ik FetchAll gebruik (had ik ook al gevonden idd) dan krijg ik hele andere resultaten. Dan lijkt het wel of hij mijn WHERE niet mee neemt of iets dergelijks. FetchRow geeft maar 4 resultaten, dus lijkt al helemaal niet te kloppen, en ook daar lijkt hij de WHERE niet mee te nemen. Gebruik ik FetchCol dan gaat het wel goed. Lastig dit...

[edit]

Als ik FetchAll gebruik moet ik zeker de Where aanpassen en dan doel ik op de namen van de columns? Stom :) Had ik kunnen weten... Ik ga het even proberen jongens.

[ Voor 21% gewijzigd door DAMAGE op 20-10-2011 22:18 ]

Lian Li O11 Dynamic EVO | Corsair HX1500i | Intel i9 13900K | ASUS Maximus HERO Z790 | 32GB GSkill Trident Z5 7200 DDR5 | Samsung 980 Pro 2TB | RTX 4080 | Simucube 2 Pro wheel


Acties:
  • 0 Henk 'm!

  • SoulWar1
  • Registratie: Augustus 2004
  • Laatst online: 14-06 18:59
Anders zoek eens op wat het verschil is tussen die 3 manieren van data ophalen, het is niet zo moeilijk.

Know Thyself


Acties:
  • 0 Henk 'm!

  • DAMAGE
  • Registratie: December 2001
  • Laatst online: 31-05 16:23

DAMAGE

a.k.a. Rice_NL

Topicstarter
Heb mijn code aangepast naar:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public function getProductsByManufacturer($manufacturerId, $storeId)
    {
        $resource = Mage::getResourceModel('catalogindex/attribute');
        $select = $resource->getReadConnection()->select();

        $select->from(array($resource->getMainTable() => ''.$resource->getMainTable().''), 'entity_id')
        ->columns('*', $resource->getMainTable(),'attributes.model_value', 'attributes')
        
        
            ->distinct(true)
            
            //Model toevoegen aan de product collectie.
            ->join(array('attributes' => 'catalog_product_flat_'.$storeId.''),
                ''.$resource->getMainTable().'.entity_id = attributes.entity_id'
                ,array('attributes.model_value')
                
            )
            
            
            ->where(''.$resource->getMainTable().'.store_id = ?', $storeId)
            ->where(''.$resource->getMainTable().'.attribute_id = ?', Mage::helper('aitmanufacturers')->getAttributeId())
            ->where(''.$resource->getMainTable().'.value = ?', $manufacturerId);
            
            
        
        return $resource->getReadConnection()->fetchCol($select);

    }


Mag allemaal niks baten. Ook de verschillende manier van data ophalen geprobeerd, geen verschil. Wel in resultaat, maar ik zie model_value niet bij mijn collection komen helaas. Ik ga eens lezen wat het verschil is tussen die drie.

Ik had inderdaad ook niet verwacht dat het zo moeilijk zou zijn, het Framework is er juist voor bedoeld om het simpel te maken }:O

[ Voor 4% gewijzigd door DAMAGE op 20-10-2011 22:28 ]

Lian Li O11 Dynamic EVO | Corsair HX1500i | Intel i9 13900K | ASUS Maximus HERO Z790 | 32GB GSkill Trident Z5 7200 DDR5 | Samsung 980 Pro 2TB | RTX 4080 | Simucube 2 Pro wheel


Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Doe het gewoon in stapjes ipv. meteen joins en een bak where's toe te voegen. Haal eerst die join eens eruit en kijk of je de gegevens terugkrijgt die je nodig hebt, als dat goed gaat dan voeg je eerst eens die join toe en dan langzaam die where's en kijk waar t mis gaat. De fetchCol heb ik bijv. nooit nodig gehad, ik gebruikte enkel fetchRow() en fetchAll() persoonlijk (inmiddels gebruik ik Doctrine 2, vandaar de verleden tijd).

Ik zie nog steeds allemaal dit soort dingen "->where(''.$resource->getMainTable()", waarom gooi je die '' . er nog eens tussen? Totaal overbodig en leesbaarder wordt t er niet van...

Acties:
  • 0 Henk 'm!

  • DAMAGE
  • Registratie: December 2001
  • Laatst online: 31-05 16:23

DAMAGE

a.k.a. Rice_NL

Topicstarter
Ik gebruik nu FetchAll, geeft het juiste resultaat met de WHERE's maar nog steeds ontbreekt model_value uit mijn collection. Dit is wel gek, aangezien inderdaad wat jullie terrecht opmerkten: het derde argument zijn de columnnames die je mee kan geven aan je JOIN. Als default staat deze op '*' dat zou dus betekenen dat hij sowieso model_value mee moet geven van mijn andere tabel? Maar ik zie het nergens terug.

Kan het niet zo zijn dat ik ergens anders moet aangeven welke columns ik in mijn collection heb? Of dat een andere functie bepaalde columns eruit laat? Kan bijna niet anders dan dat dit het geval is... De code moet nu gewoon goed staan in de functie namelijk. Heb het helemaal na gecheckt met wat Zend voorschrijft.

Dit is overigens de code waarmee ik de bovenstaande functie aanroep, wellicht dat ik hier iets mis?

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
                                    $collection = Mage::getResourceModel('catalog/product_collection');
                                    
                                    
                                    $attributes = Mage::getSingleton('catalog/config')
                                        ->getProductAttributes();
                                    
                                    $collection->addAttributeToSelect($attributes)
                                        ->addMinimalPrice()
                                        ->addFinalPrice()
                                        ->addTaxPercents()
                                        ->addStoreFilter()
                                        ;

                                    if (!isset($_REQUEST['model']))
                                    {
                                        $productIds = Mage::getModel('aitmanufacturers/aitmanufacturers')->getProductsByManufacturer($this->_manufacturer, Mage::app()->getStore()->getId());
                                    }
                                    else
                                    {
                                        $productIds = Mage::getModel('aitmanufacturers/aitmanufacturers')->getProductsByManufacturerAndModel($this->_manufacturer, $_REQUEST['model'], Mage::app()->getStore()->getId());
                                    }
                                    
                                    $collection->addIdFilter($productIds);
                                    Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($collection);
                                    Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($collection);
                                    
                                    $this->_productCollection = $collection;



[EDIT]

Yes, ik merk nu dat ik via deze laatste code kan aangeven welke columns er in de collection komen! Dit doe je zo:

code:
1
2
3
$collection->addAttributeToSelect('name')  
->addAttributeToSelect('image')
->addAttributeToSelect('url_key')


Echter gaat het hier om columns uit de eerste tabel, en dus niet uit de join. Als ik bijvoorbeeld dit zou doen:

code:
1
2
3
$collection->addAttributeToSelect('name')  
->addAttributeToSelect('image')
->addAttributeToSelect('model_value')


Dan pakt hij model_value niet van de gejoinde tabel. Even uitzoeken dus hoe dit zit.

[ Voor 69% gewijzigd door DAMAGE op 21-10-2011 16:01 ]

Lian Li O11 Dynamic EVO | Corsair HX1500i | Intel i9 13900K | ASUS Maximus HERO Z790 | 32GB GSkill Trident Z5 7200 DDR5 | Samsung 980 Pro 2TB | RTX 4080 | Simucube 2 Pro wheel


Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Ga nu eens naar de basis, echo wat Zend_Db voor queries maakt, gooi die in phpMyAdmin en kijk wat eruit komt. die columns() heb je volgens mij helemaal niet nodig, opgeven welke velden je wilt kan gewoon in je from() en in je join(). Klopt je join uberhaupt wel? (wil je geen left join of right join bijv.).

Acties:
  • 0 Henk 'm!

  • DAMAGE
  • Registratie: December 2001
  • Laatst online: 31-05 16:23

DAMAGE

a.k.a. Rice_NL

Topicstarter
Ik heb het inmiddels voor elkaar gekregen heren, dank voor het mee denken!

Wat bleek nou. De eerste reeks code die ik geplaatst had, haalt OOK data uit de database. Logisch. Maar ik kwam er achter dat ik de join in het tweede stuk code moest plaatsen. Waarom dit precies is weet ik nog niet en ben ik nog aan het uitzoeken, want het zou niet nodig moeten zijn om op twee plaatsen data op te halen uit de database, beetje teveel van het goede...

Waarschijnlijk is dit iets meer specifiek Magento en heeft het verder niet zoveel met het Zend Framework te maken? Zie hier de collection zoals ik hem nu gemaakt heb, en dus werkend is:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$collection = Mage::getResourceModel('catalog/product_collection');
                                    
    $attributes = Mage::getSingleton('catalog/config')
    ->getProductAttributes();
    $attributes[]='attributes.model_value';
    $collection->joinTable('catalog_product_flat_'.Mage::app()->getStore()->getId().'','entity_id=entity_id',array('model_value' => 'model_value'))
    
    ->addAttributeToSelect('name')  
    ->addAttributeToSelect('image')
    ->addAttributeToSelect('model')
                                
                                    
    ->addMinimalPrice()
    ->addFinalPrice()
    ->addTaxPercents()
    ->addStoreFilter()
    ->groupByAttribute('model_value');


Zoals je kunt zien Join ik daar een tabel, waarbij entity_id van tabel 1 gelijk moet zijn aan die van tabel 2. Daarachter zie je dus dat ik graag alleen model_value wil selecten uit de tweede tabel. Dit werkt, ik krijg hem nu keurig mee in mijn collection. Als laatst heb ik nog een GROUP BY laten doen op model_value, omdat ik graag alle modellen wil ophalen uit de database, maar dan wel graag van elk model maar 1x.

Ik ben happy :) hopelijk help ik iemand anders -met een soort gelijk probleem- met deze post.

[ Voor 17% gewijzigd door DAMAGE op 23-10-2011 20:06 ]

Lian Li O11 Dynamic EVO | Corsair HX1500i | Intel i9 13900K | ASUS Maximus HERO Z790 | 32GB GSkill Trident Z5 7200 DDR5 | Samsung 980 Pro 2TB | RTX 4080 | Simucube 2 Pro wheel

Pagina: 1