Als ik een loop heb van een fetchObject als deze:
while($row = $objStmt->fetchObject())
{
echo($row->naam);
}


Kan ik dan in deze while loop ook bijv. de naam van de volgende record krijgen?
Dus dat hij dit weergeeft:

Naam: Jan
Volgende resultaat is: Kees

Zodat ik voordat hij naar het volgende resultaat gaat kan kijken wat daar in zit?
Willem vp op 18/12/2014 10:07:05

Het eenvoudigst lijkt me om een fetchAll() te doen. Je hebt dan je complete resultset in een array en dan is het een eitje om te kijken wat er in het volgende record zit.

Het nadeel is dat het wel meer geheugen kost, dus het hangt een beetje af van het aantal records en de recordgrootte of het handig is om dit te doen. Uiteraard kun je dat altijd zelf inperken door een LIMIT op te nemen in je query.

Songhistory staat georderd per dag.
Zeg maar 450/500 records per pagina.
Zelf zou ik niet moeilijk doen over 500 records. Laten we even aannemen dat een record ongeveer 1 kB is (daar kun je al heel veel in kwijt) dan zou je dus een array van zo'n 500 kB hebben. Dat is niet iets waar PHP veel moeite mee zal hebben, tenzij je server heel erg krap in zijn geheugen zit. Maar als dat zo is, denk ik dat je een heel ander probleem hebt. ;-)
Willem vp op 18/12/2014 12:59:27

Zelf zou ik niet moeilijk doen over 500 records. Laten we even aannemen dat een record ongeveer 1 kB is (daar kun je al heel veel in kwijt) dan zou je dus een array van zo'n 500 kB hebben. Dat is niet iets waar PHP veel moeite mee zal hebben, tenzij je server heel erg krap in zijn geheugen zit. Maar als dat zo is, denk ik dat je een heel ander probleem hebt. ;-)

Ja, en het gaat bij mij om een paar bytes per regel dus is er al helemaal niks aan de hand.
Hoe dan ook, het werkt met onderstaande code.
Dank voor u meedenken.


<?php
if($objStmt->execute())
{
    $arrSonghistory = $objStmt->fetchAll(PDO::FETCH_OBJ);
    $intCounter = 0;
    
    foreach($arrSonghistory as $song)
    {
        if(isset($arrSonghistory[$intCounter-1]))
            echo('Vorige song was: '.$arrSonghistory[$intCounter-1]->song.'<br>');
        
        echo ('Huidige song is: ' . $song->song . '<br>');
        
        if(isset($arrSonghistory[$intCounter+1]))
            echo('Volgende song is: '.$arrSonghistory[$intCounter+1]->song.'<br>');
        
        echo ('<br>');
        
        $intCounter++;
    }
}
?>
Nog een klein optimalisatiedingetje:

In de foreach-loop test je met isset() of een bepaald array-element bestaat. Het "probleem" is, dat een array dereference in PHP relatief duur is, door de manier waarop arrays zijn geïmplementeerd in PHP. Dit merk je vooral bij grote arrays.

Als je je loop iets sneller wilt maken (bij een array van deze omvang spreek je overigens denk ik over niet meer dan een tiende seconde, wellicht zelfs minder) dan zou je de issets nog kunnen vervangen door een check op $intCounter. De fetchAll geeft een sequentieel genummerde array terug die bij index 0 begint, dus je kan veilig aannemen dat als $intCounter > 0 is, er een vorig element is. En zolang $intCounter kleiner is dan het aantal array-elementen min 1, is er ook een volgend element. In code ziet dat er dan als volgt uit:

<?php
if($objStmt->execute())
{
$arrSonghistory = $objStmt->fetchAll(PDO::FETCH_OBJ);
$intCounter = 0;
$intRecordcount = count($arrSonghistory);

foreach($arrSonghistory as $song)
{
if($intCounter > 0)
echo('Vorige song was: '.$arrSonghistory[$intCounter-1]->song.'<br>');

echo ('Huidige song is: ' . $song->song . '<br>');

if($intCounter < $intRecordcount - 1)
echo('Volgende song is: '.$arrSonghistory[$intCounter+1]->song.'<br>');

echo ('<br>');

$intCounter++;
}
}
?>
Willem vp op 18/12/2014 15:24:32

Nog een klein optimalisatiedingetje:

In de foreach-loop test je met isset() of een bepaald array-element bestaat. Het "probleem" is, dat een array dereference in PHP relatief duur is, door de manier waarop arrays zijn geïmplementeerd in PHP. Dit merk je vooral bij grote arrays.

