Webprogramozás
Horváth Győző
egyetemi docens
horvath.gyozo@inf.elte.hu
1117 Budapest, Pázmány Péter sétány 1/c., 4.725
Dinamikus szerveroldali webprogramozás: program állítja elő a tartalmat (HTML)
<?php
// Input (?)
$tracks = [
["id" => 1, "name" => "guitar", "muted" => false],
["id" => 2, "name" => "bass", "muted" => true ],
["id" => 3, "name" => "vocal", "muted" => false],
];
// Processing
$enabledTracks = array_filter($tracks, function ($track) {
return !$track["muted"];
});
?>
<!-- Output -->
<div id="tracks">
<?php foreach($enabledTracks as $t) : ?>
<div class="track">
<?= $t["name"] ?>
</div>
<?php endforeach ?>
</div>
A program bemenetének lehetséges forrásai:
CGI
Azt határozza meg, hogy egy webszerver hogyan indíthat el egy programot és milyen módon cserél adatot vele.
REQUEST_METHOD
REMOTE_ADDRESS
CONTENT_LENGTH
HTTP_*
Accept
fejléc → HTTP_ACCEPT
környezeti
változó[REMOTE_ADDR] => 188.142.184.197
[REMOTE_PORT] => 49323
[REQUEST_METHOD] => GET
[HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
[HTTP_ACCEPT_LANGUAGE] => hu-hu,hu;q=0.8,en-US;q=0.5,en;q=0.3
Kérés URL-je (szabad paraméter: <query>
)
<scheme>://<host>:<port>/<path>?<query>#<fragment>
URL → környezeti változók (fontos: QUERY_STRING
)
<scheme>
→ SERVER_PROTOCOL
<host>
→ SERVER_NAME
<port>
→ SERVER_PORT
<path>
→
SCRIPT_NAME (PATH_INFO)
<query>
→ QUERY_STRING
CONTENT_LENGTH
: adatmennyiség hossza[HTTP_HOST] => webprogramozas.inf.elte.hu
[HTTP_USER_AGENT] => Mozilla/5.0 (Windows NT 6.1; WOW64; rv:19.0) Gecko/20100101 Firefox/19.0
[HTTP_ACCEPT] => text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
[HTTP_ACCEPT_LANGUAGE] => hu-hu,hu;q=0.8,en-US;q=0.5,en;q=0.3
[HTTP_ACCEPT_ENCODING] => gzip, deflate
[HTTP_REFERER] => http://webprogramozas.inf.elte.hu/~gyozke/wf2/temp/
[HTTP_COOKIE] => WACID=1263304129000A11327866; __utma=32143338.519822639.1361532995.1362426295.1363347264.4; __utmz=32143338.1362426295.3.3.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided)
[HTTP_CONNECTION] => keep-alive
[PATH] => /usr/sbin:/bin:/usr/bin:/sbin
[SERVER_SIGNATURE] => <address>Apache/2.2.10 (Linux/SUSE) Server at webprogramozas.inf.elte.hu Port 80</address>
[SERVER_SOFTWARE] => Apache/2.2.10 (Linux/SUSE)
[SERVER_NAME] => webprogramozas.inf.elte.hu
[SERVER_ADDR] => 157.181.161.8
[SERVER_PORT] => 80
[REMOTE_ADDR] => 188.142.184.197
[DOCUMENT_ROOT] => /srv/www/webprog
[SERVER_ADMIN] => root@webprogramozas.inf.elte.hu
[SCRIPT_FILENAME] => /home/gyozke/public_html/wf2/temp/getpost.php
[REMOTE_PORT] => 49323
[GATEWAY_INTERFACE] => CGI/1.1
[SERVER_PROTOCOL] => HTTP/1.1
[REQUEST_METHOD] => GET
[QUERY_STRING] =>
[REQUEST_URI] => /~gyozke/wf2/temp/getpost.php
[SCRIPT_NAME] => /~gyozke/wf2/temp/getpost.php
[PHP_SELF] => /~gyozke/wf2/temp/getpost.php
[REQUEST_TIME] => 1365626159
GET
)GET
)GET
, POST
)GET
, POST
, …)window.location
(GET
)submit()
metódus (GET
,
POST
)<protocol>://<host>:<port>/<path>?✒><query><✒#<fragment>
Példa
<a href="http://server.hu/index.php?✒>adat=ELTE<✒">Valami</a>
?
-et követő név-érték párok sorozata&
jellel elválasztva
foo=1&bar=2
encodeURIComponent("Tom & Jerry");
title=Tom+%26+Jerry"
GET /index.php✒>?title=Tom+%26+Jerry<✒ HTTP/1.1
Host: webprogramozas.inf.elte.hu
$_SERVER
) keresztül (CGI)
$_SERVER["QUERY_STRING"]
$_GET
szuperglobális változón keresztül
$_GET["title"]
<?php
// index.php?title=Tom+%26+Jerry
// index.php?title=
// index.php
$title = $_GET["title"] ?? "I don't know";
?>
<h1>Title: <?= $title ?></h1>
GET
)GET
)GET
,
POST
)GET
, POST
, …)window.location
(GET
)submit()
metódus (GET
,
POST
)<form>
elemaction
: szerveroldali erőforrás megjelölésemethod
: HTTP metódus (GET
vagy
POST
)enctype
: a form-adatok kódolása a küldés soránenctype
application/x-www-form-urlencoded
(alapértelmezett)multipart/form-data
(fájlfeltöltés, csak
POST
esetén)text/plain
(levélküldés)<form method="get" action="index.php">
<label for="title">
<input type="text" id="title" name="title">
<button type="submit">Send</button>
</form>
submit
gomb megnyomásaform.submit()
meghívásaname
attribútumdisabled
név=érték
párokat készít&
jellel fűzi összename=Győző&pwd=secret&check1=value1&check2=on
enctype
attribútumname=Gy%C5%91z%C5%91&pwd=secret&check1=value1&check2=on
action-url
+ ?
+
query-string
(ld. korábban)GET
/POST
HTTP kérésekGET
kérés
METÓDUS /<path>?✒><query><✒ VERZIÓ
Host: <host>
FEJLÉC: ÉRTÉK
...
POST
kérés
METÓDUS /<path>?✒><query><✒ VERZIÓ
Host: <host>
FEJLÉC: ÉRTÉK
FEJLÉC: ÉRTÉK
FEJLÉC: ÉRTÉK
✒>ÜZENETTEST<✒
Űrlap:
<form action="http://host/page.php" method="post">
<input type="text" name="foo" value="bar">
<input type="password" value="secret">
<input type="hidden" name="password" value="secret">
<input type="checkbox" name="check1" value="baz" checked>
<input type="checkbox" name="check2" checked>
<button type="submit">Submit</button>
</form>
Kérésszöveg (Query string)
foo=bar&password=secret&check1=baz&check2=on
<input>
type: text
,
password
, hidden
<textarea>
textarea
-nál vigyázni kell: minden elküldésre kerül,
ami a <textarea></textarea>
elem között
vancheckbox
, radio
value
→ on
értékselect
value
→ option
szövege az
értéksize
>1 esetén ha nincs kiválasztva → nem küldi
elmultiple
esetén → ugyanazon névvel több név=érték pár
(pl. sel[]=foo&sel[]=bar
)button
/submit
file
enctype="multipart/form-data"
method="POST"
method="get"
esetén ugyanúgy, mint a$_GET
tömbön keresztülmethod="post"
esetén a $_POST
szuperglobális$_GET
: QUERY_STRING
ben érkező név=érték
pároknak megfelelő tömb, ahol a név a kulcs.$_POST
: a standard inputon érkező név=érték pároknak
megfelelő tömb, ahol a név a kulcs.$_SERVER
: az összes környezeti változót
tartalmazza$_FILES
: a feltöltött fájlok helyét tartalmazza$_COOKIES
: a kliensről érkező sütik jelennek meg
bennesugar=10
→
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Kerület</title>
</head>
<body>
<p>Sugár = 10</p>
<p>Kerület = 62.83</p>
</body>
</html>
Az URL-ben adjuk át paraméterként
kerulet.php?sugar=10
<?php
// debug
print_r($_GET);
print_r($_POST);
// input
$sugar = $_GET['sugar'];
// processing
$pi = pi();
$ker = 2 * $sugar * $pi;
// output
?>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Kerület</title>
</head>
<body>
<p>Sugár = <?= $sugar ?></p>
<p>Kerület = <?= $ker ?></p>
</body>
</html>
<?php
declare(strict_types=1);
// debug
print_r($_GET);
print_r($_POST);
// business logic
function kerulet(float $sugar): float {
return 2 * $sugar * pi();
}
// input
$sugar = (float)$_GET['sugar'];
// processing
$ker = kerulet($sugar);
// output
?>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Kerulet</title>
</head>
<body>
<p>Sugár = <?= $sugar; ?></p>
<p>Kerület = <?= $ker; ?></p>
</body>
</html>
kerulet.php
→ PHP hibákAlapértelmezett érték
// Segédfüggvény
function is_empty($input, $key) {
return !(isset($input[$key]) && trim($input[$key]) !== '');
}
$hiba = '';
$sugar = null;
// Hiány esetén alapértelmezett érték
if (is_empty($_GET, 'sugar')) {
$sugar = 0.0;
}
// Formátumellenőrzés
else if (!is_numeric($_GET['sugar'])) {
$hiba = 'A sugár nem szám!';
}
else {
$sugar = (float)$_GET['sugar'];
}
if ($hiba === '') {
// processing
$ker = kerulet($sugar);
}
Hibaüzenet
// Segédfüggvény
function is_empty($input, $key) {
return !(isset($input[$key]) && trim($input[$key]) !== '');
}
$hiba = '';
$sugar = null;
// Hiány esetén hibaüzenet
if (is_empty($_GET, 'sugar')) {
$hiba = 'A sugár megadása kötelező';
}
// Formátumellenőrzés
else if (!is_numeric($_GET['sugar'])) {
$hiba = 'A sugár nem szám!';
}
else {
$sugar = (float)$_GET['sugar'];
}
if ($hiba === '') {
// processing
$ker = kerulet($sugar);
}
Kimenet: hibaüzenet kiírása
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Kerulet</title>
</head>
<body>
<?php if ($hiba) : ?>
<p><?= $hiba ?></p>
<?php else : ?>
<p>Sugár = <?= $sugar ?></p>
<p>Kerület = <?= $ker ?></p>
<?php endif ?>
</body>
</html>
$_GET
vagy $_POST
)$data
)$errors
)<ul>
)filter_*()
filter_var()
és filter_var_array()
// is_numeric helyett
if (!filter_var($input['sugar'], FILTER_VALIDATE_FLOAT)) {
$hiba = 'A sugár nem szám!';
}
// Összetettebb: szűrés és validálás
$email = filter_var($_POST['email'], FILTER_SANITIZE_EMAIL);
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$hiba = "Nem jó e-mail formátum!";
}
// Opciók
filter_var($string, FILTER_VALIDATE_REGEXP, [
"options"=>[
"regexp"=>"/^M(.*)/",
],
]);
$errors = [];
$input = $_GET;
// Ellenőrzés
if (validate($input, $data, $errors)) {
// Beolvasás
$sugar = $data['sugar'];
// Feldolgozás
$ker = kerulet($sugar);
} else {
// Hiba: $errors tömb
}
function validate($input, &$data, &$errors) {
// sugár vizsgálata
$data['sugar'] = null;
if (is_empty($input, 'sugar')) {
$errors[] = 'A sugár megadása kötelező';
}
else if (!is_numeric($input['sugar'])) {
$errors[] = 'A sugár nem szám!';
}
else {
$data['sugar'] = (float)$input['sugar'];
}
return !(bool)$errors;
}
<?php if ($errors) : ?>
<ul>
<?php foreach($errors as $error) : ?>
<li><?= $error ?></li>
<?php endforeach ?>
</ul>
<?php endif ?>
<?php
// debug
print_r($_GET);
print_r($_POST);
// business logic
function kerulet(float $sugar): float {
return 2 * $sugar * pi();
}
// helper function
function is_empty($input, $key) {
return !(isset($input[$key]) && trim($input[$key]) !== '');
}
function validate($input, &$data, &$errors) {
// sugár vizsgálata
$data['sugar'] = null;
if (is_empty($input, 'sugar')) {
$errors[] = 'A sugár megadása kötelező';
}
else if (!is_numeric($input['sugar'])) {
$errors[] = 'A sugár nem szám!';
}
else {
$data['sugar'] = (float)$input['sugar'];
}
return !(bool)$errors;
}
// start
$errors = [];
$input = $_GET;
// check
if (validate($input, $data, $errors)) {
// input
$sugar = $data['sugar'];
// processing
$ker = kerulet($sugar);
}
// output
?>
<?php if ($errors) : ?>
<ul>
<?php foreach($errors as $error) : ?>
<li><?= $error ?></li>
<?php endforeach ?>
</ul>
<?php else : ?>
<p>Sugár = <?= $sugar ?></p>
<p>Kerület = <?= $ker ?></p>
<?php endif ?>
kerulet.php?sugar=10
kerulet.html
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Kerulet</title>
</head>
<body>
<form action="kerulet.php" method="get">
Radius:
<input type="text" name="sugar" value="10">
<button>Calculate</button>
</form>
</body>
</html>
kerulet.php (ugyanaz)
<?php
declare(strict_types=1);
// debug
print_r($_GET);
print_r($_POST);
// business logic
function kerulet(float $sugar): float {
return 2 * $sugar * pi();
}
// helper function
function is_empty($input, $key) {
return !(isset($input[$key]) && trim($input[$key]) !== '');
}
function validate($input, &$data, &$errors) {
// sugár vizsgálata
$data['sugar'] = null;
if (is_empty($input, 'sugar')) {
$errors[] = 'A sugár megadása kötelező';
}
else if (!is_numeric($input['sugar'])) {
$errors[] = 'A sugár nem szám!';
}
else {
$data['sugar'] = (float)$input['sugar'];
}
return !(bool)$errors;
}
// start
$errors = [];
$input = $_GET;
// check
if (validate($input, $data, $errors)) {
// input
$sugar = $data['sugar'];
// processing
$ker = kerulet($sugar);
}
// output
?>
<?php if ($errors) : ?>
<ul>
<?php foreach($errors as $error) : ?>
<li><?= $error ?></li>
<?php endforeach ?>
</ul>
<?php else : ?>
<p>Sugár = <?= $sugar ?></p>
<p>Kerület = <?= $ker ?></p>
<?php endif ?>
Az űrlap önmagának küldi az adatot!
<?php
$errors = [];
$input = $_GET;
if (count($_GET) !== 0) {
// validate
if (validate($input, $data, $errors)) {
// input
$sugar = $data['sugar'];
// processing
$ker = kerulet($sugar);
}
}
// output
?>
<body>
<?php if ($errors) : ?>
<ul>
<?php foreach($errors as $error) : ?>
<li><?= $error ?></li>
<?php endforeach ?>
</ul>
<?php endif ?>
<form action="" method="GET">
Radius:
<input type="text" name="sugar" value="10">
<button>Calculate</button>
</form>
<?php if (isset($ker)) : ?>
<p>Sugár = <?= $sugar ?></p>
<p>Kerület = <?= $ker ?></p>
<?php endif ?>
</body>
Írjuk vissza a kitöltött adatokat, legalább hiba esetén!
<form action="circle.php" method="get">
Sugár:
<input type="text" name="sugar" ✒>value="<?= $input['sugar'] ?? '' ?><✒">
<input type="submit">
</form>
<input name="input1" type="text" value="<?= $input1 ?? '' ?>">
<textarea name="input2"><?= $input2 ?></textarea>
<input name="input3" type="checkbox" value="value3"
<?= $input3 === "value3" ? " checked" : "" ?>
>
<input name="input4" type="radio" value="value4"
<?= $input4 === "value4" ? " checked" : "" ?>
>
<select name="input5">
<option value="value51"
<?= $input5 === "value51" ? " selected" : "" ?>
>Value 3</option>
<option value="value52"
<?= $input5 === "value52" ? " selected" : "" ?>
>Value 4</option>
</select>
$messages = [];
if (/* ERROR */) {
$messages[✒>'field1'<✒] = [
"type" => "error",
"message" => "ERROR MESSAGE"
];
}
<input name="field1">
<?php if (isset($messages['field1'])) : ?>
<span><?= $messages['field1']['message'] ?></span>
<?php endif ?>
GET
)GET
)GET
, POST
)GET
, POST
, …)window.location
(GET
)submit()
metódus (GET
,
POST
)Oldal újratöltése programozottan (GET
)
window.location = "http://example.com?✒>name=value<✒";
Űrlap elküldése programozottan (GET
,
POST
)
const form = document.querySelector("form");
✒>form.submit()<✒;
AJAX/fetch kérés küldése szervernek
async function () {
const formData = new FormData();
formData.append("name", "value");
const response = fetch("http://example.com?✒>name=value<✒", {
✒>method: "POST"<✒,
✒>body: formData<✒
})
}
GET
)GET
)GET
, POST
)GET
, POST
, …)window.location
(GET
)submit()
metódus (GET
,
POST
)GET
)POST
)