chevron-left chevron-right

[PHP][JS] Galeria zdjęć ze zmieniającymi się zdjęciami + upload zdjęć na serwer

Korzystając z chwili przerwy w czasie nauki do sesji egzaminacyjnej postanowiłem dzisiaj zaprezentować Ci ciekawy pomysł na galerię zdjęć lub swoisty pokaz slajdów, zależnie od tego jak to potraktujesz.
Ten projekt galerii wykorzystuje zapytania wywoływane przez AJAX do bazy danych MySQL w celu pobrania losowych obrazków do widoku galerii.
Zdjęcia w galerii są co jakiś czas odświeżane bez przeładowania strony (właśnie po to korzystamy z AJAXa).
Brzmi ciekawie? To zapraszam do czytania dalej.

Etap pierwszy - utworzenie tabeli

Aby zacząć zabawę z naszą galerią, musimy najpierw stworzyć tabelę w bazie danych. Kod takiego zapytania MySQL generujący bazę danych wygląda następująco:

CREATE TABLE 'galeria' (
'id_zdjecie' INT( 10 ) NOT NULL AUTO_INCREMENT ,
'nazwa_zdjecie' VARCHAR( 255 ) DEFAULT NULL ,
'opis_zdjecie' text,
'link_zdjecie' VARCHAR( 255 ) NOT NULL ,
PRIMARY KEY ( 'id_zdjecie' )
);

Czyli nic szczególnego.

Etap drugi - połączenie z bazą danych

Pierwszy etap za nami. Pora na napisanie kodu PHP udostępniającego połączenie z bazą danych:

db.php
 
< ?php
$dbhost							= "adres_serwera";
$dbuser							= "uzytkownik";
$dbpass							= "haslo";
$dbname							= "nazwa_bazy";
 
$mysqli = new MySQLi($dbhost, $dbuser, $dbpass, $dbname) or die(mysqli_error());
?>

Bardzo często jako adres serwera wystarczy wpisać localhost.

Etap trzeci - tworzenie mechanizmu uploadu

Kolejnym krokiem jest stworzenie prostego formularza wysyłającego zdjęcia na serwer wraz z zapisaniem lokalizacji zdjęcia w bazie danych.

Najpierw wygląd formularza wysyłającego:

upload.php
<h1>Upload zdjęcia do galerii</h1>
<form action="upload.php?plik=dodaj" method="post" enctype="multipart/form-data"  name="form1">
<input name="plik" type="file" size="50"/>
<input name="max_file_size" type="hidden" value="2048576" />
<input value="Wyślij zdjęcie" type="submit" />
</form>

W formularzu wprowadziłem ograniczenie wielkości pliku do 1MB.
Teraz pora na kod przetwarzający dane z formularza i zapisujący wstępne dane do bazy MySQL:

