Kirjautuminen

Haku

Tehtävät

Koodit: PHP: Sivutus

Kirjoittaja: Antti Laaksonen

Kirjoitettu: 29.08.2004 – 27.09.2016

Tagit: koodi näytille, vinkki

Jos esimerkiksi vieraskirjassa on paljon näytettäviä viestejä, kaikkia ei kannata ahtaa samalle sivulle. Hyvä idea on järjestää viestit useammalle sivulle ja panna sivun ylälaitaan sivulista, jonka avulla näytettävän sivun pystyy valitsemaan. Toisinaan tällaisen systeemin toteuttaminen tuntuu kuitenkin tuottavan vaikeuksia. Sen takia tässä tulee kunnollinen esimerkki viestien (tai muiden tietojen) sivutuksesta. Vinkkiin kuuluu kaksi skriptiä, joista toinen lukee tiedot tekstitiedostosta ja toinen tietokannasta.

Sivutus on toteutettu niin, että sivun numero kulkee sivun osoitteen mukana sivu-muuttujassa. Jos sivua ei ole ilmoitettu, näytetään ensimmäinen sivu. Sivujen kokonaismäärä selviää jakamalla viestien määrä sivulla olevien viestien määrällä. Näytettävät viestit valikoidaan tekstitiedoston rivit sisältävästä taulukosta - aloituskohta selviää kertomalla sivulla olevien viestien määrä sivunumerolla. Tietokantaversiossa luetaan vain ne viestit, jotka tullaan näyttämään sivulla. Rajaus tapahtuu kyselyn lopussa olevalla "LIMIT aloituskohta, määrä" -lisäyksellä.

Tekstitiedoston rakenne on ensimmäisessä esimerkissä seuraava:

aika1|lähettäjä1|teksti1
aika2|lähettäjä2|teksti2
aika3|lähettäjä3|teksti3

Tietokantaan yhdistämistä ei ole toisessa esimerkissä mukana, joten se täytyy lisätä itse. Taulun nimi on Viestit, ja siihen kuuluu kentät aika, lahettaja ja teksti. Ajat on tallennettu molemmissa esimerkissä "aikaleimoina", eli ne täytyy erikseen muotoilla date-funktiolla.

tekstitiedostoversio

<?php

// yhdellä sivulla olevien viestien määrä
$vps = 10;

// luetaan osoitteen mukana tullut sivunumero
if (isset($_GET['sivu'])) {
    $sivu = $_GET['sivu'];
}
$sivu = intval($sivu);

// luetaan viestit tiedostosta taulukkoon käänteisessä järjestyksessä
$viestit = array_reverse(file("viestit.txt"));

// selvitetään viestien määrä
$maara = count($viestit);

// luodaan sivunumerolista, jos sivuja on useampia
if ($maara > $vps) {
    echo "<p>";
    for ($i = 0; $i < $maara / $vps; $i++) {
        // tulostetaan pystyviivat sivunumeroiden väliin
        if ($i <> 0) {
            echo " | ";
        }
        // jos tämä sivu näytetään, tulostetaan sivun numero lihavoituna
        if ($sivu == $i) {
            echo "<b>".($i + 1)."</b>";
        // muussa tapauksessa luodaan linkki toiselle sivulle
        } else {
            echo "<a href=\"?sivu={$i}\">".($i + 1)."</a>";
        }
    }
    echo "</p>";
}

// tulostetaan sivulla olevat viestit oikeasta kohdasta alkaen
for ($i = $sivu * $vps; $i < $sivu * $vps + $vps; $i++) {
    // varmistetaan, että viimeisellä sivulle ei tule ylimääräistä
    if ($i < $maara) {
        // tulostetaan viestin tiedot yksinkertaisesti muotoiltuna
        $tiedot = explode("|", $viestit[$i]);
        echo "<p><b>{$tiedot[1]}</b> kirjoitti

              <b>".date("d.m.y H:i", $tiedot[0])."</b>:<br>
              <i>{$tiedot[2]}</i></p>";
    }
}

?>

tietokantaversio

<?php

