D. lecke (HTML5, CSS3, PHP5)


Új (PHP manual)


Tudáspróba - 1. variáció (egyszerű feleletválasztós teszt két PHP programmal)

Ennek a lényege a következő: Egy egyszerű szerkezetű szövegfájlt (adatfájlt) alakít tesztté egy PHP program (index1.php), egy másik PHP program (ertekel.php) pedig kiértékeli a válaszainkat. Minden feladat egy kérdésből és két vagy több válaszból (max. 5) áll. A válaszok közt csak egy hibátlan van, ezt kell megjelölni. Az összes kérdés megválaszolása után törölhetjük válaszainkat vagy kérhetünk egy értékelést.


Előkészületek

A szükséges fájlok (tömörítve):

  • quiz/ - a teszttel kapcsolatos fájlok helye
  • quiz/index1.php - a tesztet feldolgozó PHP fájl
  • quiz/ertekel.php - a tesztet értékelő PHP fájl
  • quiz/index.txt - a tesztek hívását vezérlő linkgyűjtemény
  • quiz/css/style1.css - a tesz megjelenését beállító stílusfájl
  • quiz/data/ - tesztfájlok/tesztadatok helye
  • quiz/data/minta.txt - teszt(adat)fájl: egy egyszerű teszt 4 kérdéssel és válaszokkal
  • quiz/data/logi1.txt - teszt(adat)fájl: logikai kérdések és válaszok
  • quiz/data/html1.txt - teszt(adat)fájl: HTML kérdések és válaszok
  • quiz/data/css1.txt - teszt(adat)fájl: CSS kérdések és válaszok
  • stb.
  • quiz/imgs/ - a teszttel kapcsolatos képek helye
  • quiz/imgs/bk.jpg - képfájl: jómagam
  • stb.

Látható, hogy az összes fájl a quiz könyvtárban, vagy ennek valamelyik alkönyvtárában található.


Másoljuk le az "indexC.php" fájlt "indexD.php", a "mainC.css" fájlt "mainD.css", valamint a "menuC.inc" fájlt "menuD.inc" néven és javítsuk át a rá való hivatkozásokat!


Javítsuk ki a "Tudáspróba" menüpont hívását (menuD.inc-ben):

   <a href='indexD.php?kod=tp'>Tudáspróba</a>

Szúrjuk be ki a "Tudáspróba" menüpont megjelenítését vezérlő részt indexD.php-be (a "Hírek" if-je után):

   if ($kod=='tp') { // Tudáspróba
      $fn = "quiz/index.txt";
      $htm = txtmegjel($fn); echo "$htm";
   }

Ellenőrizzük az "quiz/index.txt" meglétét (a leckeD.zip-ben van becsomagolva)!

Ezután elméletileg működik az első quiz-ünk (a Quiz1)!


A teszt adatfájljainak felépítése

Részletesebben az első öt sorról:

  1. a teszt címe
  2. a teszttel kapcsolatos információ (egy sor, de a <br> HTML paranccsal több sorra is törhető)
  3. a teszt szerzője (pl. Összeállította: xy)
  4. a tesz "születési dátuma" (pl. 2017.03.30.)
  5. a teszttel kapcsolatos linkek (források, hasonló kvízek, olvasmányok, de lehet egy üres sor is)

Az adatfájl elején pontosan öt sornak kell állnia, mert a 6. sort már kérdésnek értelmezi a feldolgozó program!

Részletesebben a "tesztelemekről":

  • minden kérdés egy szövegsor legyen, de ebben lehetnek HTML parancsok (pl. kép, link, egy <br> amivel többsorossá tehető a megjelenítés, felsorolás, sorszámozott lista vagy akár egy komplett táblázat)
  • a válaszok felépítése:
    - a válaszok is egysorosak
    - az első karakter mindegyik sorban egy tabulátor,
    - a válaszok közt csak egy helyes válasz lehet, ezt (a tab után) egy csillag jelölje (tehát a 2. karakter csillag)
  • az utolsó válaszok után egy üres sor álljon

Az adatfájl magyarázattal

Az adatfájl magyarázat nélkül

Kattints ide!



A kérdőív működése, összeállítása, feldolgozása, megjelenése



Kitöltött kérdőív


A hibátlanul kitöltött kérdőív (adatfájl: minta.txt)


