Jak funguje PHP
PHP je skriptovací jazyk server-side, který se ve valné většině používá pro tvorbu dynamických webových stránek.
Zpracování webu probíhá na straně serveru, proto také „server-side“. Komunikace vypadá následovně.
- Návštěvník odesílá požadavek na webserver (např. nginx nebo Apache2), kde je zprovozněné PHP.
- Webserver přijímá požadavek.
- Zjistí, zda je požadavek na PHP soubor nebo jiný (např. CSS nebo JS, které není třeba nijak interpretovat)
- Pokud se jedná o požadavek na PHP skript, předává webserver zpracování PHP interpreteru.
- PHP interpreter požadavek kompletně zpracuje a posílá jej zpátky (typicky ve formě HTML stránky)
- Návštěvníkovi se po přijetí odpovědi obnoví stránka (tzv. refresh stránky)
PHP a AJAX
Cílem tohoto článku je ukázat, jak lze velice jednoduše vytvořit odesílaní požadavku na pozadí tak, aby právě nedocházelo ke zbytečným načítáním stránky (refreshům) – tedy bod č. 6. Webovým stránkám, aplikacím nebo eshopům se tak zvýší uživatelská přívětivost a napodobí se tak funkcionalita aplikací běžně instalovaných do operačního sytému.
Abychom toho však docílili budeme potřebovat ještě pomoc jazyka Javascript, který dokáže vyvolávat právě požadavky, které se pak odesílají na webserver s PHP.
Příklad č.1 – Generování náhodného čísla bez obnovení stránky
Pro jednoduchost jsem zvolil příklad vygenerování náhodného čísla, které by však samo o sobě zvládal i sám Javascript bez nutnosti PHP.
Vytvoříme si adresář s projektem např. php-ajax1.
Soubor index.php
V něm pak soubor index.php se základní HTML5 kostrou a do body napíšeme
<h1>PHP, AJAX a náhodně generované číslo</h1>
<p>Toto je soubor <strong>index.php</strong></p>
<div id="result" style="border: 1px solid"></div>
<a href="number.php" id="generate-button">Generuj číslo</a>
Soubor number.php
Následně vytvoříme soubor number.php, který bude generovat náhodné číslo a bude vypisovat i čas, kdy k tomu došlo.
<?php
$number = rand(1, 100);
$currentTime = (new DateTime())->format('H:i:s');
?>
<p>Toto je zpráva ze souboru <strong>number.php</strong></p>
<p>V čase <?= $currentTime ?> bylo vygenerováno číslo <?= $number ?></p>
Nudný výsledek bez AJAXu
V tuto chvíli máme index.php s odkazem, na který když klikneme, tak jsme odkázáni na soubor number.php. To chceme ale změnit tak, aby došlo k částečnému obnovení a zobrazení odpovědi ze souboru number.php přímo při zobrazování index.php, aniž by došlo ke kompletnímu obnovení stránky.
Asynchronní volání pomocí Javascriptu a funkce fetch.
Do souboru index.php si přidáme před koncovou značku </body> následující Javascript.
<script>
const result = document.getElementById('result');
const generateButton = document.getElementById('generate-button');
const URL = generateButton.getAttribute('href');
generateButton.addEventListener('click', (e) => {
e.preventDefault(); // zablokouje přesměrování na stránku number.php
fetch(URL)
.then(response => response.text())
.then(numberPHPContent => result.innerHTML = numberPHPContent);
});
</script>
result – je element div, kde se bude zobrazovat vše, co vypsal soubor number.php na pozadí.
generateButton – je element a (anchor-odkaz), který po
URL – z elementu generateButton si zjistím hodnotu atributu href
e.preventDefault() – zastaví vykonávání výchozí události – v tomto případě přesměrování na number.php
funkce fetch pošle požadavek na URL, potom (then) převede odpověď (response) na text (response.text) a potom (then) zobrazí tento text do div#result.
Příklad č. 2 – Odesílání formuláře bez obnovení stránky a využití JSON
JSON – JavaScript Object Notation si lze představit jako speciálně upravený strukturovaný text.
{"firstname":"Martin","lastname":"Kokeš","age":"35"}
V našem příkladu lze využít formát JSON pro zjednodušenou práci se vstupními daty. Nemusíme pak otrocky načítat, každé vstupní políčko formuláře zvlášť, ale pracovat s odesílanými daty hromadně a to i v PHP.
Založení nového projektu s index.php
Vytvoříme si nový projekt a v něm index.php, do kterého vložíme HTML formulář
<h1>Evidence zaměstnanců</h1>
<form action="submit.php" id="my-form" method="post">
<label for="input-firstname">Jméno:</label>
<input type="text" name="firstname" id="input-firstname">
<br>
<label for="input-lastname">Příjmení:</label>
<input type="text" name="lastname" id="input-lastname">
<br>
<label for="input-age">Věk:</label>
<input type="number" name="age" id="input-age">
<br>
<input type="submit" name="submit" value="Vložit">
</form>
Soubor scripts.js
<script>
const form = document.getElementById('my-form');
const submit = document.getElementById("submit");
const URL = form.getAttribute('action');
submit.addEventListener('click', (e) => {
const firstname = document.getElementById("input-firstname").value;
const lastname = document.getElementById("input-lastname").value;
const age = document.getElementById("input-age").value;
e.preventDefault(); // zablokouje přesměrování na stránku number.php
fetch(URL, {method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({firstname, lastname, age})})
.then(response => response.text())
.then(response => document.getElementById("result").innerHTML = response);
});
</script>
V index.php si nalinkujeme <script src=“script.js“></script>
Soubor submit.php ukládající vstupní data do souboru employees.txt
<?php
$contentType = isset($_SERVER["CONTENT_TYPE"]) ? trim($_SERVER["CONTENT_TYPE"]) : '';
if($contentType === "application/json") {
$content = trim(file_get_contents("php://input"));
$decoded = json_decode($content, true);
if(!is_array($decoded)) { ?>
<h1>ERROR</h1>
<?php
} else {
file_put_contents("employees.txt", $content . "\n", FILE_APPEND);
?><p>Zaměstnanec <?= $decoded["firstname"] . ' ' . $decoded["lastname"] ?> byl úspěšně zapsán do souboru employees.txt</p>
<?php
}
}
?>
Děkuji za pomoc s dotažením článku Vítkovi Fenclovi.