// yhdellä sivulla olevien viestien määrä
$vps = 10;

// luetaan osoitteen mukana tullut sivunumero
if (isset($_GET['sivu'])) {
    $sivu = $_GET['sivu'];
}
$sivu = intval($sivu);

// haetaan näytettävät viestit tietokannasta
$viestit = mysql_query("SELECT aika, lahettaja, teksti FROM Viestit
                        ORDER BY aika DESC LIMIT ".($sivu * $vps).", {$vps}");

// selvitetään viestien määrä
$maara = mysql_result(mysql_query("SELECT COUNT(*) FROM Viestit"), 0);

// luodaan sivunumerolista, jos sivuja on useampia
if ($maara > $vps) {
    echo "<p>";
    for ($i = 0; $i < $maara / $vps; $i++) {
        // tulostetaan pystyviivat sivunumeroiden väliin
        if ($i <> 0) {
            echo " | ";
        }
        // jos tämä sivu näytetään, tulostetaan sivun numero lihavoituna
        if ($sivu == $i) {
            echo "<b>".($i + 1)."</b>";
        // muussa tapauksessa luodaan linkki toiselle sivulle
        } else {
            echo "<a href=\"?sivu={$i}\">".($i + 1)."</a>";
        }
    }
    echo "</p>";
}

// tulostetaan tietokannasta luetut viestit
for ($i = 0; $i < $vps; $i++) {
    // varmistetaan, että viimeisellä sivulle ei tule ylimääräistä
    if ($i + $sivu * $vps < $maara) {
        // tulostetaan viestin tiedot yksinkertaisesti muotoiltuna
        $aika = mysql_result($viestit, $i, 0);
        $nimi = mysql_result($viestit, $i, 1);
        $teksti = mysql_result($viestit, $i, 2);
        echo "<p><b>$aika</b> kirjoitti
              <b>".date("d.m.y H:i", $nimi)."</b>:<br>
              <i>{$teksti}</i></p>";
    }
}

?>

Kommentit

makeuu [29.08.2004 10:32:37]

#

varmasti hyödyllinen, jos osaa hyödyntää :)

T.M. [29.08.2004 17:25:27]

#

Turhat välilyönnit noista tulostettavista jutuista olisi järkevää poistaa, täyttää turhaan HTML-sivua turhilla välilyönneillä.

        echo "<p><b>$aika</b> kirjoitti
              <b>".date("d.m.y H:i", $nimi)."</b>:<BR>
              <i>{$teksti}</i></p>";

...muotoon:

        echo "<p><b>$aika</b> kirjoitti <b>".date("d.m.y H:i", $nimi)."</b>:<BR><i>{$teksti}</i></p>";

Edit: kappas, tuo kooditagi poistaa <BR> tagit (pienellä kirjoitettuna) ja muuttaa ne rivinvaihdoiksi.

Edit2: näyttääpi muuttavan myös tavallisen kommentin <BR> tagit.

ajv [29.08.2004 18:31:01]

#

Hyödyllinen esimerkki. Näin lyhyessä/yksinkertaisessa vinkissä jotenkin kiinnittää huomiota pikkuseikkoihin. Ja vaikka en haluaisi pilkkua viilata, niin kaksi bugia löytyy:
jos sattuu palvelimella olemaan error_reporting = E_ALL, niin

$sivu = $_GET['sivu']

antaa huomautuksen. Varma tapa on

if(isset($_GET['sivu'])) $sivu = intval($_GET['sivu']);

Ja toinen hieman isompi, on $PHP_SELF, joka vaatii register_globals = on, mikä taas nykyaikana on defaulttina off. Muuten oikein hyvä esimerkki. Se olisi hieman kiinnostanut, miten sivutuksen saa näkymään esim. "1,2,3...50,51,52". Muistan joskus tuon toteuttaneeni hirveällä purkalla.

T.M. kirjoitti:

Turhat välilyönnit noista tulostettavista jutuista olisi järkevää poistaa, täyttää turhaan HTML-sivua turhilla välilyönneillä.

Tuosta taas olen aivan eri mieltä. Itse useasti väännän php-koodin jopa siten, että html-koodi on myös täydellisesti ja loogisesti sisennettyä. Muutama rivinvaihto jossain vieraskirjassa ei paljon tiedostokokoon vaikuta.

Antti Laaksonen [29.08.2004 22:11:38]

#

T.M. kirjoitti:

Turhat välilyönnit noista tulostettavista jutuista olisi järkevää poistaa

Lopullinen tekstin tulostus kannattaa muotoilla oman maun mukaan; tämä tuskin muutenkaan sopii sellaisenaan mihinkään tarkoitukseen. Jaoin tekstit sen takia eri riveille, että riveistä ei tulisi liian pitkiä.

ajv kirjoitti:

jos sattuu palvelimella olemaan error_reporting = E_ALL, niin
$sivu = $_GET['sivu'] antaa huomautuksen.

Olet oikeassa, paransin vinkkiä.

ajv kirjoitti:

Ja toinen hieman isompi, on $PHP_SELF, joka vaatii register_globals = on, mikä taas nykyaikana on defaulttina off.

Nyt on korjattu tämäkin.

ajv kirjoitti:

Se olisi hieman kiinnostanut, miten sivutuksen saa näkymään esim. "1,2,3...50,51,52".

Laajennan vinkkiä jossain vaiheessa...

chiqu [20.03.2005 13:15:49]

#

Jrh, sainpa tämän toimimaan. Tosin aikapaljon muokattuna, mutta toimiipa kuitenkin :)

miettinen [17.07.2005 16:56:01]

#

Kyselyn vois muuttaa muotoon LIMIT row_count OFFSET offset, jotta se toimis myös PostgreSQL:llä

ajv [25.12.2005 12:19:46]

#

Tässä vielä oma sivutus-funktioni, joka sivuttaa sivut tyyliin 1, 2, 3, 4, 5 ... 23. Tein alunperin keskustelualueelle esimerkiksi, mutta laitetaan myös tänne, jos tästä jollekkin vaikka apua olisi.

<?php
/*
*  function sivuta(
*     $cp niinkuin current page,
*     $lp niinkuin last page,
*     $url niinkuin sivutuslinkin alkuosa, jonka perään lisätään vain sivunumero
*   )
*/
function sivuta($cp, $lp, $url='?p='){

   $sivut = array();

   //alusta muutama sivu
   for($i=1; $i<=5; $i++){
      $sivut[$i] = true;
   }
    //valitun sivun ympäriltä sopivasti
   for($i=($cp-2); $i<=($cp+2); $i++){
      $sivut[$i] = true;
   }
    //lopusta muutama sivu
   for($i=$lp; $i>=($lp-2); $i--){
      $sivut[$i] = true;
   }

   $str = NULL;
   //käydään läpi 1...viimeinen sivu
   for($i=1; $i<=$lp; $i++){
      //jos sivu on asetettu, niin pistetään linkki merkkijonoon talteen
      if(isset($sivut[$i])){
             $str .= $i == $cp ? ' <b>'.$i.'</b> ' : ' <a href="'.$url.$i.'">'.$i.'</a> ';
         //$k-muuttuja kertoo meille, että merkkijonon viimeisin lisäys on sivutus-linkki
          $k = true;
      }else{
         $str .= $k === true ? '...' : '';
         //$k-muuttuja "pois päältä" => ei lisäillä pisteitä kuin maksimissaa kerran
             $k = false;
      }//if-else
   }//for
   return $str;
}//function
?>

ja käyttöesimerkki ylläolevaan:

<?php
$vps = 40;

// luetaan osoitteen mukana tullut sivunumero
if(isset($_GET['sivu'])) {
    $sivu = intval($_GET['sivu']);
}else{
    $sivu = 1;
}

$maara = mysql_result(mysql_query("SELECT COUNT(*) FROM galleria_users WHERE activation = '1'", $yhteys), 0);

//selvyyden vuoksi nimetään vielä nuo muuttujat samanlailla kuin funktiossakin
$cp = $sivu;
//lasketaan viimeinen sivu
$lp = ceil($maara/$vps);
//ja selattavan sivun osoite
$url = $_SERVER['PHP_SELF'].'?sivu=';

//tarkistus, että osoiteriviltä tullut luku on välillä 1...viimeinen sivu
if($cp < 1 || $cp > $lp) $cp=1;

//sitten vain sivutellaan. Funktio palauttaa sivutuksen tarkoituksella merkkijonona...
$sivutus = sivuta($cp, $lp, $url);

//.. jotta saadaan yhdellä funktiokutsulla sivutus sivun yläreunaan..
echo $sivutus;

    //sivun sisältö
    $kysely = "SELECT * FROM galleria_users WHERE activation = '1' ORDER BY id LIMIT ".(($cp-1) * $vps).", {$vps}";
    //suoritetaan kysely
    $haku = mysql_query($kysely, $yhteys);
    for($i=0; $i<100; $i++) echo rand(0,1) ? 'foo' : 'bar';

//.. ja sivun alareunaan
echo $sivutus;
?>

Ja esimerkki:
http://cgi.evtek.fi/~k0101030/sivutusesimerkki.php

TuhoojaBotti [18.03.2008 15:37:50]

#

plääh minulla on semmoinen onjelma että jos käyttää väli lyöntejä kirjoittaessa viestiä ne hyppäävät seuraavalle riville:
nimi|email|pvm|vie
sti
eli se lukee sen sitten toisen viestin nimenä ;( kuinkas tuon saisi korjattua?

OILgame [11.06.2008 01:20:05]

#

TuhoojaBotti kirjoitti:

plääh minulla on semmoinen onjelma että jos käyttää väli lyöntejä kirjoittaessa viestiä ne hyppäävät seuraavalle riville:

nimi|email|pvm|vie
sti

eli se lukee sen sitten toisen viestin nimenä ;( kuinkas tuon saisi korjattua?

Helpoiten varmaan laittamalla kirjoittajan muodostamaan rivi näin:

  $tiedosto = fopen("teksti.txt", "a");
  $rivi = "$nimi|$email|$pvm|$viesti\n";
  fwrite($tiedosto, $rivi);
  fclose($tiedosto);

ApE!0 [29.06.2008 15:23:37]

#

Ei onnistu jos viesti syötetään textarealla. Käytä tälläistä:

$viesti = str_replace(array("\r\n", "\n"), "<br/>", $viesti);

E: turha näin vanhoihin viesteihin on vastata mutta mutta...

stageradio [13.01.2009 21:24:15]

#

sain database version toimimaan kertaalleen.. mutta kun yritän saada sitä toimimaan toisen tietokannan kanssa niin syntyy ongelmia enkä ymmärrä mikä sen aiheuttaa..


virhe koodi on seuraavan lainen:
Warning: mysql_result(): supplied argument is not a valid MySQL result resource in C:\Apache\Apache2.2\htdocs\uusi\news.php on line 29

ja rivillä 29 on seuraavan laista:
$maara = mysql_result(mysql_query("SELECT COUNT(*) FROM news"), 0);

tiedän että on jo vanha topic mutta mutta...

Hakoulinen [10.10.2009 13:50:19]

#

stageradio kirjoitti:

sain database version toimimaan kertaalleen.. mutta kun yritän saada sitä toimimaan toisen tietokannan kanssa niin syntyy ongelmia enkä ymmärrä mikä sen aiheuttaa..


virhe koodi on seuraavan lainen:
Warning: mysql_result(): supplied argument is not a valid MySQL result resource in C:\Apache\Apache2.2\htdocs\uusi\news.php on line 29

ja rivillä 29 on seuraavan laista:
$maara = mysql_result(mysql_query("SELECT COUNT(*) FROM news"), 0);

tiedän että on jo vanha topic mutta mutta...

Joko et ole luonut taulua news (1. parametri funktiolle mysql_result) tai et ole saanut yhteyttä muodostettua (2. parametri)

Kirjoita kommentti

Muista lukea kirjoitusohjeet.
Tietoa sivustosta