A kérdőív/form forrása, működése

<form action='ertekel.php' method='post' id='quiz'> (1)

<ol>
   <li>
      <p>Mi a vezetéknevem?<br><img style='width:64px;' src='imgs/bk.jpg' /></p> (2)
      <div class='inp'><input type='radio' name='q01' id='q01A' value='A' /></div> (3)
      <div class='lab'><label for='q01A'>Burcsi</label></div> (4)
      <div class='jel'>A</div><br>
      <div class='inp'><input type='radio' name='q01' id='q01B' value='B' /></div> (3)
      <div class='lab'><label for='q01B'>Károly</label></div> (4)
      <div class='jel'>B</div><br>
      <div class='inp'><input type='radio' name='q01' id='q01C' value='C' /></div> (3)
      <div class='lab'><label for='q01C'>Ferenc</label></div> (4)
      <div class='jel'>C</div><br>
      <div class='inp'><input type='radio' name='q01' id='q01D' value='D' /></div> (3)
      <div class='lab'><label for='q01D'>Burján</label></div> (4)
      <div class='jel'>D</div><br>
   </li>
   <li>
      <p>Mi az első keresztnevem?</p> (2)
      <div class='inp'><input type='radio' name='q02' id='q02A' value='A' /></div> (3)
      <div class='lab'><label for='q02A'>Burján</label></div> (4)
      <div class='jel'>A</div><br>
      <div class='inp'><input type='radio' name='q02' id='q02B' value='B' /></div> (3)
      <div class='lab'><label for='q02B'>Károly</label></div> (4)
      <div class='jel'>B</div><br>
      <div class='inp'><input type='radio' name='q02' id='q02C' value='C' /></div> (3)
      <div class='lab'><label for='q02C'>Ferenc</label></div> (4)
      <div class='jel'>C</div><br>
   </li>
   .....
   <li>
      <p>Milyen nemű lehetek?</p> (2)
      ...
   </li>

</ol>

<input type='hidden' name='kdrb' value='4'> (7)
<input type='hidden' name='hval' value='DBCA'> (7)
<input type='hidden' name='fcim' value='$cim'> (7)
<div class='ressub'>
   <input type='reset' value='   Adott válaszok törlése   '> (6)     
   <input type='submit' value='   Rendben van, értékelés   '> (5)
</div>

</form>

Kicsit részletezve:

  1. form
    action - utána áll a feldolgozó program neve, amely a kérdőív kitöltése és elküldése után kezd el "dolgozni"
    method - kétféle értéke lehet: GET (lekérés) illetve POST (elküldés), kérdőíveknél általában az az utóbbit használjuk (nagyobb adatmennyiséget tud kezelni)
    id - azonosító, a CSS-el való formázáshoz szükséges
  2. p - kérdés (sorszámozott listaelemek, lehet benne kép, lista, táblázat, stb.)
  3. input type='radio' - beviteli mező, most éppen választógomb (sokféle lehet: text,password,date, ..., radio,hidden,reset,submit)
    e típusnál az egy csoportbeliekből csak egyet tudunk választani (az azonos nevűek tartoznak egy csoportba, pl. name='q02')
    a feldolgozó program kapja és használja az összerendelt "name" --> "value" párt ("név" --> "érték"), amelyet választottunk
  4. label - az űrlapmező címkéje/megnevezése; az összetartozó párokat (pl. id='q02C' <---> for='q02C') az azonos karakterlánc (itt q02C) kapcsolja össze
  5. input type='submit' - elküldő gomb, rákattintva a mezők értéke átkerül a feldolgozó programhoz (általában ide kattintunk utoljára!)
  6. input type='reset' - törlő gomb, rákattintva az addig kitöltött/választott értékek mind törlődnek
  7. input type='hidden' - rejtett beviteli (bár inkább "átviteli") mező, értéke nem látszik a kérdőíven, a feldolgozó program kapja meg és értelmezi majd (kdb: kérdések darabszáma, hval: helyes válaszok betűjele, fcim: a quiz főcíme)

A kérdőív/form generálása (index1.php)

Konstansok (10-28. sor)

A tisztán PHP program elején két állandót/konstanst adunk meg, a weboldal fej- és lábrészét ($htmlfej,$htmllab), amelyeket majd később a megfelelő "időpontban" kiírunk (43. ill. 126. sor).

