Ta teden si bomo pogledali delo z datotekami in mapami.
PHP ima nekaj zelo "udobnih" funkcij za branje iz datotek, najbolje, da si kar pogledamo primer.
Imamo datoteko imena.txt, v kateri imamo v vsako vrstico zapisano po eno ime, recimo:
Marko
Peter
Mitja
Janez
Te podatke lahko v naš program preberemo z uporabo
dveh funkcij - file() in file_get_contents().
Razlika med tema dvema funkcijama je, da funkcija file() prebere
datoteko in jo vrne v obliki polja, funkcija file_get_contents()
pa jo vrne v obliki niza.
Funkcija file() sprejme en obvezen argument - to je pot do datoteke. Ta pot je lahko podana absolutno (npr. c:\dokumenti\podatki.csv (Windows) oz. /home/marko/doc/podatki.csv (Linux)), relativno (doc/podatki.csv), lahko pa je to tudi pot do datoteke na nekem HTTP ali FTP strežniku (recimo http://www.stamcar.com/test.txt).
Če se vrnemo na zgornjo datoteko imena.txt (ki se nahaja v istem direktoriju kot naša skripta) - z ukazom
$vsebina = file("imena.txt");
vsebino datoteke shranimo v 1-dimenzionalno polje z imenom vsebina. Vsaka vrstica v tem polju odgovarja eni vrstici v datoteki, zato lahko z ukazom count($vsebina) dobimo število vrstic v datoteki.
Vsebino datoteke bi na zaslon vrstico-po-vrstico izpisali takole:
$vsebina = file("imena.txt");
for ($i = 0; $i < count($vsebina); $i++) {
print $vsebina[$i]; // izpis trenutne
vrstice
}
Uporabili smo zanko for,
s pomočjo katere smo šli čez vse vrstice, začenši
pri 0 in do "velikost polja - 1".
Primer branja iz spleta (prebrali bomo vremensko napoved iz strani ARSO):
$vsebina =
file("http://www.arso.gov.si/podro~cja/vreme_in_podnebje/napovedi_in_podatki/napoved.html");
for ($i = 0; $i < count($vsebina); $i++) {
print $vsebina[$i]; // izpis trenutne
vrstice
}
Z izpisom še nismo zadovoljni, ker smo bili primorani zajeti celotno spletno stran. Zato moramo ugotoviti, v kateri vrstici se začne dejanska vremenska napoved. Če si pogledamo izvorno kodo strani, ugotovimo, da v 35. vrstici - zato bomo začetno vrednost števca i iz 0 spremenili v 34.
Morda bi želeli odrezati tudi spodnji del strani, kjer se vremenska napoved konča. V kodi opazimo, da se tam pojavi oznaka za konec celice - </td>. Zanko lahko z ukazom break prekinemo, ko pridemo do vrstice, v kateri se nahaja ta oznaka.
V skladu z zgornjim namigom moramo upoštevati, da je na koncu vsake vrstice dodana oznaka \n, ki pomeni prelom vrstice. Imamo dve možnosti - ko iščemo, ali je v trenutni vrstici ($vsebina[$i]) oznaka </td>, moramo na koncu dodati še znak \n, ali pa iz vseh vrstic z uporabo funkcije substr() odstranimo zadnji znak. Spodaj sta ti dve možnosti pobarvani z rdečo in modro barvo (pri kopiranju kode izberi samo eno možnost!).
Izboljšana verzija kode je tako takšna:
$vsebina =
file("http://www.arso.gov.si/podro~cja/vreme_in_podnebje/napovedi_in_podatki/napoved.html");
for ($i = 34; $i < count($vsebina); $i++) {
$vsebina[$i] = substr($vsebina[$i],0,strlen($vsebina[$i])-1);
/* iz trenutne vrstice
odrežemo zadnji znak */
if ($vsebina[$i] == "</td>") {
if ($vsebina[$i] == "</td>\n") {
break;
}
print $vsebina[$i];
}
Če želimo iz izpisa odstraniti HTML oznake, lahko uporabimo funkcijo strip_tags().
Če odstranimo HTML oznake, izgubimo tudi oznake <br />, ki označujejo prelome vrstic v HTML kodi (pomni, da spletni brskalniki vrstice prelomijo samo z oznako <br />, znake za prelom vrstic \n pa ignorirajo oz. jih pretvorijo v presledke.), zato je koristno uporabiti tudi funckijo nl2br(), ki znake za nove vrstice pretvori v HTML oznake <br />. V primeru, da bi želeli uporabiti to funkcijo, se moramo obvezno poslužiti modre variante zgoraj, vrstico za izpis trenutne vrstice pa spremenimo v
print nl2br(strip_tags($vsebina[$i]));
kar pomeni, da iz trenutne vrstice najprej odstranimo vse HTML oznake iz originalne spletne strani, nato pa vse znake za nove vrstice zamenjamo z HTML oznakami <br />.
je dokaj podobna funkciji file() s to razliko, da nam namesto 1D polja vsebino datoteka vrne z niz. Tako je branje iz datoteke še lažje, če jo ne mislimo obdelovati - primer izpisa vsebine datoteke imena.txt z dodanimi oznakami <br /> za nove vrstice, s katerimi dosežemo lepši izpis:
$vsebina = file_get_contents("imena.txt");
print nl2br($vsebina);
V datoteko neke podatke najpogosteje zapišemo s kombinacijo funkcij fopen(), fputs() in fclose().
Če bi v datoteko test.txt želeli napisati Živjo!, bi to storili takole:
$handler = fopen("test.txt",
"w");
fputs($handler, "Živjo!");
fclose($handler);
V prvi vrstici datoteko test.txt odpremo za pisanje (ta kazalec shranimo v spremenljivko z imenom handler), nato v drugi vrstici s sklicevanjem na ta kazalec v datoteko zapišemo niz Živjo! in datoteko na koncu "zapremo" (prenehamo obdelovati) s klicem funkcije fclose().
Sedaj si oglejmo, kako bi naredili preprosto knjigo gostov. Od uporabnika bomo želeli 3 podatke - ime, priimek in kraj. Podatke o knjigi gostov bomo hranili v datoteki knjigagostov.txt, vsak vnos pa bomo shranili v novo vrstico. Za začetek si poglejmo kodo za obrazec in za shranjevanje v datoteko:
<form method="post">
Ime: <input type="text" name="ime"/><br />
Priimek: <input type="text" name="priimek"/><br
/>
Kraj: <input type="text" name="kraj"/><br />
<br />
<input type="submit" name="akcija" value="Vpis v knjigo
gostov"/>
</form>
<?php
if ($_POST['akcija']) {
if ($_POST['ime'] &&
$_POST['priimek'] && $_POST['kraj']) {
$niz =
$_POST['ime'] . "@" . $_POST['priimek'] . "@" . $_POST['kraj'] . "\n";
$handler
= fopen("knjigagostov.txt", "a");
fputs($handler, $niz);
fclose($handler);
print
"<br /><b>Hvala! :)</b>";
} else {
print
"<br /><b>Napaka: niste izpolnili vseh
polj!</b>";
}
}
?>
Prvih 7 vrstic tvori kodo za standarden HTML obrazec s tremi tekstovnimi polji in gumbom za pošiljanje.
V PHP kodi imamo nato en zunanji if stavek, s katerim preverjamo, če je uporabnik kliknil na gumb ($_POST['akcija'] je okrajšava za $_POST['akcija'] != ""), z notranjim if stavkom pa preverjamo, če so bila res izpolnjena vsa 3 vnosna polja (v nasprotnem primeru vrnemo napako).
Če so bila, ustvarimo nov niz z imenom niz in vanj "sestavimo" vrstico, ki jo bomo zapisali v datoteko. Podatke ločimo z nekim znakom, ki ga v samem zapisu ne pričakujemo, recimo z @ (afno). Na koncu ne smemo pozabiti še znaka za novo vrstico - \n. (Drugače bi se vsi naslednji zapisi "nabirali" v isti vrstici, česar pa nočemo).
Z naslednjimi 3 vrsticami ta niz zapišemo v datoteko knjigagostov.txt (ker smo uporabili argument "a" se bodo podatki dodali na konec datoteke) in se uporabniku zahvalimo za vnos.
Če bi sedaj podatke iz knjige gostov želeli izpisati v obliki tabele, bi uporabili funkciji file() in explode().
Funkcija explode() nam omogoča, da vrstico razdelimo na več manjših koščkov (funkcija vrne 1D polje s temi koščki), koščke pa ločuje seperator, v našem primeru je seperator znak @ (afna).
Koda za izpis podatkov v obliki tabele:
<table>
<tr><th>Ime</th><th>Priimek</th><th>Kraj</th></tr>
<?php
$podatki = file("knjigagostov.txt");
for ($i = 0; $i < count($podatki); $i++) {
$vrstica
= explode("@",$podatki[$i]);
print
"<tr><td>{$vrstica[0]}</td><td>{$vrstica[1]}</td><td>{$vrstica[2]}</td></tr>";
}
?>
</table>
V polje podatki smo shranili vsebino celotne datoteke, nato pa vsako vrstico razbijemo s funkcijo explode() in sicer na 3 dele, do katerih nato dostopamo prek $vrstica[0], $vrstica[1] in $vrstica[2].
Poglejmo si še, kako bi naredili preprost števec obiskovalcev. Podatke bomo shranjevali v datoteko stevec.txt:
<?php
$vsebina = file("stevec.txt");
$stevilo = intval($vsebina[0]);
$stevilo++;
$handler = fopen("stevec.txt", "w");
fputs($handler, $stevilo);
fclose($handler);
print $stevilo;
?>
Prvič, ko boš skripto pognal, bo javila napako, ker datoteke stevec.txt še ni, naslednjič pa bo že lepo delovala. Ob vsakem klicu se iz datoteke prebere trenutno število (ki je shranjeno v prvi in edini vrstici datoteke), nato se to število poveča za 1 in zapiše v datoteko (ker smo v funkciji fopen() uporabili argument "w", se trenutno število v datoteki prepiše z novim) ter se na koncu še izpiše trenutno število obiskovalcev.
Poglejmo si še nekaj koristnih funkcij za delo z datotekami in mapami:
unlink()
- kot argument podamo ime datoteke, ki jo želimo izbrisati
opendir(), readdir() in closedir() -
seznam datotek v neki mapi, primer:
<?php
$mapa = "."; // trenutna mapa, kjer se nahaja skripta
$handler = opendir($mapa);
while (($datoteka = readdir($handler)) !== false) {
echo $datoteka . "<br />";
}
closedir($handler);
?>
filesize() in
filectime() -
vrne velikost datoteke v bajtih datum ustvaritve datoteke (samo v
Windowsih)
mime_content_type() -
vrne MIME tip datoteke (npr. text/plain)
Tukaj si lahko ogledaš še seznam preostalih funkcij za delo z datotekami in mapami.
Sedaj znamo z datotekami ustvariti preprosto podatkovno bazo. V PHP žargonu bi temu rekli "flat-text database". Z uporabo nekega neuporabljenega znaka lahko v isto vrstico "zakodiramo" več podatkov. Sedaj pa veselo na domačo nalogo in nato na forum, če imaš kakšna vprašanja :)