< ?php
    if(isset($_GET['plik']) && $_GET['plik']=='dodaj')
	{
		$p_pojemnosc=$_FILES['plik']['size'];
		$p_typ=$_FILES['plik']['type'];
		if( strpos( $p_typ, 'image/jpeg' ) === false )
   			die( 'Wybrany plik nie plikiem jpg.' );
		$p_nazwa=$_FILES['plik']['name'];
		$p_smiec=$_FILES['plik']['tmp_name'];
 
		$p_nazwa = strtolower($p_nazwa);
		$p_nazwa = str_replace("ż","z",$p_nazwa);
		$p_nazwa = str_replace("ą","a",$p_nazwa);
		$p_nazwa = str_replace(" ","",$p_nazwa);
		$p_nazwa = str_replace("_","",$p_nazwa);
		$p_nazwa = str_replace("ś","s",$p_nazwa);
		$p_nazwa = str_replace("ł","l",$p_nazwa);
		$p_nazwa = str_replace("ó","o",$p_nazwa);
		$p_nazwa = str_replace("ń","n",$p_nazwa);
		$p_nazwa = str_replace("ź","z",$p_nazwa);
		$p_nazwa = str_replace("ć","c",$p_nazwa);
		$p_nazwa = str_replace("ę","e",$p_nazwa);
 
		$sprawdzenia = substr($p_nazwa, strrpos($p_nazwa, "."));
 
		$p_roz= array_pop(explode(".", $p_nazwa));
 
		$max_size=round(($_POST['max_file_size']/2048576),3)."MB";
 
		$poj_MB=round(($p_pojemnosc/2048576),2).'MB'; 
 
		$p_nazwa_zm=(md5($p_nazwa)).".".$p_roz;
		$folder="img/";
 
		if ($p_pojemnosc <= 0)
		{
			echo ("Plik jest pusty. Nie mogę go przesłać <b>".$p_nazwa." ".$poj_MB.$f_koniec."");
			echo "Wracaj ...";
			exit;
		}
		if ($poj_MB > $max_size)
		{
			echo("Plik jest za duży. Maksymalnie można wysłać <b>".$max_size.$f_koniec."</b>"." .Plik wysyłany ma rozmiar <b><i>".$poj_MB.$f_koniec."</i></b>");
			echo "Wracaj ...";
			exit;
		}
		if (file_exists($folder.$p_nazwa_zm))
		{
			echo ("Plik o takiej nazwie jest już na serwerku <b><i>".$p_nazwa_zm."</i></b>");
			echo "Wracaj ...";
			exit;
		}
		else
		{
			if(!move_uploaded_file($p_smiec, $folder.$p_nazwa_zm))
				exit('Nie można zachować pliku. Prawdopodobnie nie ma folderu lub nie można w nim zapisać');
 
			echo "Przesłanie udało się - <b>".$p_nazwa."</b>"." ".$poj_MB."";
			$path_file=$folder.$p_nazwa_zm;
			require 'db.php';
			$query = "INSERT INTO galeria (link_zdjecie) VALUES ('$path_file')";
			$zapytanie = mysql_query($query);
			if(!$zapytanie)
            {
                echo "Wykonanie zapytania zawiodło. " . mysql_error();
            }
            else
            {
                echo 'Dodaj informacje o pliku';
            }
		}
	}

W powyższym kodzie PHP ma miejsce zamiany znaków diaktrycznych polskich na ich angielskie zamienniki, a także sprawdzenie czy plik nie jest za duży, czy zdjęcie jest w rozszerzeniem jpg oraz czy już przypadkiem nie istnieje zdjęcie o tej samej nazwie w folderze docelowym. Dodatkowo następuje szyfrowanie nazwy za pomocą MD5.
Po zakończeniu operacji dodawania zdjęcia do galerii wyświetla się komunikat, że można przejść do opisu zdjęcia.

Oto kod wyświetlający stronę z polami do opisu zdjęcia:

upload.php
 
if(isset($_GET['plik']) && $_GET['plik']=='opisz')
	{
		echo '
<form method="post" action="upload.php?plik=dodajopis">
			<label for="nazwa_zdjecie">Tytuł zdjęcia: </label>
<input type="text" name="nazwa_zdjecie" id="nazwa_zdjecie"/>
			<label for="opis_zdjecie">Opis zdjęcia: </label>
			<textarea id="opis_zdjecie" name="opis_zdjecie" cols="50" rows="5"></textarea>
<input value="Dodaj opis" type="submit" />
    	</form>
 
';
	}

Jest to po prostu wywołanie formularza za pomocą PHP. Kod przetwarzający dane z tego formularza wygląda następująco:

upload.php
 
if(isset($_GET['plik']) && $_GET['plik']=='dodajopis')
{
	require 'db.php';
	$nazwa=$_POST['nazwa_zdjecie'];
	if(!empty($_POST['opis_zdjecie']))
	{
		$opis=$_POST['opis_zdjecie'];
	}
	else
	{
		$opis='Brak opisu';
	}
	if(empty($nazwa) || empty($opis))
	{
		echo "Musisz wypełnić wszystkie pola";
		exit;
	}
	$query="SELECT id_zdjecie, link_zdjecie FROM galeria ORDER BY id_zdjecie DESC LIMIT 1";
	$wynik = mysql_query($query) or die(mysql_error());
	if(!$wynik)
	{
		echo "Zapytanie nieudane. Nie można pobrać id zdjęcia. " . mysqli_error();
	}
	else
	{
		$row = mysql_fetch_object($wynik);
		$id_zdjecie = $row->id_zdjecie;
		$path_file = $row->link_zdjecie;
		$sql = "UPDATE galeria SET nazwa_zdjecie='$nazwa', opis_zdjecie='$opis' WHERE id_zdjecie='$id_zdjecie'";
		$zapytanie = mysql_query($sql);
		if(!$zapytanie)
		{
			echo "Wykonanie zapytania zawiodło. Nie można dodać informacji o filmie. " . mysqli_error();
		}
		else
		{
			echo "Udało się dodać informacje o zdjęciu.Tytuł: ".$nazwa."Opis: ".$opis."";
			echo '<img src="'.$path_file.'" width="320" class="demo" alt="" />';
		}
	}
}

Powyższy kod dodaje opis do zdjęcia, które przed chwilą zostało zapisane w bazie danych.

Na koniec jako potwierdzenie zapisu zostaje wywołany opis z bazy danych oraz zdjęcie, które zostało właśnie wstawione.
Ten mechanizm uploadu nie jest jakiś specjalnie zaawansowany, nie ma też zabezpieczeń przed atakami ze strony hakerów. Przykład ten ma tylko pokazać jak zbudować taki mechanizm, a od Twoich chęci będzie zależała kwestia bezpieczeństwa takiego formularza.

Etap czwarty - pobieranie danych do galerii

Teraz pora na stworzenie naszej galerii. Na początek musimy przygotować plik zczytujący dane z bazy danych i przetwarzający je na dane wejściowe do AJAXa.
Wygląda on tak:

json.php
 
require 'db.php';
$query = "SELECT id_zdjecie, nazwa_zdjecie, opis_zdjecie, link_zdjecie FROM galeria ORDER BY Rand() LIMIT 4";
$result = mysql_query($query) or die(mysql_error($mysqli));
if ($result) {
	echo "
<ul id='galeria'>";
	while ($row = mysql_fetch_object($result)) {
		$nazwa = $row->nazwa_zdjecie;
		$opis = $row->opis_zdjecie;
		$link = $row->link_zdjecie;
		$id = $row->id_zdjecie;
		echo "
<li>
<h4>$nazwa</h4>
 
$opis
</li>
 
 n";
	}
	echo "</ul>
 
";
}

Ma tutaj miejsce odczytywanie danych z bazy. Dodatkowo w zapytaniu MySQL jest funckaj Rand() która losowo wybiera 4 wiersze z bazy.

Etap piąty - wyświetlanie zdjęć w galerii

Takie dane przesyłamy do pliku index.php, gdzie znajduje się kod wyświetlający naszą galerię.

index.php
<h2>[PHP][MySQL][AJAX] Galeria zdjęć ze zmieniającymi się zdjęciami
    demo by Piotr Nalepa</h2>
<div id="box">
<div id="galeria">
        </div>
</div>

Pewnie się teraz dziwisz, a gdzie tu jest AJAX? Heh, AJAX pojawia się w sekcji naszej strony i wygląda on tak:

function odswiezZdjecia() {
	   $("#galeria").fadeOut(750, function() {
			$("#galeria").empty
			$("#galeria").load("json.php", function() {
				$("#galeria").fadeIn();
			});
		});
	};
	$(function(){
		odswiezZdjecia();
		var int = setInterval("odswiezZdjecia()", 6500);
	});

Dodatkowo należy pamiętać, że trzeba dołączyć bibliotekę jQuery do kodu pliku index.php, bo inaczej galeria nie będzie działać.
Na koniec przedstawię Ci jak wyglądają style dla takiej galerii:

