PHP, PDO fetch_into, array probleem

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Sjoerd
  • Registratie: December 2003
  • Niet online
Ik heb het volgende probleem, ik heb een klasse pages met daarin een functie getAllRows():

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
    // Only display the pages that our user is authorized to see
        $sSQL = 'SELECT * FROM pages';
        // execute query, execute the result in a object
        $rows=registry::get('db')->query($sSQL);
        $rows->setFetchMode(PDO::FETCH_INTO, $this);
        //make an aResult array
        $aResult = array();
        foreach($rows as $row){
            $aResult [] =  $row;
        }
        return $aResult;
    }


het probleem wanneer ik werk met $aResult is dat ik elke keer hetzelfde object krijg.
Iets duidelijker:

In mijn database:
pages: id, title, content
rij 1: 1, home, dit is home
rij 2: 2, over ons, dit is de over ons pagina
rij 3: 3, contact, neem contact met ons op

Het geen wat ik echter krijg wanneer ik aResult print is:
3, contact, neem contact met ons op
3, contact, neem contact met ons op
3, contact, neem contact met ons op

Iemand een idee waar ik de mist in ga?
als ik in mijn foreach het volgende doe:

PHP:
1
2
3
4
foreach($rows as $row){
     echo $row->title;
     $aResult [] =  $row;
}


Zie ik wel 3x een andere titel dus: home, over ons, contact 8)7

Modelbouw - Alles over modelbouw, van RC tot diorama


Acties:
  • 0 Henk 'm!

  • Luqq
  • Registratie: Juni 2005
  • Laatst online: 19-09 14:23
En als je het aantal rows count, en een forloop gebruikt? van 0 tot count, dus?

Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
3 tips:
  1. Dit is een gekke functie, die waarschijnlijk inefficiënt is, zeker bij veel rijen. Ook is niet duidelijk om wat voor rijen het gaat ('getAllRows')
  2. Je haalt referenties en waardes door elkaar; je slaat nu steeds dezelfde referentie op, waardoor je dus dezelfde rijen krijgt. (PDO::FETCH_INTO "updates an existing instance")
  3. Kijk eens naar fetchAll. :)

[ Voor 15% gewijzigd door pedorus op 23-11-2008 22:26 ]

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • Sjoerd
  • Registratie: December 2003
  • Niet online
Het lijkt inderdaad een onlogische functie naam op het eerste gezicht, maar ik heb ongeveer 11 models waarin deze functie zit, dan wordt het vrij logisch als ik in mijn controller $model->getAllRows(); doe.

FetchAll geeft een array terug met alle waardes, maar ik zou graag alle rijen als object hebben vandaar de FETCH_INTO. Als ik met fetch_all werk moet ik nogmaals door de resultaten array lopen en voor elke array rij een object ervan maken.

Ik kom er dus niet goed uit, het is in ieder geval zeker dat de fout inderdaad in de referenties zal zitten. :)
Ik heb dus geen idee hoe ik dit moet laten werken zonder door resultaten arrays te gaan wandelen en deze om te vormen naar objecten.

Modelbouw - Alles over modelbouw, van RC tot diorama


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Tjsa, waar zal FETCH_CLASS nou voor zijn? :) Maar lees ook even de warning:
Using this method to fetch large result sets will result in a heavy demand on system and possibly network resources. Rather than retrieving all of the data and manipulating it in PHP, consider using the database server to manipulate the result sets. For example, use the WHERE and SORT BY clauses in SQL to restrict results before retrieving and processing them with PHP.

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • Sjoerd
  • Registratie: December 2003
  • Niet online
pedorus schreef op zondag 23 november 2008 @ 22:35:
Tjsa, waar zal FETCH_CLASS nou voor zijn? :) Maar lees ook even de warning:

[...]
Ben er mee aan de slag gegaan maar weer zonder succes helaas.

PHP:
1
2
3
4
5
6
7
8
9
10
11
// execute query, execute the result in a object
    $rows=registry::get('db')->query($sSQL); 
    $rows->setFetchMode(PDO::FETCH_CLASS, 'pages'); 
        //make an aResult array 
        $aResult = array(); 
        foreach($rows as $row){
            print_r($row);
            echo "<br>";
            $aResult [] =  $row; 
        } 
        return $aResult;