$htmllab = "

</body>
</html>
";

Megjelenítéskor az üres sor és a sortörések is megjelennek. (Próbáljuk ki: futassuk le az "index1.php"-t, majd nézzük meg a forrást!)


Adatfájl neve paraméterként (35., 36. sor)

$kod = $_GET['kd']; if ( $kod == "" ) { $kod = "minta"; } // hívás .txt nélkül
$inp = "data/$kod.txt";

A "kd" paraméter tartalmazza az adatfájl nevét (kiterjesztés nélkül). Ezek helye a "data" könyvtár, ha nincs fájlnév, a "data/minta.txt" lesz a tesztalany.


Elágazás egy fájl léte alapján (45-124. sor)

 if (!file_exists($inp)) {
    echo "<h1 style='margin-top:300px;font-size:300%;color:red;'>A(z) $inp fájl nem létezik!</h1>";
 } else {
    ...
 }

A "file_exists($inp)" függvény a zárójelben lévő adatfájl ($inp) létezését vizsgálja (a "!" ennek a tagadása), ha a fájl létezik, az "else" ág fut, egyébként egy hibaüzenetet ír ki (hatalmas piros betűkkel).


Beolvasás, tesztjellemzők változókba (51-56. sor)

 $s = file("$inp"); // Adatfájl beolvasása tömbbe - 5. sor már az első a kérdés
 $cim    = chop(array_shift($s)); // teszt megnevezése
 $info   = chop(array_shift($s)); // információ
 $szerzo = chop(array_shift($s)); // szerző(i)
 $datum  = chop(array_shift($s)); // dátuma
 $forras = chop(array_shift($s)); // forrása(i)

Az "$cim = chop(array_shift($s));" magyarázata (az alatta lévők hasonlóan működnek):

  • megjegyzi az előzőleg beolvasott "$s" tömb első elemét, majd kiszedi a tömbből (csak az utána lévők maradnak, tehát a régi 2. lesz az első) – array_shift() függvény
  • levágja róla a sorvégjelet – chop() függvény
  • ezt megkapja értékül a "$cim" változó

Tehát az adatfájl első öt sorát (feldolgozás után) kivesszük a tömbből, azaz csak tisztán a kérdések és a rájuk adható válaszok maradnak.

Ezután az 59., 60. sor a fentiekből a címet és az alcímet/infót formázva kiírja.

echo "
    <p class='h1'>$cim</p>
    <p class='h2'>$info</p>

    <form action='ertekel.php' method='post' id='quiz'>

    <ol>
";

Majd megkezdjük a form létrehozását (62. sor), ebben egy lista tartalmazza a kérdéseket és az erre adható válaszokat (64. sor).


Form tartalmának létrehozása (62-120. sor)

    $ki = 0; // kérdés indexe /1/
    $i = 0;  // sor indexe
    $hval = "";
    do { /2/
        $sor = chop($s[$i]); $i++; /3/
        $vi = 0;    // válasz indexe /4/
        $num = 0;  // helyes válasz sorszáma (0,1,...)

echo "
        <li>
            <p>$sor</p>"; /5/

        do { /1/
            $sor = chop($s[$i]); $i++; /1/
            $sor = substr($sor,1);   // tab leszedve /2/
            if ($sor[0]=='*') { /3/
                $sor = substr($sor,1);   // * leszedve
                $num = $vi;
            }
            $ssz = $ki+1; if ($ssz<10) { $ssz = "0$ssz"; } /4/   // kérdés sorszáma (kétjegyűvé kiegészítve)
            $jel = chr(65+$vi);   // válasz betűjele: A,B, ... /5/
            $valt = "q$ssz"."$jel"; /6/
            $vi++; /6/

echo "
            <div class='inp'><input type='radio' name='q$ssz' id='$valt' value='$jel' /></div>
            <div class='lab'><label for='$valt'>$sor</label></div>
            <div class='jel'>$jel</div><br>"; /7/

        } while (chop($s[$i]) != ''); /1/

echo "
        </li>
"; /5/

        $hval = $hval.chr(65+$num); /6/   // stringben adom át a helyes válaszokat
        $ki++;
        $i++;
    } while (chop($s[$i]) != ''); /2/


