welke fetch mode?
Welke van deze fetch modes gebruiken jullie eigenlijk het meest (en waarom)?
En de rest: BOUND vind ik alleen maar nutteloos. NUM is handig als je met for loops moet werken en BOTH is handig als je zowel met for loops moet werken als met het normaal opvragen van data. ASSOC, andere zorgen imo voor te grote arrays en daardoor traagheid. CLASS, INTO en OBJ zijn welliswaar heel vet, maar dat wil ik zelf kunnen doen.
1) Wat bedoel jij met "... maar dat wil ik zelf kunnen doen." ?
"NUM is handig als je met for loops moet werken"
2) In welk opzicht is het bij for-loops handiger dan ASSOC? (ASSOC werkt toch ook in for-loops?)
Waarom ik de vraag stel... ik ben bezig met m'n database class en ik wil een fetchRow/getRow method maken, maar ik vraag me af ik dus meerdere varianten daarvan zal maken, bijv. getAssocRow of getNumRow. Ik vermoed ook dat ik ASSOC het meest zal gebruiken en dus is het wellicht handiger om maar 1 method getRow te maken die dan de ASSOC methode gebruikt.
3) Wat vind jij? Wouter, dankjewel voor je reactie!
Je zal ASSOC mogelijk het vaakst gebruiken, maar waarom zou je het daarom beperken? Die verschillende fetch methodes zijn er niet voor niets, blijkbaar zijn de andere af en toe dus ook handig. Als je het nu gaat beperken en later toch nog nodig hebt dan kost het je meer werk om het aan te passen dan het nu te doen. Wat ik wel zou doen, is ASSOC de standaard maken (in plaats van BOTH zoals in PDO). Dus als er geen methode wordt opgegeven via bijvoorbeeld een property, dan gebruik je gewoon ASSOC, anders de opgegeven methode.
Gebruiken jullie trouwens get of fetch als je iets uit de database haalt? Dus getAssocRow of fetchAssocRow? Erwin, ik bedoel meer hoe ik dan de method zal noemen. De fetch wijze meegeven via een property vind ik best tricky (dan moet ik telkens kijken wat ook alweer de juiste naam was). Maar ik zou bijv. kunnen doen getAssocRow en getNumRow. Waar ik dan even over twijfel is... stel dat ik altijd de ASSOC methode gebruik dan zou ik het ook gewoon getRow kunnen noemen (is wat korter), maar wat jij zegt is ook wel een goed punt... want wat als je inderdaad een keer een andere fetch wijze wil gebruiken?
Daar heb je constantes voor zodat je het via de code completion altijd goed hebt.
Ik heb in mijn database class vier verschillende methodes die een query uitvoeren en de resultaten daarvan opslaan in een property wat dan later weer kan wordern uitgelezen. Data ophalen is dan met 'getResults()'.
"Ik heb in mijn database class vier verschillende methodes die een query uitvoeren en de resultaten daarvan opslaan in een property wat dan later weer kan wordern uitgelezen. Data ophalen is dan met 'getResults()'."
Hoe moet ik me dit voorstellen? Ik zou zelf zoiets doen:
- $sql = 'bla bla';
- execute($sql);
- $row = getRow();
In $row zitten dan de gegevens uit de database.
Maar jij zou dan zoiets doen? (Of begrijp ik je niet goed?)
- $sql = 'bla bla';
- execute($sql);
- fetchRow();
- $row = getResults(); Ah, oké. Via constants. Daar had ik nog niet aan gedacht. Je bedoelt dan zoiets?
- $sql = 'bla bla';
- execute($sql);
- fetchRow();
- $row = getResults();
De database class zal niet verantwoordelijk zijn voor de query die moet worden uitgevoerd en zal verder ook niets met de resultaten doen.
Als je het opbreekt krijg je dus
- query class -> stelt query op
- query class -> geeft query aan database class
- database class -> voert query uit
- database class -> haalt resultaten op en slaat het op in een property van de database class
- query class (of de class die de query class aanroept) -> haalt resultaten op uit de database class
De reden waarom ik vier verschillende methodes heb om de queries uit te voeren is omdat niet elke query op dezelfde manier resultaten oplevert:
- queries die geen resultaten opleveren (INSERT, UPDATE, DELETE)
- queries die 1 rij opleveren
- queries die meerdere rijen opleveren
- queries die meerdere rijen opleveren maar die met een LIMIT en SQL_CALC_FOUND_ROWS zijn uitgevoerd
In principe kan je 2 en 3 wel samen doen, ik heb ervoor gekozen ze te splitsen omdat je dan de eerste met een PDO::fetch kan doen en de tweede met een PDO::fetch_all. Zelfs al zou de query die 1 rij terug wil hebben er meer krijgt, er wordt er dan maar 1 opgehaald. Deze vier methodes zitten niet in dezelfde class natuurlijk:
Ah oké, mijn opzet is iets anders. Ik stop wel alles in 1 class omdat ik het als een service heb ingesteld. Ik roep dan die service aan een die maakt automatisch een database connectie (eenmalig). Aan die service geef ik m'n slq query door en uit die service haal ik ook het resultaat op. Ik stop het resultaat echter niet in een property. Schematisch moet het dan zoiets worden:
Een andere reden om het niet te doen zoals jij nu wil gaan doen is dat je moeilijk moet gaan voor de queries met een LIMIT. Als je namelijk het aantal berekende rijen wilt ophalen moet een je nog een query uitvoeren (SELECT FOUND_ROWS()). Die kan je pas doen nadat je de data van de oorspronkelijke query hebt gefetched, anders ben je die data kwijt. Met andere woorden, je krijgt deze stappen:
Terwijl als je alles in 1 keer doet krijg je dit:
En in data zit dan een array met als eerste element het aantal berekende rijen en daarna alle rijen. Omdat ik lui ben prefereer ik de tweede :-) Het enige dat je dan anders hebt is dat niet de database class, maar de aanroepende class de while loop moet gaan bouwen om alle rijen uit te lezen. Dat had ik ook ooit eens, tot ik me bedacht dat ik gewoon elke keer weer die while loop aan het bouwen was. Daar had ik geen zin meer in en dus heb ik dat verplaatst naar de database class. Als je dat doet kan je dus ook meteen alles uitlezen met PDO::fetch_all en heb je helemaal geen loop meer nodig. Uiteindelijk vind ik dat een veel betere optie, omdat ik toch nooit tijdens het uitlezen van de gegevens al iets met de data doe. Pas in de view wordt de data behandeld.
Uh... je kunt toch alle rijen in 1x ophalen met PDO fetchAll? Dan heb ik toch geen while loop nodig?
Even voor de duidelijkheid. Ik heb dus 1 database class en dit is een specifieke PDO MySQL class. Dus alles in die class is gebaseerd op PDO MySQL. Stel nu dat ik ooit een andere database wil gebruiken dan zou ik dus een nieuwe class daarvoor maken. In mijn service hoef ik dan alleen de class naam te wijzigen. (Via een interface stel ik overigens een aantal verplichte methods in.) "Het enige dat je dan anders hebt is dat niet de database class, maar de aanroepende class de while loop moet gaan bouwen om alle rijen uit te lezen."
Absoluut, alleen omdat je de methode 'getRow()' noemde ging ik ervanuit dat je rijen 1 voor 1 op wilde halen. Haal je alles op dan verwacht ik de naam 'getRows()'. Anders dan dat zijn we het denk ik wel helemaal met elkaar eens.
Klopte dit voorbeeldje trouwens? Was dit hoe jij het bedoelde?
Ah oke... getRow haalt inderdaad 1 rij op en getRows die haalt er meerdere op :)
Ik had weer niet gedacht aan de PDO parameters (waar je overigens PDO::FETCH_ASSOC voor moet hebben, niet FETCH_ASSOC), maar die kan je inderdaad direct gebruiken. Meestal definieer ik mijn eigen parameters als class constants (eventueel in een abstracte class alleen bedoeld voor constantes), maar in dit geval zijn die PDO constants afdoende uiteraard. Ja, bijvoorbeeld.
$row = $db->getRow(PDO::FETCH_ASSOC);
Dan gaat het mis. Het mooiste zou dus zijn om een algemene FETCH_ASSOC te hebben... en die dan misschien matchen met een class constant ofzo? Ja, dat klopt... alleen ik zit even te denken hoe je dat handig zou kunnen aanpakken. Sowieso vind ik het idee van constants een goede. Maar stel ik zou ooit van database veranderen en heb dan ergens in mijn code dit staan:
Deze kan je altijd gebruiken en als een database een hele speciale heeft dan kan je die toevoegen, zolang je altijd meer een default hebt gedefinieerd in de andere database classes is dat geen punt. Die gaan dan gewoon terug naar de default. Dan kan je dus zelf je constantes definieren:
Ik dacht zelf om bijv. in de PDO MySQL class zulke constants op te nemen:
cons ASSOC = PDO::FETCH_ASSOC;
En dan zou ik dus dit kunnen doen:
$row = $db->getRow('ASSOC');
Trouwens nog iets super irritants. Dat met die defines gaat niet werken. Dat leek me dus super handig omdat ik me dan niet kan "vertypen". Maar ik heb mijn defines dus in een config bestandje staan en ze worden dan met een foreach loop ge-defined. Met als gevolg dat mijn editor ze dus niet herkent. Grrrrr... Oké thanks... maar waar haal jij nu die getallen vandaan?
cons ASSOC = PDO::FETCH_ASSOC;
dan zit je alsnog gebonden aan de PDO constanten. Dan kan je net zo goed die direct gebruiken.
Ik gebruik getallen omdat het gebruik van constanten in feite niets anders is dan een makkelijke naam geven aan iets dat anders moeilijk te onthouden is (denk aan pi, ik ken pi, maar voorbij 3,14 ken ik het getal echt niet). De waardes die je er in dit geval aan geeft zijn puur jouw keuze. Voor de compiler maakt het niets uit, en voor jou ook niet omdat je nooit met de getallen gaat werken, maar met de namen.
Alleen je laatste stukje begrijp ik niet helemaal. Een define is iets anders dan een class constant. Je kan het natuurlijk ook met defines doen, maar ik prefereer class constants omdat je dan de groep eenvoudig bij elkaar kunt houden, de classname al als prefix fungeert en het sneller schijnt te zijn (zelf nooit getest). Als je dit doet:
Als ik dit in mijn specifieke PDO MySQL class zet:
cons ASSOC = PDO::FETCH_ASSOC;
En ik doe dan dit:
$row = $db->getRow('ASSOC');
Dan zal ASSOC gematched worden met de class constant ASSOC die dan weer de waarde van de define PDO::FETCH_ASSOC teruggeeft. Snap je wat ik bedoel?
Die defines leek mij handig omdat ik dan dit kan doen:
$row = $db->getRow(ASSOC); // assoc is hier dus een define
waarbij dan de bedoeling zou zijn dat ASSOC automatisch wordt aangevuld door de editor, zodat ik het niet per ongeluk verkeerd kan typen zeg maar. Puur voor het gemak. Hoe leg ik dit uit...
$row = $db->getRow(PDO::FETCH_ASSOC);
Je editor zal die constantes ook kennen, neem ik aan.
De reden om je eigen constantes te maken is dat als je eens een andere database interface gaat gebruiken (dus niet PDO) je dan nog steeds je eigen constantes kunt gebruiken, maar niet de PDO constantes. Als je nu je eigen constantes 1-op-1 doorzet naar de PDO constantes dan heb je dat probleem namelijk nog wel. Dat begrijp ik, maar waarom doe je dan niet meteen:
En de rest: BOUND vind ik alleen maar nutteloos. NUM is handig als je met for loops moet werken en BOTH is handig als je zowel met for loops moet werken als met het normaal opvragen van data.
1) Wat bedoel jij met "... maar dat wil ik zelf kunnen doen." ?
"NUM is handig als je met for loops moet werken"
2) In welk opzicht is het bij for-loops handiger dan ASSOC? (ASSOC werkt toch ook in for-loops?)
Waarom ik de vraag stel... ik ben bezig met m'n database class en ik wil een fetchRow/getRow method maken, maar ik vraag me af ik dus meerdere varianten daarvan zal maken, bijv. getAssocRow of getNumRow. Ik vermoed ook dat ik ASSOC het meest zal gebruiken en dus is het wellicht handiger om maar 1 method getRow te maken die dan de ASSOC methode gebruikt.
3) Wat vind jij?
FETCH_ASSOC, is ook de meest gebruikte volgens mij?
Ozzie PHP op 23/05/2013 14:02:43:
Waarom ik de vraag stel... ik ben bezig met m'n database class en ik wil een fetchRow/getRow method maken, maar ik vraag me af ik dus meerdere varianten daarvan zal maken, bijv. getAssocRow of getNumRow. Ik vermoed ook dat ik ASSOC het meest zal gebruiken en dus is het wellicht handiger om maar 1 method getRow te maken die dan de ASSOC methode gebruikt.
Je zal ASSOC mogelijk het vaakst gebruiken, maar waarom zou je het daarom beperken? Die verschillende fetch methodes zijn er niet voor niets, blijkbaar zijn de andere af en toe dus ook handig. Als je het nu gaat beperken en later toch nog nodig hebt dan kost het je meer werk om het aan te passen dan het nu te doen. Wat ik wel zou doen, is ASSOC de standaard maken (in plaats van BOTH zoals in PDO). Dus als er geen methode wordt opgegeven via bijvoorbeeld een property, dan gebruik je gewoon ASSOC, anders de opgegeven methode.
Gebruiken jullie trouwens get of fetch als je iets uit de database haalt? Dus getAssocRow of fetchAssocRow?
Ozzie PHP op 23/05/2013 14:28:26:
De fetch wijze meegeven via een property vind ik best tricky (dan moet ik telkens kijken wat ook alweer de juiste naam was).
Daar heb je constantes voor zodat je het via de code completion altijd goed hebt.
Ik heb in mijn database class vier verschillende methodes die een query uitvoeren en de resultaten daarvan opslaan in een property wat dan later weer kan wordern uitgelezen. Data ophalen is dan met 'getResults()'.
"Ik heb in mijn database class vier verschillende methodes die een query uitvoeren en de resultaten daarvan opslaan in een property wat dan later weer kan wordern uitgelezen. Data ophalen is dan met 'getResults()'."
Hoe moet ik me dit voorstellen? Ik zou zelf zoiets doen:
- $sql = 'bla bla';
- execute($sql);
- $row = getRow();
In $row zitten dan de gegevens uit de database.
Maar jij zou dan zoiets doen? (Of begrijp ik je niet goed?)
- $sql = 'bla bla';
- execute($sql);
- fetchRow();
- $row = getResults();
- $sql = 'bla bla';
- execute($sql);
- fetchRow();
- $row = getResults();
De database class zal niet verantwoordelijk zijn voor de query die moet worden uitgevoerd en zal verder ook niets met de resultaten doen.
Als je het opbreekt krijg je dus
- query class -> stelt query op
- query class -> geeft query aan database class
- database class -> voert query uit
- database class -> haalt resultaten op en slaat het op in een property van de database class
- query class (of de class die de query class aanroept) -> haalt resultaten op uit de database class
De reden waarom ik vier verschillende methodes heb om de queries uit te voeren is omdat niet elke query op dezelfde manier resultaten oplevert:
- queries die geen resultaten opleveren (INSERT, UPDATE, DELETE)
- queries die 1 rij opleveren
- queries die meerdere rijen opleveren
- queries die meerdere rijen opleveren maar die met een LIMIT en SQL_CALC_FOUND_ROWS zijn uitgevoerd
In principe kan je 2 en 3 wel samen doen, ik heb ervoor gekozen ze te splitsen omdat je dan de eerste met een PDO::fetch kan doen en de tweede met een PDO::fetch_all. Zelfs al zou de query die 1 rij terug wil hebben er meer krijgt, er wordt er dan maar 1 opgehaald.
Gewijzigd op 23/05/2013 15:14:26 door Erwin H
Een andere reden om het niet te doen zoals jij nu wil gaan doen is dat je moeilijk moet gaan voor de queries met een LIMIT. Als je namelijk het aantal berekende rijen wilt ophalen moet een je nog een query uitvoeren (SELECT FOUND_ROWS()). Die kan je pas doen nadat je de data van de oorspronkelijke query hebt gefetched, anders ben je die data kwijt. Met andere woorden, je krijgt deze stappen:
Code (php)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
<?php
$db = $services->get('db');
$db->setSql('SELECT...);
while ( $db->hasNext() ){
$row = $db->getRow();
//doe iets met $row
}
$num = $db->getCalcRowNum();
?>
$db = $services->get('db');
$db->setSql('SELECT...);
while ( $db->hasNext() ){
$row = $db->getRow();
//doe iets met $row
}
$num = $db->getCalcRowNum();
?>
Terwijl als je alles in 1 keer doet krijg je dit:
Code (php)
1
2
3
4
5
2
3
4
5
<?php
$db = $services->get('db');
$db->setSql('SELECT...);
$data = $db->DBcall_fetch_limit();
?>
$db = $services->get('db');
$db->setSql('SELECT...);
$data = $db->DBcall_fetch_limit();
?>
En in data zit dan een array met als eerste element het aantal berekende rijen en daarna alle rijen. Omdat ik lui ben prefereer ik de tweede :-)
Uh... je kunt toch alle rijen in 1x ophalen met PDO fetchAll? Dan heb ik toch geen while loop nodig?
Even voor de duidelijkheid. Ik heb dus 1 database class en dit is een specifieke PDO MySQL class. Dus alles in die class is gebaseerd op PDO MySQL. Stel nu dat ik ooit een andere database wil gebruiken dan zou ik dus een nieuwe class daarvoor maken. In mijn service hoef ik dan alleen de class naam te wijzigen. (Via een interface stel ik overigens een aantal verplichte methods in.)
Ozzie PHP op 23/05/2013 15:41:58:
Uh... je kunt toch alle rijen in 1x ophalen met PDO fetchAll? Dan heb ik toch geen while loop nodig?
Absoluut, alleen omdat je de methode 'getRow()' noemde ging ik ervanuit dat je rijen 1 voor 1 op wilde halen. Haal je alles op dan verwacht ik de naam 'getRows()'. Anders dan dat zijn we het denk ik wel helemaal met elkaar eens.
Klopte dit voorbeeldje trouwens? Was dit hoe jij het bedoelde?
Ik had weer niet gedacht aan de PDO parameters (waar je overigens PDO::FETCH_ASSOC voor moet hebben, niet FETCH_ASSOC), maar die kan je inderdaad direct gebruiken. Meestal definieer ik mijn eigen parameters als class constants (eventueel in een abstracte class alleen bedoeld voor constantes), maar in dit geval zijn die PDO constants afdoende uiteraard.
$row = $db->getRow(PDO::FETCH_ASSOC);
Dan gaat het mis. Het mooiste zou dus zijn om een algemene FETCH_ASSOC te hebben... en die dan misschien matchen met een class constant ofzo?
Code (php)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
<?php
abstract class Ozzie_Fetch(
const ASSOC = 0;
const NUM = 1;
const BOTH = 2;
const INVERTED = 3;
const DOWNUNDER = 4;
);
?>
abstract class Ozzie_Fetch(
const ASSOC = 0;
const NUM = 1;
const BOTH = 2;
const INVERTED = 3;
const DOWNUNDER = 4;
);
?>
Deze kan je altijd gebruiken en als een database een hele speciale heeft dan kan je die toevoegen, zolang je altijd meer een default hebt gedefinieerd in de andere database classes is dat geen punt. Die gaan dan gewoon terug naar de default.
Ik dacht zelf om bijv. in de PDO MySQL class zulke constants op te nemen:
cons ASSOC = PDO::FETCH_ASSOC;
En dan zou ik dus dit kunnen doen:
$row = $db->getRow('ASSOC');
Trouwens nog iets super irritants. Dat met die defines gaat niet werken. Dat leek me dus super handig omdat ik me dan niet kan "vertypen". Maar ik heb mijn defines dus in een config bestandje staan en ze worden dan met een foreach loop ge-defined. Met als gevolg dat mijn editor ze dus niet herkent. Grrrrr...
cons ASSOC = PDO::FETCH_ASSOC;
dan zit je alsnog gebonden aan de PDO constanten. Dan kan je net zo goed die direct gebruiken.
Ik gebruik getallen omdat het gebruik van constanten in feite niets anders is dan een makkelijke naam geven aan iets dat anders moeilijk te onthouden is (denk aan pi, ik ken pi, maar voorbij 3,14 ken ik het getal echt niet). De waardes die je er in dit geval aan geeft zijn puur jouw keuze. Voor de compiler maakt het niets uit, en voor jou ook niet omdat je nooit met de getallen gaat werken, maar met de namen.
Alleen je laatste stukje begrijp ik niet helemaal. Een define is iets anders dan een class constant. Je kan het natuurlijk ook met defines doen, maar ik prefereer class constants omdat je dan de groep eenvoudig bij elkaar kunt houden, de classname al als prefix fungeert en het sneller schijnt te zijn (zelf nooit getest).
Als ik dit in mijn specifieke PDO MySQL class zet:
cons ASSOC = PDO::FETCH_ASSOC;
En ik doe dan dit:
$row = $db->getRow('ASSOC');
Dan zal ASSOC gematched worden met de class constant ASSOC die dan weer de waarde van de define PDO::FETCH_ASSOC teruggeeft. Snap je wat ik bedoel?
Die defines leek mij handig omdat ik dan dit kan doen:
$row = $db->getRow(ASSOC); // assoc is hier dus een define
waarbij dan de bedoeling zou zijn dat ASSOC automatisch wordt aangevuld door de editor, zodat ik het niet per ongeluk verkeerd kan typen zeg maar. Puur voor het gemak.
$row = $db->getRow(PDO::FETCH_ASSOC);
Je editor zal die constantes ook kennen, neem ik aan.
De reden om je eigen constantes te maken is dat als je eens een andere database interface gaat gebruiken (dus niet PDO) je dan nog steeds je eigen constantes kunt gebruiken, maar niet de PDO constantes. Als je nu je eigen constantes 1-op-1 doorzet naar de PDO constantes dan heb je dat probleem namelijk nog wel.