img.demo {
	margin: 5px;
	border-top: 5px #fff solid;
	border-right: 5px #fff solid;
	border-left: 5px #fff solid;
	border-bottom: 50px #fff solid;
}
#galeria {
	margin-top: 0px;
	margin-right: auto;
	margin-bottom: 0px;
	margin-left: auto;
	padding: 10px;
	height: 100%;
}
#box {
	width: 620px;
	height: 200px;
	background-color: #333333;
	margin: 0 auto;
	padding-top: 20px;
	padding-right: 0px;
	padding-bottom: 20px;
	padding-left: 0px;
	border: 1px solid #999999;
}
#box ul {
	list-style: none;
	padding: 0px;
	margin: 0px;
}
#box li {
	display: block;
	float: left;
	width: 138px;
	text-align: center;
	overflow: hidden;
	margin: 0px;
	padding-top: 10px;
	padding-right: 5px;
	padding-bottom: 10px;
	padding-left: 5px;
}
#box li:hover {
	background-color: #666666;
	cursor:pointer;
}
#galeria h4 {
	padding: 0px;
	margin-top: 5px;
	margin-right: 0px;
	margin-bottom: 5px;
	margin-left: 0px;
	color: #FFFFFF;
	font-size: 11px;
}
#galeria img {
	border: 1px solid #FFFFFF;
	margin: 0px;
	padding: 0px;
	width: 125px;
	height: auto;
}
#galeria p {
	font-size: 11px;
	margin: 0px;
	padding: 5px;
	color: #999999;
	font-weight: bold;
}

Demo z tego artykułu jest dostępne tutaj: Galeria obrazków z użyciem AJAXa.

  • Właściwie bawię się php ale jquery nawet nie liznąłem. Szukałem ciekawej galerii i ta mi się bardzo podoba ale niestety nie kumam gdzie i jakie biblioteki dodać i jak je wyegzekwować. Proszę o wyrozumiałość.

  • Tomek

    Czy jest moze juz rozwiązanie problemu z wyświetlaniem w IE tych samych zdjęć. Zdaje się, że IE zapamiętuje plik json.php i nie czyta go ponownie. Czy można czyms wymusić na IE ponowne odczytanie tego pliku?

  • Tomek

    Tutaj jest opisane rozwiazanie ale nie potrafie go wykorzystac w powyzszymm skrypcie. Jesli udaloby by sie to prosze o kontakt na maila

    http://stackoverflow.com/questions/1061525/jquerys-load-not-working-in-ie-but-fine-in-firefox-chrome-and-safari

  • Mariusz

    Tak przy okazji w json.php nie jest przypisana zmienna $title 🙂

  • Piotr Nalepa

    ostatnio zmodyfikowałem nieco ten skrypt i w najbliższym czasie będzie jego aktualizacja 🙂

  • witam mam taki błąd i nie mogę go usuna a wszystko wpisywalem dokladnie.
    Warning: mysql_query() [function.mysql-query]: Access denied for user ‚root’@’62.146.68.219’ (using password: NO) in /srv/home/tpm10081/public_html/alert/galeria/upload.php on line 68

    Warning: mysql_query() [function.mysql-query]: A link to the server could not be established in /srv/home/tpm10081/public_html/alert/galeria/upload.php on line 68
    Wykonanie zapytania zawiodło. Access denied for user ‚root’@’62.146.68.219’ (using password: NO)

  • Piotr Nalepa

    Wygląda na to, że dane dostępu do serwera zostały źle podane. Należy wprowadzić poprawne i problem zniknie.

  • Właśnie o to chodzi ze sa poprawne 🙁

  • Piotr Nalepa

    Skoro jest brak dostępu do serwera, to musi być coś źle z danymi dostępowymi. Proszę się upewnić.

  • Shadow

    a ten cały kod trzeba wrzucić do upload.php razem z kodem przetwarzającym dane?

  • Wiem w czym byl blad w moim przypadku.
    w pliku upload.php
    zamiast:
    $mysqli = new MySQLi($dbhost, $dbuser, $dbpass, $dbname) or die(mysqli_error());

    musialem zamienic na:
    $mysqli = mysql_connect(‚localhost’,’tpm10081_paciak2′,’paciaki2′)
            or die(‚Nieudane połączenie z bazą danych…’);
    mysql_select_db(‚tpm10081_new’)
            or die(‚Nie udało się wybrać bazy danych…’);

    i dopiero zadziałało.
    Dlaczego?

  • michl

    znaki diaktryczne polskie zastepuje sie 2linijkami kodu w php?
    skad pomysl na taki sposob … jest raczej malo optymalny