Het resultaat is echter:
pages Object ( [m_sFieldIdName:protected] => id [m_sTableName:protected] => pages [m_aFields:protected] => Array ( [0] => id [1] => title [2] => content [3]) [id] => [title] => [content] =>)
pages Object ( [m_sFieldIdName:protected] => id [m_sTableName:protected] => pages [m_aFields:protected] => Array ( [0] => id [1] => title [2] => content [3]) [id] => [title] => [content] =>)
pages Object ( [m_sFieldIdName:protected] => id [m_sTableName:protected] => pages [m_aFields:protected] => Array ( [0] => id [1] => title [2] => content [3]) [id] => [title] => [content] =>)

De data wordt dus niet meegepakt, maar misschien begrijp ik dan toch de functie verkeerd als nog? :? bedankt voor alle moeite overigens!

Modelbouw - Alles over modelbouw, van RC tot diorama


Acties:
  • 0 Henk 'm!

  • frickY
  • Registratie: Juli 2001
  • Laatst online: 18-09 14:42
$rows is een object
PHP:
1
$rows=registry::get('db')->query($sSQL);

Daar kun je niet zomaar doorheen loopen.
Kijk eens naar SPL Iterator

[ Voor 31% gewijzigd door frickY op 24-11-2008 12:51 ]


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 21-09 02:21

Janoz

Moderator Devschuur®

!litemod

Welke code gebruik je voor het afdrukken van $aResult?

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Sjoerd
  • Registratie: December 2003
  • Niet online
Voor het afdrukken van $aResult gebruik ik de volgende test functie:

PHP:
1
2
3
4
5
public function test(){
        $pages = new pages();
        $pages = $pages->getAllRows();
        print_r($pages);
    }

Die print_r is natuurlijk tijdelijk maar ik zou eerst graag objecten met data inhoud hebben.

Ik zal me is inlezen in de Iterator (dit is nieuw voor mij) eigenlijk nog nooit nodig gehad.

[ Voor 13% gewijzigd door Sjoerd op 24-11-2008 13:35 ]

Modelbouw - Alles over modelbouw, van RC tot diorama


Acties:
  • 0 Henk 'm!

  • Sjoerd
  • Registratie: December 2003
  • Niet online
Ben aan het spelen geweest met iterators (ArrayObject) maar kom er nog altijd niet uit.
wanneer ik een nieuw ArrayObject aanmaak en ik loop hier over heen met het volgende

PHP:
1
2
3
4
5
6
7
8
9
for($iterator = $row->getIterator();
/*** check if valid ***/
$iterator->valid();
/*** move to the next array member ***/
$iterator->next())
{
/*** output the key and current array value ***/
echo $iterator->key() . ' -> ' . $iterator->current() . '<br />';
}


Krijg ik volgende output:
*m_sFieldIdName -> id
id ->
title ->
content ->
*m_sFieldIdName -> id
id ->
title ->
content ->
*m_sFieldIdName -> id
id ->
title ->
content ->

