Szerveroldali webprogramozás
Tűri Erik
doktorandusz
1117 Budapest, Pázmány Péter sétány 1/c., 4.725-ös szoba
turierik@inf.elte.hu
A leküldendő tartalmat egy program állítja elő.
Azt határozza meg, hogy egy webszerver hogyan indíthat el egy programot és milyen módon cserél adatot vele.
<?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>
<?php
// debug
print_r($_GET);
print_r($_POST);
// Segédfüggvény
function is_empty($input, $key) {
return !(isset($input[$key]) && trim($input[$key]) !== '');
}
// business logic
function kerulet(float $sugar): float {
return 2 * $sugar * pi();
}
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;
}
$errors = [];
$input = $_GET;
if (count($_GET) !== 0) {
// validation
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 endif; ?>
<form action="" method="GET">
Radius:
<input type="text" name="sugar" value="<?= $input["sugar"] ?? "10" ?>">
<button>Calculate</button>
</form>
<?php if (isset($ker)) : ?>
<p>Sugár = <?php echo $sugar; ?></p>
<p>Kerület = <?php echo $ker; ?></p>
<?php endif; ?>
json_encode
, json_decode
function load_from_file(string $filename, bool $array_result = false, $default_data = []) {
$s = @file_get_contents($filename);
return ($s === false
? $default_data
: json_decode($s, $array_result));
}
function save_to_file(string $filename, $data) {
$s = json_encode($data);
return file_put_contents($filename, $s, LOCK_EX);
}
$_SESSION
namespace \A\B\C
\A\B\C\func()
// definition and local use
namespace Tools\Html;
class Table { /* ... */ }
$table = new Table();
// Use outside the namespace
$table = new Tools\Html\Table();
// Use inside the namespace
namespace Tools\Html;
$table = new Table();
// class alias
use Tools\Html\Table as T;
$table = new T();
// namespace alias
use Tools\Html as H;
$table = new H\Table();
// namespace alias
use Tools\Html;
$table = new Html\Table();
composer require csomagnév
vendor
mappába (.gitignore
❗)composer.json
composer install
: függőségek telepítéserequire 'vendor/autoload.php';
namespace
, use
// SleekDb.php
namespace SleekDB;
class SleekDB { /* ... */ }
// index.php
$myStore = \SleekDB\SleekDB::store('something', $dataDir);
// Or
// index.php, with using namespace
use \SleekDB\SleekDB;
$myStore = SleekDB::store('something', $dataDir);
<?php
function get_all_tracks() {
$tracks = json_decode(file_get_contents('tracks.array.json'), true);
return $tracks;
}
$tracks = get_all_tracks();
?>
<ul>
<?php foreach($tracks as $track) : ?>
<li style="background-color: <?= $track['color'] ?>">
<span>🎵 <?= $track['category'] ?></span>
<?= $track['name'] ?> (<?= $track['instrument'] ?>)
</li>
<?php endforeach ?>
</ul>
SleekDB: Flat file NoSQL-like database
<?php
require __DIR__ . '/vendor/autoload.php';
$dataDir = "./data";
$trackStore = \SleekDB\SleekDB::store('tracks', $dataDir);
$tracks = $trackStore->fetch();
?>
<ul>
<?php foreach($tracks as $track) : ?>
<li style="background-color: <?= $track['color'] ?>">
<span>🎵 <?= $track['category'] ?></span>
<?= $track['name'] ?> (<?= $track['instrument'] ?>)
</li>
<?php endforeach ?>
</ul>
require __DIR__ . '/vendor/autoload.php';
$dataDir = "./data";
$trackStore = \SleekDB\SleekDB::store('tracks', $dataDir);
// Delete store
$trackStore->deleteStore();
$trackStore = \SleekDB\SleekDB::store('tracks', $dataDir);
// Prepare users data.
$tracks = json_decode(file_get_contents('tracks.array.orig.json'), true);
$tracks = array_map(function ($track) {
unset($track['id']);
return $track;
}, $tracks);
// Insert all data.
$trackStore->insertMany($tracks);
echo "Seeded";
Plates: Natív PHP sablonok
<?php
require __DIR__ . '/vendor/autoload.php';
// Data
$dataDir = "./data";
$trackStore = \SleekDB\SleekDB::store('tracks', $dataDir);
$tracks = $trackStore->fetch();
// Template
$templates = new League\Plates\Engine('./templates');
echo $templates->render('track_list', ['tracks' => $tracks]);
Sablon és layout
<?php $this->layout('layouts/default') ?>
<ul>
<?php foreach($tracks as $track) : ?>
<li style="background-color: <?= $track['color'] ?>">
<span>🎵 <?= $track['category'] ?></span>
<?= $track['name'] ?> (<?= $track['instrument'] ?>)
</li>
<?php endforeach ?>
</ul>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>MIDI editor</title>
</head>
<body>
<?=$this->section('content')?>
</body>
</html>
<?php
function validate($post, &$data, &$errors) {
if (!(isset($post['name']) && trim($post['name'])!=='')) {
$errors['name'] = "The track name is required";
} else {
$data['name'] = $post['name'];
}
if (!(isset($post['color']) && trim($post['color'])!=='')) {
$errors['color'] = "The track color is required";
}
else if (filter_var($post['color'], FILTER_VALIDATE_REGEXP, [
"options"=>[
"regexp"=>"/^#[0-9a-f]{6}$/",
],
]) === false) {
$errors['color'] = "The track color has a wrong format";
}
else {
$data['color'] = $post['color'];
}
if (!(isset($post['category']) && trim($post['category'])!=='')) {
$errors['category'] = "The category is required";
} else {
$data['category'] = $post['category'];
}
if (!(isset($post['instrument']) && trim($post['instrument'])!=='')) {
$errors['instrument'] = "The instrument is required";
}
else if (filter_var($post['instrument'], FILTER_VALIDATE_INT) === false) {
$errors['instrument'] = "The instrument has to be an integer";
} else {
$data['instrument'] = $post['instrument'];
}
return count($errors) === 0;
}
function add_track($data) {
$data["id"] = uniqid();
$data["notes"] = [];
$tracks = json_decode(file_get_contents('tracks.array.json'), true);
$tracks[] = $data;
file_put_contents('tracks.array.json', json_encode($tracks), LOCK_EX);
}
$data = [];
$errors = [];
if ($_POST) {
if (validate($_POST, $data, $errors)) {
add_track($data);
header('Location: index.php');
exit();
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>MIDI editor - Add new track</title>
<link rel="stylesheet" href="https://webprogramozas.inf.elte.hu/webprog/zh/midi/midi.css">
</head>
<body>
<h2>Add new track</h2>
<form action="" method="post">
<?php if ($errors) : ?>
<div class="errors">
<?= var_dump($errors) ?>
</div>
<?php endif ?>
<div>
<label for="name">Track name</label>
<input type="text" id="name" name="name">
(required)
</div>
<div>
<label for="color">Color</label>
<input type="text" id="color" name="color" placeholder="#1234af">
(required, format: hex color code, e.g. #12af4d)
</div>
<div>
<label for="category">Category</label>
<input type="text" id="category" name="category" list="category-list">
(required)
<datalist id="category-list">
<option value="Piano">
<option value="Organ">
<option value="Accordion">
<option value="Strings">
<option value="Guitar">
<option value="Bass">
<option value="Choir">
<option value="Trumpet">
<option value="Brass">
<option value="Saxophone">
<option value="Flute">
<option value="Synth Lead">
<option value="Synth Pad">
<option value="Percussion">
<option value="World">
<option value="Synth effects">
<option value="Sound effects">
</datalist>
</div>
<div>
<label for="instrument">Instrument</label>
<select id="instrument" name="instrument">
<option value="100">Instrument 1</option>
<option value="200">Instrument 2</option>
<option value="300">Instrument 3</option>
<option value="400">Instrument 4</option>
<option value="500">Instrument 5</option>
</select>
(required, number)
</div>
<div>
<button type="submit">Add new track</button>
</div>
</form>
<a href="index.php">Return to editor</a>
</body>
</html>
SleekDB
require __DIR__ . '/vendor/autoload.php';
$dataDir = "./data";
$trackStore = \SleekDB\SleekDB::store('tracks', $dataDir);
// function validate() {}
function add_track($trackStore, $data) {
$data["notes"] = [];
$trackStore->insert($data);
}
$data = [];
$errors = [];
if ($_POST) {
if (validate($_POST, $data, $errors)) {
add_track($trackStore, $data);
header('Location: index.php');
exit();
}
}
Rakit: űrlapellenőrzés
require __DIR__ . '/vendor/autoload.php';
use Rakit\Validation\Validator;
$dataDir = "./data";
$trackStore = \SleekDB\SleekDB::store('tracks', $dataDir);
function add_track($trackStore, $data) {
$data["notes"] = [];
$trackStore->insert($data);
}
$errors = [];
if ($_POST) {
$validator = new Validator();
$validation = $validator->validate($_POST, [
'name' => 'required',
'color' => 'required|regex:/^#[0-9a-f]{6}$/',
'category' => 'required',
'instrument' => 'required|integer',
]);
if ($validation->fails()) {
// handling errors
$errors = $validation->errors()->all();
} else {
// validation passes
$data = $validation->getValidData();
add_track($trackStore, $data);
header('Location: index.php');
exit();
}
}
Plates: sablon
<?php
require __DIR__ . '/vendor/autoload.php';
use Rakit\Validation\Validator;
$dataDir = "./data";
$trackStore = \SleekDB\SleekDB::store('tracks', $dataDir);
function add_track($trackStore, $data) {
$data["notes"] = [];
$trackStore->insert($data);
}
$errors = [];
if ($_POST) {
$validator = new Validator();
$validation = $validator->validate($_POST, [
'name' => 'required',
'color' => 'required|regex:/^#[0-9a-f]{6}$/',
'category' => 'required',
'instrument' => 'required|integer',
]);
if ($validation->fails()) {
// handling errors
$errors = $validation->errors()->all();
} else {
// validation passes
$data = $validation->getValidData();
add_track($trackStore, $data);
header('Location: index.php');
exit();
}
}
// Template
$templates = new League\Plates\Engine('./templates');
echo $templates->render('new_track', ['errors' => $errors]);
php
composer
php -S localhost:3000