Két egymásba ágyazott hátultesztelő ciklus, a külső készíti elő és dolgozza fel a kérdést, a belső pedig a válaszok sorait. Az utolsó kérdés után üres sor áll, így kilép a belső ciklusból,

Külső ciklus (fekete, sorszámozás narancsszínnel)

  1. az indexek alapértékeinek ill. a helyes választ tároló sztring beállítása (a válaszok indexét belül állítjuk)
  2. kezdődik a ciklus, ebből csak a második üres sor után lép ki
  3. a kérdés sorának beolvasása, sorindex növelése (ez már az első válaszé)
  4. a válasz indexét az elsőre állítjuk (0.!), majd beállítjuk a helyes válasz indexét mutató "$num"-ot is
  5. kérdés kiírása listaelemként (<li>), a ciklus után lezárjuk (</li>)
  6. a helyes válasz indexét a "chr" függvénnyel nagybetűvé konvertáljuk (0->A ,1->B, 2->C, ...), a "$hval" jobb oldalára ragasztjuk, majd növeljük a kérdés- és sorindexet

Belső ciklus (piros, sorszámozás kékkel)

  1. hátultesztelő ciklus kezdődik
    az "$i" még a kérdés utáni első válasz sorára mutat, tartalmát a "$sor" változóba tesszük, és lépünk vele a következő sorra
    a ciklus végén az üres sort vizsgáljuk, ha az van, kilépünk
  2. mivel minden válaszsor tabulátorral kezdődik (PHP-ben "\t" a tab), a "substr" függvénnyel megszabadulunk tőle
  3. a helyes válasz előtt még "*" is állhat, most ezt vizsgálja az elágazás: ha van, akkor leszedjük a sor elejéről, és megjegyezzük a "$j" válaszsorszámot a "$num" változóban
  4. megnöveljük a kérdés indexét ($ki-t, mert 0-ról indult), s ha egyjegyű, teszünk elé egy "0"-t, így mindegyik kétjegyű lesz (01, 02, ..., 10, 11, ...)
  5. az aktuális válasz "$j" indexéből karakteres indexet gyártunk (0->A, 1->B, 2->C, ...)
  6. a "$valt" változó fogja azonosítani az egy kérdéshez tartozó válaszokat, ezt állítjuk itt elő,
    majd növeljük a válasz indexét "$j"-t
  7. egy sorba (stílusokkal formázva) kiírjuk a következő három dolgot:
    rádiógomb megjelenítése; a kérdéssel a "q$ssz", a válasszal a "$valt" kapcsolja össze, a feldolgozó program a "value" utáni "$jel"-et kapja majd, ha éppen ezt választottuk
    a válasz szövegének megjelenítése (itt a "for", a rádiógombnál az "id" a kapcsolódási pont)
    a válasz betűjelének megjelenítése (A, B, ...)

Kitöltött kérdőívek értékelés után




A "minta.txt" adatfájl két különböző kitöltése utáni értékelés.


Értékelés/feldolgozás generálása (ertekel.php)

Az értékelő program itt is (lásd "Kérdőív program") a konstansok megadásával kezdődik, ezt most már nem részletezzük. (10-28. sor)

Form átadott (rejtett) adatait változókba tesszük (34-36. sor)

 $kdrb = $_POST['kdrb']+0; // numerikus legyen!
 $hval = $_POST['hval'];
 $fcim = $_POST['fcim'];

A "GET"-el átadott paraméterekhez hasonlóan kell a "POST" adatait is átvenni. Ezek karakter-típusúak lesznek, ezért ha "0"-val növeljük, automatikusak numerikussá konvertálódik.

Weboldal fejrészének, és a címeknek kiírása (38-40. sor)

 echo "$htmlfej";
 echo "<p class='h1'>$fcim</p>\n";
 echo "<p class='h2'>A teszt értékelése</p>\n";

Az első "echo" az oldal fejrészét generálja (head és környéke), a másik kettő a fő- és alcímet írja ki a weboldalra.

Táblázatszerű fejléc (42-44. sor)

 echo "<div class='kerd'><b>Kérdés sorszáma</b></div>";
 echo "<div class='hval'><b>Helyes válasz</b></div>";
 echo "<div class='aval'><b>Adott válasz</b></div><br>\n";

A kiírás egy sorba történik, aminek a megjelenését a "kerd", "hval", "aval" stílusosztályok vezérlik (részletezve a "Stílusok" lapon lesz), ugyanezek a stílusok megtalálhahatók a lentebbi ciklus belsejében is.

Adott válaszok kiértékelése ciklusban (46-61. sor)

 $ossz = 0;
 for ( $i=1; $i<=$kdrb; $i++ ) {
	$ii = ($i<10) ? "0$i" : $i ;
	$hv = $hval[$i-1];
	$nev = "q$ii";
	$av = $_POST["$nev"];
	echo "<div class='kerd'>   $i. Kérdés</div>";
	echo "<div class='hval'>   $hv</div>";
	if ($av==$hv) {
		$ossz++;
		echo "<div class='aval'>   <span style='font-weight:bold;color:red;'>$av</span></div>";
	} else {
		echo "<div class='aval'>   $av</div>";
	}
	echo "<br>\n";
 }

Magyarázat soronként

  1. "$ossz" változó beállítása alapértékre (ez számolja az összes helyes választ)
  2. megszámlálható ciklus, amely végigfut az összes kérdésen (és természetesen vizsgálja majd az adott válaszokat)
  3. ez egy feltételes értékadás: ha a zárójelben lévő feltétel igaz, akkor a kérdőjel utáni, ha hamis a kettőspont utáni értéket kapja az "$ii" változó (tulajdonképpen egy kétirányú, nagyon tömörített elágazás).
  4. kiveszi a "$hv" változóba az aktuális helyes választ (pl. ha a $hval='DBCA' és $i=1, akkor $hv='D', mert $hval[0]='D')
  5. "$nev"-ben előállítjuk a kérdés nevét (q01, q02, ..., stb.), amely alapján megkaphatjuk majd a kérdőív kitöltésekor a kérdésre adott választ
  6. a válasz kiolvasása, elhelyezése az "$av" (adott válasz) változóban
  7. a "Kérdés" szöveg kiírása, előtte a sorszáma
  8. a kérdésre adandó helyes válasz kiírása
  9. - 15. Végül kiírjuk az adott választ is, ha egyezik a helyessel, akkor piros színnel (és növeljük a "$ossz" számlálót), valamint elhelyezünk egy soremelést

Összesítés, hibátlan esetben gratuláció (63-66. sor)

 echo "<br><p class='h2'>A helyes válaszok száma: $ossz</p>\n";
 if ($ossz==$kdrb) {
	echo "<p class='h2'>Gratulálok, ez 100%-os teljesítmény!</p>\n";
 }

Az "$ossz" változóban gyűjtögetett értéket írjuk ki, s ha ez egyezik a kérdések számával, akkor gratulálunk is.

A legvégén generáljuk a weboldal lábrészét. (68. sor)


Stílusok (style1.css)

A teljes stílusfájl: "quiz/css/style1.css"

Csak a legfontosabb stílusok rövid magyarázata szerepel itt. Célszerű a megértésükhöz kicsit módosítva kipróbálni ezeket, majd (ha az jobb volt) visszaállítani az eredetit.


Kérdőív stílusai

 .inp {
    display:inline-block; width:3%; padding-top:8px;
    text-align:right; vertical-align:top;
 }

 .lab {
    display:inline-block; width:90%; margin:0 4px 4px 4px; padding:4px 8px 4px 8px;
    background-color:#eee;
    line-height:24px;
 }
 .jel {
    display:inline-block; width:3%;
 }

Az .inp, .lab, .jel stílusosztályok egy sorban lévő téglalap alakú blokkok, szélességüket a lapszélesség százalékában adtuk meg (pl. width:3%; a rádiógombnak kicsi kell).

(Hasonló az értékeléshez szükséges lenti három stílushoz!)

Értékelés stílusai

 .kerd {
    display:inline-block; width:30%;
    line-height:24px;
 }
 .hval {
    display:inline-block; width:20%;
 }
 .aval {
    display:inline-block; width:10%;
 }

A fenti három stílusosztály (.kerd, .hval, .aval) mindegyike téglalap alakú blokk, melyek egy sorban vannak (display:inline-block;), szélességüket pedig a lapszélesség százalékában adtuk meg (width:xx%;).