Als je je loop iets sneller wilt maken (bij een array van deze omvang spreek je overigens denk ik over niet meer dan een tiende seconde, wellicht zelfs minder) dan zou je de issets nog kunnen vervangen door een check op $intCounter. De fetchAll geeft een sequentieel genummerde array terug die bij index 0 begint, dus je kan veilig aannemen dat als $intCounter > 0 is, er een vorig element is. En zolang $intCounter kleiner is dan het aantal array-elementen min 1, is er ook een volgend element. In code ziet dat er dan als volgt uit:

Bedankt voor je aanvulling. Dit is inderdaad een goed advies.
Het script was inmiddels al wat aangepast, eigenlijk was jou advies hier al in verwerkt. Echter niet met de $intCounter maar ik geef de key van de Array mee in de loop. Zie hier een gecomprimeerde versie van het huidige script:

<?php
if($objStmt->execute())
{
    $arrSonghistory = $objStmt->fetchAll(PDO::FETCH_OBJ);
    $intCounter = 0;
    $intRecordcount = count($arrSonghistory);
    
    foreach($arrSonghistory as $intKey=>$arrSong)
    {
        if($intKey > 0)
            echo('Vorige song was: '.$arrSonghistory[$intCounter-1]->song.'<br>');
        
        echo ('Huidige song is: ' . $arrSong->song . '<br>');
        
        if($intKey < $intRecordcount - 1)
            echo('Volgende song is: '.$arrSonghistory[$intCounter+1]->song.'<br>');
        
        echo ('<br>');
    }
}
?>

Wanneer ik dit in de class verwerk werkt het correct waarvoor ik het nodig heb.
Dit script gaat niet werken, maar ik ga ervan uit dat je het in de echte code wel goed hebt gedaan.

In deze snippet gebruik je namelijk nog $intCounter waar je $intKey moet/kan gebruiken. Omdat $intCounter niet wordt opgehoogd en dus 0 blijft, zal regel 11 altijd een foutmelding geven (invalid index -1) en regel 16 bijna altijd een verkeerde song (behalve bij het eerste record; daar gaat het per ongeluk goed).
Willem vp op 18/12/2014 16:39:27

Dit script gaat niet werken, maar ik ga ervan uit dat je het in de echte code wel goed hebt gedaan.

In deze snippet gebruik je namelijk nog $intCounter waar je $intKey moet/kan gebruiken. Omdat $intCounter niet wordt opgehoogd en dus 0 blijft, zal regel 11 altijd een foutmelding geven (invalid index -1) en regel 16 bijna altijd een verkeerde song (behalve bij het eerste record; daar gaat het per ongeluk goed).

Klopt in had jou script even quick & dirty aangepast.
In het script sla ik namelijk de $intKey waar daadwerkelijk iets mee gedaan wordt op in een variabele. En deze is dan automatisch de vorige record. Dit doe ik omdat er soms een result wordt overgeslagen en daar dus niets mee gedaan mag/hoeft worden. Als ik dan terug ga in de array zelf dan pakt hij alsnog die onnodige record weer.

Zie hier de functie:

<?php
if($objStmt->execute())
{
$objNewSong = new clsSonghistoryItem();
$arrSonghistory = $objStmt->fetchAll(PDO::FETCH_OBJ);

$intLastAdd = '';
$intRecordcount = count($arrSonghistory);

foreach($arrSonghistory as $intKey=>$arrCurrSong)
{
if($intKey > 0)
{
if($intKey < ($intRecordcount-1))
{
$diffMinutes = $this->calcDifference($arrSonghistory[($intKey+1)]->date, $arrCurrSong->date);

if($diffMinutes > 1)
{
if($arrCurrSong->song != $arrSonghistory[$intLastAdd]->song)
{
$objNewSong->addSong($arrCurrSong->id, $arrCurrSong->viewDate, $arrCurrSong->song);
$intLastAdd = $intKey;
}
}
}
else
{
if($arrCurrSong->song != $arrSonghistory[$intLastAdd]->song)
{
$objNewSong->addSong($arrCurrSong->id, $arrCurrSong->viewDate, $arrCurrSong->song);
$intLastAdd = $intKey;
}
}
}
else
{
$objNewSong->addSong($arrCurrSong->id, $arrCurrSong->viewDate, $arrCurrSong->song);
$intLastAdd = $intKey;
}
}

$this->colSonghistory = $objNewSong->toArray();
}
?>

Reageren