De bovenstaande is overigens afgeleid uit een tutorial (http://www.phpro.org/tutorials/Introduction-to-SPL.html)

Modelbouw - Alles over modelbouw, van RC tot diorama


Acties:
  • 0 Henk 'm!

  • pedorus
  • Registratie: Januari 2008
  • Niet online
Sjoerd schreef op zondag 23 november 2008 @ 23:03:
Ben er mee aan de slag gegaan maar weer zonder succes helaas.

PHP:
1
2
3
// execute query, execute the result in a object
    $rows=registry::get('db')->query($sSQL); 
    $rows->setFetchMode(PDO::FETCH_CLASS, 'pages');
Waarom staat hier pages en geen Page? Hoe ziet die class eruit?
PHP:
4
5
6
7
8
9
10
11
        //make an aResult array 
        $aResult = array(); 
        foreach($rows as $row){
            print_r($row);
            echo "<br>";
            $aResult [] =  $row; 
        } 
        return $aResult;
Waarom niet gewoon fetchAll gebruikt?

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


Acties:
  • 0 Henk 'm!

  • Sjoerd
  • Registratie: December 2003
  • Niet online
Waarom dat er pages stond ipv page is omdat mijn echte classe waar het uiteindelijk in moet werken pages heet. Ondertussen is het eigenlijk zo goed als gelukt.

Uiteindelijke complete code van de functie getAllRows in de klasse pages
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public function getAllRows() {
    // Only display the pages that our user is authorized to see
    $sSQL = 'SELECT * FROM pages p 
            JOIN page_permissions pp
            ON p.id = pp.pageID
            WHERE pp.groupID = "'.registry::get('auth') -> currentUser() -> groupID.'"
            ORDER BY p.templateID, p.title';
    $oResult = registry::get('db')->query($sSQL);
    $aResult = array();
    while($oRow = $oResult->fetchAll(PDO::FETCH_CLASS)) {
        $aResult[] = $oRow;
    } 
       return $aResult; 
}


En de code hoe de functie er vroeger uit zag:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public function getAllRows() {
    // Only display the pages that our user is authorized to see
    $sSQL = 'SELECT p.id FROM pages p 
            JOIN page_permissions pp
            ON p.id = pp.pageID
            WHERE pp.groupID = "'.registry::get('auth') -> currentUser() -> groupID.'"
            ORDER BY p.templateID, p.title';
    $aRows=registry::get('db')->query($sSQL);
    if($aRows){
        $aResult = array();
        foreach ($aRows as $row) {
            $page = new pages();
            $page -> id = $row['id'];
            if ($page->getData()) {
                $aResult[] = $page;
            }
        }
        return $aResult;
    } else {
        return false;
    }   
}


waarbij getData de rest van de ontbrekende data ophaalde doormiddel van een dynamisch gegenereerde query die er dan zo zou uit zien "select * from pages where id = x";


Het verschil tussen de 2 functies?
de "nieuwe" functie: 0.908629894256 seconden
de "oude" functie: 2.0846970081329 seconden

Dit is wanneer de getAllRows 1000X werd aangeroepen in een for loopje...

Het enige "probleem" wat ik nu nog heb is het volgende:
PHP:
1
2
3
$pages = new pages();
$pages = $pages -> getAllRows();
$pages = $pages[0];

Als ik de laatste regel niet doe moet ik mijn objecten benaderen via
$pages[0][x] geen idee waar die index 0 vandaan komt eigenlijk?

Modelbouw - Alles over modelbouw, van RC tot diorama


Acties:
  • 0 Henk 'm!

  • Cartman!
  • Registratie: April 2000
  • Niet online
Je kunt ook bijv. dit gebruiken dan:

PHP:
1
2
$pages = new pages();
$pages = $pages -> getAllRows()->current();


Dat gaat alleen op zn bek volgens mij als je getAllRows false of null returned dus ik weet niet hoe je daarmee zit.

Verder is het misschien een idee om eens te kijken naar Zend_Db, een onderdeel van Zend Framework :)

edit:
om antwoord te geven op je vraag: met fetchAll haal je een rowset op, geen enkele row :)

[ Voor 32% gewijzigd door Cartman! op 24-11-2008 16:12 ]


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 21-09 02:21

Janoz

Moderator Devschuur®

!litemod

Ik moet zeggen dat ik het variabele hergebruik hierboven en de testcode van Sjoerd behoorlijk smerig vind. Eerst is pages een object, en een regel later is het ineens een simpele array met resultaten. Ik weet dat het in php allemaal kan, maar het is natuurlijk een ideaal startpunt voor onduidelijke en ononderhoudbare code...

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Sjoerd
  • Registratie: December 2003
  • Niet online
Cartman! schreef op maandag 24 november 2008 @ 16:09:
Je kunt ook bijv. dit gebruiken dan:

PHP:
1
2
$pages = new pages();
$pages = $pages -> getAllRows()->current();


Dat gaat alleen op zn bek volgens mij als je getAllRows false of null returned dus ik weet niet hoe je daarmee zit.

Verder is het misschien een idee om eens te kijken naar Zend_Db, een onderdeel van Zend Framework :)

edit:
om antwoord te geven op je vraag: met fetchAll haal je een rowset op, geen enkele row :)
Hm ik moet alles nog is op mijn gemak gaan bekijken heb ik al wel gemerkt ;)
Ik weet van het bestaan van het Zend Framework maar wil toch even zelf sukkelen :+

Overigens lukt die -> current() aangezien het geen object meer is die $aResult die ik return... (Fatal error: Call to a member function current() on a non-object in)

edit:
@janoz, dus meer consenquentie doorvoeren zoals $oPages en $aPages? of gewoon totaal andere namen gebruiken? (heb zelf altijd moeite een goede variabele naam te verzinnen), wel leerzaam dit :)

[ Voor 9% gewijzigd door Sjoerd op 24-11-2008 16:23 ]

Modelbouw - Alles over modelbouw, van RC tot diorama

Pagina: 1