MC, 13:50 sobota, 07.07.2012 r.
Ilustracja do artykułu: PHP i MySQL - Rozwiązanie: Access denied for user 'www-data'@'localhost' (using password: NO)

PHP i MySQL - Rozwiązanie: Access denied for user 'www-data'@'localhost' (using password: NO)

W PHP piszę rzadko i ma to swoje objawy w robieniu prostych błędów. Ten akurat dotyczył połączenia z bazą danych MySQL. Jeżeli również zamiast nawiązać połączenie otrzymujesz komunikat: Access denied for user 'www-data'@'localhost' (using password: NO), to zapraszam do dalszej lektury.

Co powoduje ten problem?

Już na pierwszy rzut oka widać, że zachodzi jakaś dziwna rzecz skoro z komunikatu wynika, że próbowaliśmy połączyć się z bazą przy pomocy loginu "www-data" oraz bez hasła. No... chyba, że akurat właśnie tak było, ale wątpliwe. Otóż są to domyślne parametry połączenia z bazą danych, które są wpisane w konfigurację PHP i zostaną one użyte, gdy do funkcji mysql_connect() zostaną przekazane puste parametry. Gdyby wpisać je literalnie, np. w ten sposób:
mysql_connect("localhost", "mojUzytkownik", "mojeHaslo");
powyższy problem na pewno by nie wystąpił. Dlatego jestem niemal pewien, że skoro tutaj trafiłeś/aś, to podobnie do mnie przekazywałaś te parametry pod postacią zmiennych:
mysql_connect($host, $uzytkownik, $haslo);

Dobrze, ale dlaczego zmienne nie posiadają wartości?

Scenariusze mogę być różne i należałoby sprawę prześledzić, czy aby po drodze coś się nie dzieje, że przekazywane wartości zmiennych są wyczyszczone. Od siebie chciałbym pokazać bardzo popularną sytuację, która taki problem może powodować. Spójrzmy na kod:
$host = "localhost";
$uzytkownik = "mojUzytkownik";
$haslo = "mojeHaslo";

function Polacz()
{
$polaczenie = mysql_connect($host, $uzytkownik, $haslo)
or die ("Połączenie nie zostało nawiązane! (". mysql_error() .")");
}

Widać tutaj, że mamy zmienne, które chcemy by miały zasięg globalny oraz funkcję, w której wykorzystujemy te zmienne w próbie nawiązania połączenia z bazą danych MySQL. Jeżeli u Ciebie kod wygląda podobnie, to już wiemy co jest przyczyną.

Co jest nie tak?

Problem w powyższym przykładzie polega na tym, że zmienne zdefiniowane poza funkcją nie mają zasięgu globalnego i wewnątrz funkcji, parser traktuje je jako zmienne lokalne nie posiadające żadnej wartości! Stąd problem "Access denied for user 'www-data'@'localhost' (using password: NO)". Niestety, jest to elementarna wiedza o programowaniu w PHP, której mi zabrakło.

Jak używa się zmiennych globalnych w PHP?

Aby rozwiązać zajmujący nas problem, należy uczyć odpowiednie zmienne zmiennymi globalnymi. I tutaj PHP ma pewną osobliwość. Istnieje dyrektywa global, więc można przypuszczać, że poniższy zabieg będzie prawidłowy:
global $host = "localhost";
global $uzytkownik = "mojUzytkownik";
global $haslo = "mojeHaslo";

function Polacz()
{
$polaczenie = mysql_connect($host, $uzytkownik, $haslo)
or die ("Połączenie nie zostało nawiązane! (". mysql_error() .")");
}
Jednak absolutnie nie! W PHP dyrektywy global nie używa się po to by wskazać, że dana zmienna ma mieć zasięg globalny, tylko by wskazać np. wewnątrz funkcji, że zmienna której chcemy użyć, jest zmienną globalną! Zatem moje wcześniejsze stwierdzenia mówiące o tym, że zmienne przez nas zdefiniowane nie miały zasięgu globalnego, nie są do końca poprawne. One miały zasięg globalny, tylko wnętrze naszej funkcji nic na ten temat nie wiedziało. Poprawnym rozwiązaniem jest więc:
$host = "localhost";
$uzytkownik = "mojUzytkownik";
$haslo = "mojeHaslo";

function Polacz()
{
global $host, $uzytkownik, $haslo;

$polaczenie = mysql_connect($host, $uzytkownik, $haslo)
or die ("Połączenie nie zostało nawiązane! (". mysql_error() .")");
}

Artykuł z kategorii tych wstydliwych, bo obnażających niewiedzę, ale mam nadzieję, że komuś oszczędzi czasu i łez.

Komentarze (0) - Nikt jeszcze nie komentował - bądź pierwszy!

Imię:
Treść: