PHP Lekcije - lekcija 3.5 - Rad sa MySQL bazom podataka. JOIN operator. Učitavanje fajlova na server.
Pre nego što počnemo sa pisanjem ovog časa, dugo sam razmišljao kako je najbolje predstaviti upite sa JOIN operatorima. Razlog je što je JOIN operator potreban za izvlačenje podataka iz više tabela odjednom. Pošto nam treba još jedna tabela, napravićemo je. Predlažem da napravimo tabelu za fajlove koje ćemo učitavati putem forme već u ovom času. Tako ćemo imati čas sa dve različite teme: rad sa bazom podataka i rad sa formama.
Počećemo verovatno sa dodavanjem polja za učitavanje fajla. Da bi forma mogla da učitava fajlove, potrebno je dodati tip forme u njene parametre:
$content .= '<form action="' . $_SERVER['PHP_SELF'] . '" method="post" enctype="multipart/form-data">';
Na ovaj način, kroz parametar enctype, dajemo do znanja pretraživaču da ćemo preko ove forme učitavati fajlove. Sada kada je forma pripremljena, dodajmo polje za učitavanje fajla:
public function display_admin() { // metoda za unos poruke $content = ''; $content .= '<form action="' . $_SERVER['PHP_SELF'] . '" method="post" enctype="multipart/form-data">'; $content .= '<label for="title">Ime:</label><br />'; $content .= '<input name="title" id="title" type="text" maxlength="150" />'; $content .= '<div class="clear"></div>'; $content .= '<label for="bodytext">Poruka:</label><br />'; $content .= '<textarea name="bodytext" id="bodytext"></textarea>'; $content .= '<input type="file" name="filename">'; // polje za učitavanje fajla $content .= '<div class="clear"></div>'; $content .= '<input type="submit" value="Dodaj poruku" />'; $content .= '</form>'; $content .= '<p><a href="/index.php">Vrati se na početnu</a></p>'; return $content; }
Kroz input sa tipom file, učitavaćemo naš fajl. Ako sačuvate fajlove i osvežite stranicu za dodavanje poruke, trebalo bi da vam se pojavi polje za učitavanje fajla.
Sada hajde da pogledamo kako se fajl prenosi u POST zahtevu.
public function write($p) { print_r($p); // štampamo niz iz forme print_r($_FILES); // štampamo niz fajlova $sql = 'INSERT INTO Messages (title, bodytext, created) VALUES ("'. $p["title"] . '", "' . $p["bodytext"] . '", ' . time() . ')'; return mysql_query($sql); }
Sada učitajte neki fajl i sačuvajte poruku. Svi fajlovi učitani preko forme biće dostupni u superglobalnoj promenljivoj $_FILES. Ja sam učitao fajl i dobio sledeće nizove:
Array ( [title] => asfasdf [bodytext] => asfasdf ) Array ( [filename] => Array ( [name] => ip.txt [type] => text/plain [tmp_name] => Y:\tmp\phpAA.tmp [error] => 0 [size] => 13 ) )
Sada kada imamo niz sa podacima i fajlom, napravimo tabelu za fajlove, da bismo sačuvali učitane fajlove. Počećemo tako što ćemo napraviti folder files u korenu našeg sajta, i ako koristite Linux ili radite na hostingu, podesite prava za ovaj folder na 777, kako bi naš skript mogao da čuva fajlove u ovaj folder.
Izmenimo upit za kreiranje tabela u metodu buildDB():
$sql = "CREATE TABLE Messages ( mid int NOT NULL AUTO_INCREMENT, PRIMARY KEY(mid), title varchar(15), bodytext text, created int(11), file int(11), ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1; CREATE TABLE Files ( fid int NOT NULL AUTO_INCREMENT, PRIMARY KEY(fid), filename varchar(255), filepath varchar(255), filemime varchar(255), filesize int(10), timestamp int(10), )ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;";
Pored dodavanja nove tabele, dodaćemo polje fid koje će biti strani ključ za tabelu fajlova. Za novu tabelu fajlova imaćemo sledeća polja:
fid - primarni ključ naše tabele, ID fajla.
filename - ime fajla.
filepath - putanja do fajla u odnosu na koren sajta.
filemime - tip fajla, da bi se odredilo proširenje fajla i čemu služi (na primer za tekstualne fajlove je text/plain, za slike može biti image/jpg, image/png).
filesize - veličina fajla u bajtovima.
timestamp - vreme učitavanja fajla.
Sada napišimo kako sačuvati fajl i kako napraviti upit za unos fajla u bazu. Možete napraviti potrebna polja kroz phpMyAdmin.
if($_FILES["filename"]["size"] > 1024*3*1024) { echo ("Veličina fajla prelazi tri megabajta"); exit; } // Proveravamo da li je fajl uspešno učitan if(is_uploaded_file($_FILES["filename"]["tmp_name"])) { // Ako je fajl uspešno učitan, premestimo ga // iz privremene fascikle u konačnu move_uploaded_file($_FILES["filename"]["tmp_name"], "/files/".$_FILES["filename"]["name"]); } else { echo("Greška prilikom učitavanja fajla"); }
Ovako čuvamo fajl u folder files. Sada, nakon uspešnog učitavanja fajla, ubacujemo upit u bazu za dodavanje u tabelu Files:
$sql = 'INSERT INTO Files (filename, filepath, filemime, filesize, timestamp) VALUES ("'. $_FILES['filename']['name'] . '", "files/' . $_FILES['filename']['name'] . '", "'. $_FILES['filename']['type'] .'", '. $_FILES['filename']['size'] .', '. time() . ')'; mysql_query($sql);
Sada kada smo ubacili zapis u tabelu fajlova, potrebno je ubaciti i poruku. Upit za unos poruke malo ćemo izmeniti i dodati polje fid.
$sql = 'INSERT INTO Messages (title, bodytext, created, fid) VALUES ("'. $p["title"] . '", "' . $p["bodytext"] . '", ' . time() . ',LAST_INSERT_ID())';
Obratite pažnju na funkciju last_insert_id(), koja vraća poslednji ID ubačen u bilo koju tabelu baze podataka. U našem slučaju, poslednji upit je ubacivao zapis u tabelu fajlova, pa se poslednji ID odnosi na tabelu fajlova.
Sada se zapisi ubacuju u obe tabele, ostaje da ih prikazujemo pomoću JOIN operatora. Izmenimo upit za prikaz poruka da prikazuje i ime fajla:
public function display_public() { // metoda za prikaz poruka $content = ''; $sql = 'SELECT * FROM Messages LEFT JOIN Files ON Messages.fid=Files.fid ORDER BY mid DESC'; $result = mysql_query($sql) or die(mysql_error()); ...
JOIN operator ovde koristim zajedno sa LEFT. Razlog je što se spajanje tabela za selekciju može raditi na različite načine, a u nekom od narednih časova detaljnije ćemo razmotriti upotrebu JOIN-a. Za sada ćemo se držati toga da LEFT JOIN prikazuje sve zapise, uključujući i one gde polje fid nije postojano.
Sada ako odštampamo niz rezultata upita:
public function display_public() { // metoda za prikaz poruka $content = ''; $sql = 'SELECT * FROM Messages LEFT JOIN Files ON Messages.fid=Files.fid ORDER BY mid DESC'; $result = mysql_query($sql) or die(mysql_error()); while($row = mysql_fetch_array($result)){ // rezultat upita treba obraditi posebnom funkcijom mysql_fetch_array() print_r($row);
Videćemo da se prikazuju podaci i iz tabele poruka i iz tabele fajlova. Pri tome, ako odgovarajući fajl ne postoji, polja su prazna. Zato je potrebno proveravati ove vrednosti.
if(!empty($row['filename'])){ $content .= '<p>Prilog: <a target="_blank" href="/'. $row['filepath'] .'">'. $row['filename'] .'</a></p>'; }
Sada će se uz poruku prikazivati i prilog u vidu linka ka fajlu koji smo učitali. U narednom času ćemo detaljnije proučiti sjajan JOIN operator koji omogućava prikaz podataka iz više tabela odjednom. Uz članak ću sada dodavati aktuelni dump baze podataka napravljen kroz phpMyAdmin.