DBanaszewski | 2019-08-20 07:20:25 UTC | #1
Kiedyś programiści pragnący komunikować się z bazą danych poprzez PHP musieli zmagać się z wieloma problemami. Każdy serwer DB udostępniał inne API do komunikacji, które zostały na nasze nieszczęście wiernie odtworzone w interpreterze. Jeżeli ktoś chciał napisać elastyczny projekt do uruchamiania na kilku bazach, musiał pisać samodzielnie odpowiednie nakładki, które wybiorą odpowiednią funkcję w zależności od tego, czym się łączymy. Pozostawały też różne gotowe skrypty robiące to zadanie za nas.
PDO to skrót od PHP Data Objects. Jest to nowoczesny interfejs języka PHP przeznaczony do komunikacji z bazami danych, po raz pierwszy napisany wyłącznie w OOP. Jego najważniejszą zaletą jest to, że możemy za jego pomocą łączyć się zarówno z bazą danych MySQL, jak i z bazą danych PostgreSQL (o innych systemach DB nie wspominając). Wersji beta PDO można było używać już w PHP 5.0, natomiast stabilna wersja pojawiła się wraz z PHP 5.1. Gorąco zachęcamy do jego stosowania, gdyż nie tylko jest wygodniejszy od starych rozwiązań, ale też szybszy i bezpieczniejszy.
Tyle słowa wstępu, do dzieła!
7
)MySQL
(np. MariaDB
)pdo_mysql
Przydałby się również phpMyAdmin ;)
Tekst zapisany w taki sposób:
<?php
//komentarz
?>
jest komentarzem i nie musi znajdować się w kodzie.
Tworzymy pliki o nazwach: database.php
, config.php
, script.php
i index.php
.
Możemy je edytować w przeznaczonym do tego celu programie np. PHPStorm
albo w zwykłym edytorze tekstu - np. Notepad++
.
Teraz edytujemy plik config.php
.
Konfiguracja będzie tutaj prostą rzeczą. Musimy utworzyć tablicę, czyli:
<?php
$config = array(
//Adres połączenia do bazy danych
"hostname" => "mysql.mojadomena.pl",
//Port połączenia do bazy danych (standardowy to 3306).
"port" => 3306,
//Nazwa użytkownika bazy danych
"username" => "root",
//Hasło użytkownika bazy danych
"password" => "abcdefghijk123!@#",
//Nazwa tabeli
"table_name" => "test"
);
Zauważ, że nie ma znacznika zamykającego, czyli ?>
.
Dlaczego? Jeżeli plik zawiera tylko kod PHP to nie jest wymagane dodawanie znacznika kończącego.
Przed zapisaniem uprawniamy się, czy wpisane dane do tablicy są prawidłowe. Jeżeli tak to zapisujemy i jedziemy dalej!
Edytujemy plik database.php
.
Musimy załączyć plik config.php
, aby PHP mogło się połączyć z bazą danych.
Robimy to tak:
<?php
require_once("config.php");
?>
Plik został załączony, idziemy dalej.
Następnie tworzymy wyłapywanie wyjątków, czyli:
<?php
require_once("config.php");
try {
}
catch (PDOException $error) {
}
?>
Okej, mamy to już za sobą. Jest to potrzebne, jeżeli podczas połączenia wystąpi jakiś błąd (np. literówka w haśle).
Teraz musimy otworzyć połączenie z bazą danych, czyli:
<?php
require_once("config.php");
try {
$database = new PDO("mysql:host=".$config["hostname"].";port=".intval($config["port"]).";dbname=".$config["table_name"].";charset=utf8", $config["username"], $config["password"], [
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
]);
}
catch (PDOException $error) {
exit("Błąd połączenia z bazą danych!");
}
?>
Gotowe. Możesz zauważyć, że użyłem funkcji exit()
. Zostanie ona wykonana, jeżeli połączenie z bazą się nie uda, a co idzie dalej, skrypt zatrzyma się i nic dalej nie wykona wypluwając na ekran komunikat Błąd połączenia z bazą danych!
.
Lecimy dalej!
Teraz edytujemy plik index.php
.
Jest to strona główna, więc użyjemy tutaj trochę HTMLa.
Chcemy, aby dane ze skryptu pobierającego dane pokazały się pod formularzem, więc musimy aktywować sesje, których będziemy używać.
Musimy uruchomić system sesji przy pomocy jednej linijki kodu:
<?php
session_start();
?>
I sesje zostały uruchomione.
W tym poradniku chcemy zrobić formularz, który umożliwi nam odczytanie danych użytkownika z bazy.
Ty możesz sam zrobić co chcesz, tutaj jest tylko przykład.
Kod HTML:
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Sprawdzanie użytkownika</title>
</head>
<body>
<header>
<h1>Sprawdzanie użytkownika</h1>
</header>
<main>
<article>
<form method="post" action="script.php">
<label>Nazwa użytkownika <input type="text" name="username"></label>
<input type="submit" value="Sprawdź!">
</form>
</article>
</main>
</body>
</html>
Owy kod umieszczamy pod kodem PHP, czyli tak powinno to wyglądać (tutaj bez kolorków, bo mix kodów):
<?php
session_start();
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Sprawdzanie użytkownika</title>
</head>
<body>
<header>
<h1>Sprawdzanie użytkownika</h1>
</header>
<main>
<article>
<form method="post" action="script.php">
<label>Nazwa użytkownika <input type="text" name="username"></label>
<input type="submit" value="Sprawdź!">
</form>
</article>
</main>
</body>
</html>
Super! Formularz mamy gotowy!
Teraz przydałoby się wyświetlać nam dane z bazy poniżej formularza. Jest to wstęp do kroku 5.
Pomiędzy znacznikiem </form>
a </article>
umieścimy kod PHP, który będzie odpowiadał za wyświetlanie danych z bazy, które zostaną wcześniej umieszczone w sesji przez inny skrypt.
Oto on:
<?php
if (isset($_SESSION["user_unknown"])) {
echo '<p style="color:red;">Użytkownik nie został odnaleziony!</p>';
unset($_SESSION["user_unknown"]);
}
if (isset($_SESSION["user_known"])) {
echo '<p style="color:green;">Użytkownik został odnaleziony!</p>';
echo '<p>Nazwa użytkownika: <b>'.$_SESSION["username"].'</b><br>';
echo 'Numer identyfikacyjny: <b>'.$_SESSION["idnum"].'</b><br>';
echo 'Adres e-mail: <b>'.$_SESSION["email"].'</b><br>';
echo 'Data rejestracji: <b>'.$_SESSION["regdate"].'</b></p>';
unset($_SEaSSION["user_known"]);
unset($_SESSION["username"]);
unset($_SESSION["idnum"]);
unset($_SESSION["email"]);
unset($_SESSION["regdate"]);
}
?>
A jak to teraz powinno wyglądać (znowu bez kolorków, bo mix :frowning:) :
<?php
session_start();
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Sprawdzanie użytkownika</title>
</head>
<body>
<header>
<h1>Sprawdzanie użytkownika</h1>
</header>
<main>
<article>
<form method="post" action="script.php">
<label>Nazwa użytkownika <input type="text" name="username"></label>
<input type="submit" value="Sprawdź!">
<?php
if (isset($_SESSION["user_unknown"])) {
echo '<p style="color:red;">Użytkownik nie został odnaleziony!</p>';
unset($_SESSION["user_unknown"]);
}
if (isset($_SESSION["user_known"])) {
echo '<p style="color:green;">Użytkownik został odnaleziony!</p>';
echo '<p>Nazwa użytkownika: <b>'.$_SESSION["username"].'</b><br>';
echo 'Numer identyfikacyjny: <b>'.$_SESSION["idnum"].'</b><br>';
echo 'Adres e-mail: <b>'.$_SESSION["email"].'</b><br>';
echo 'Data rejestracji: <b>'.$_SESSION["regdate"].'</b></p>';
unset($_SESSION["user_known"]);
unset($_SESSION["username"]);
unset($_SESSION["idnum"]);
unset($_SESSION["email"]);
unset($_SESSION["regdate"]);
}
?>
</form>
</article>
</main>
</body>
</html>
Okej, index.php
możemy zapisać, jest gotowy.
Teraz przydałoby się odczytać te dane, bo jak na razie to tylko nam coś będzie pokazywać, ale na pewno nie dane z bazy :stuckouttongue:
Teraz edytujemy plik script.php
.
Formularz gotowy, teraz backend, czyli strona niewidoczna dla zwykłego użytkownika.
W poprzednim kroku uruchomiliśmy sesje. Tutaj też musimy :slight_smile:
<?php
session_start();
I sesje już uruchomione.
Musimy jeszcze załączyć plik bazy danych, bez którego ten skrypt nie będzie działał.
Robimy to w podobny sposób co do pliku config.php
, czyli:
<?php
require_once("database.php");
Teraz musimy odczytać dane wysłane z formularza.
Dane są wysyłane przy pomocy metody POST (więcej informacji), więc musimy je teraz odebrać. Następnie, dane zostaną zapisane w jednej zmiennej, bo przesyłamy tylko nazwę użytkownika. Przydałyby się również zapytania SQL, które przekażą nam dane z bazy danych do PHP. Musimy również wziąć pod uwagę, że dany użytkownik nie istnieje. Zastosujemy tutaj instrukcję if
i else
. Po udanym odczycie danych z bazy zostaną one umieszczone w sesji. Strona główna je odczyta i pokaże. Dla świętego spokoju dane w sesji zostaną usunięte, aby zwolnić pamięć RAM (i zatrzymać wycinkę lasów deszczowych). Nie będę się rozpisywał, przeanalizuj cały kod :stuckouttongue:
<?php
session_start();
//Bez tego nic nie pójdzie :P
require_once("database.php");
if (isset($_POST["username"])) {
$username = filter_input(INPUT_POST, "username");
$query = $database->prepare("SELECT * FROM users WHERE username = :username");
$query->bindValue(':username', $username, PDO::PARAM_STR);
$query->execute();
if (intval($query->rowCount()) == 1) {
$user = $query->fetch();
$_SESSION["user_known"] = true;
$_SESSION["username"] = $user["username"];
$_SESSION["idnum"] = $user["idnum"];
$_SESSION["email"] = $user["email"];
$_SESSION["regdate"] = $user["regdate"];
header("Location: index.php");
exit();
} else {
$_SESSION["user_unknown"] = true;
header("Location: index.php");
exit();
}
} else {
$_SESSION["user_unknown"] = true;
header("Location: index.php");
exit();
}
Zapisz ten plik i gotowe.
Tak naprawdę ten krok jest nadobowiązkowy, ale trzeba go dopisać.
Pusta baza danych = skrypt będzie zawsze odpowiadał, że taki gracz nie istnieje.
Tutaj przygotowałem dla Ciebie skrypt SQL, który możesz wykonać na serwerze MySQL poprzez panel phpMyAdmin. Owy skrypt zawiera kilka wpisów z danymi (oczywiście wymyślone).
CREATE TABLE `users` ( `idnum` INT NOT NULL AUTO_INCREMENT , `username` TEXT NOT NULL , `email` TEXT NOT NULL , `regdate` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP , PRIMARY KEY (`idnum`)) ENGINE = InnoDB;
INSERT INTO `users` (`idnum`, `username`, `email`, `regdate`) VALUES (NULL, 'Maur123', '[email protected]', CURRENT_TIMESTAMP), (NULL, 'Dawid', '[email protected]', CURRENT_TIMESTAMP), (NULL, 'Tadek', '[email protected]', CURRENT_TIMESTAMP), (NULL, 'Andrzej', '[email protected]', CURRENT_TIMESTAMP), (NULL, 'Jarek1', '[email protected]', CURRENT_TIMESTAMP);
Github: https://github.com/DBanaszewski/PHP-Poradnik-1
Link do kodu: https://s1.dbanaszewski.pl/poradnik-1/php-1.zip
Skan (dla spokoju): link
Strona testowa: https://s1.dbanaszewski.pl/poradnik-1/
Dane do testowania, czyli nazwa użytkownika, są zawarte w skrypcie SQL (jest wyżej). Proszę wytężyć umysł i wyczytać chociaż jedną nazwę :slight_smile:
Źródło: Wikibooks
Błędy lub sugestie proszę pisać poniżej lub na PM.
kacper | 2018-06-30 20:40:26 UTC | #2
[quote=”DBanaszewski, post:1, topic:7211”]
Link do kodu: https://s1.dbanaszewski.pl/poradnik-1/php-1.zip
[/quote]
Mógłbyś wrzucić kod na GitLaba? Boje się że pobiore wirusa :frowning:
DBanaszewski | 2018-06-30 20:48:08 UTC | #4
Wrzuciłem na Githuba ;)
kacper | 2018-06-30 20:51:08 UTC | #5
Dzięki :D
anon10657637 | 2018-07-01 23:09:15 UTC | #6
Czy ja tam widzę printowanie kodu błędu do end-usera czy mi się przewidziało?
Nieznajomy11 | 2018-07-02 12:44:58 UTC | #7
Hehe, dobrze widzisz. Do dzisiaj pamiętam jak przez przypadek wywołałem błąd z bazą na kiciusiach jak były odpalone “w trybie beta” (rakportal) i moim oczom szybko ukazało się hasło do mysql wraz z adresem. :smile:
DBanaszewski | 2018-07-02 12:54:43 UTC | #8
@anon10657637 - naprawię ten błąd bezpieczeństwa.
Dlaczego tak zrobiłem? A otóż dla ułatwienia - błąd + powód.
Wkrótce łatka zostanie opublikowana.
Pantoflarz | 2018-07-02 20:10:01 UTC | #9
ogólnie to i tak polecam korzystanie z frameworka, który komunikację z bazą ma wbudowaną, wszystko jest sprawdzane i zabezpieczane na bieżąco pod względem bezpieczeństwa itp. itd. przez autorów czy community.
wiadomo, że require’owanie pliku database.php w każdym pliku gdzie łączymy się z bazą też optymalne nie jest, no ale przestane już narzekać, bo wiadomo, od czegoś trzeba zaczynać :stuckouttongue: