Webprogramozás
Horváth Győző
Egyetemi docens
1117 Budapest, Pázmány Péter sétány 1/c., 2.408-as szoba
Tel: (1) 372-2500/8469
horvath.gyozo@inf.elte.hu

JsonStorage)include('jsonio.php');
include('jsonstorage.php');
include('movierepository.php');
include('userrepository.php');
$movieRepository = new MovieRepository();
$userRepository = new UserRepository();
$userId = $userRepository->insert(["username" => "q"]);
$movieRepository->insert(["title" => "Something", "user_id" => $userId]);
var_dump($movieRepository->all());
class UserRepository extends JsonStorage {
public function __construct() {
parent::__construct('./data/users.json');
}
}
class MovieRepository extends JsonStorage {
public function __construct() {
parent::__construct('./data/movies.json');
}
}

explode($elválasztó, $s): elemekre bontásimplode($elválasztó, $tömb): összefűzéssubstr($s, $kezdet, $hossz): részszövegltrim($s), rtrim($s), trim($s): fehérszóköz-eltávolítás.strstr($miben, $mit), strpos($miben, $mit), strrpos($miben, $mit): részszöveg keresésepreg_match($minta, $s): regkif illeszkedésedate($formátum): az aktuális idő kiírása a megadott formátumban.time(): Unix idő visszaadása másodpercben.strtotime($s): szövegként megadott dátum Unix időbe átalakítása.getdate(): dátuminformációk visszaadása tömbként.date_*: dátummal kapcsolatos további függvényekDateTime, DateInterval, DatePeriod osztályokdate("Y:m:d G:i:s"); // 2019:11:24 17:18:59
time(); // 1574615959 (s)
strtotime('2019-12-12'); // 1576108800
strtotime('2019-12-12T12:34:12'); // 1576154052
strtotime('now'); // 1574616109
strtotime('last day of next month'); // 1577813072
$d1 = new DateTime('+2 days');
$d2 = new DateTime('-2 weeks');
$interval = $d1->diff($d2);
$interval->format('%R%a days'); // -16 days
$d1 = new DateTimeImmutable('+2 days');
$d2 = $d1->add(new DateInterval('P2Y4DT6H8M'));
$interval = $d2->diff($d1);
$interval->format('%R%a days'); // -735 days
header()
header('Location: index.php');
function redirect($page) {
header("Location: index.php?{$page}");
}
include($fájlnév) – hiba esetén warninggal továbbmegyinclude_once($fájlnév)require($fájlnév) – hiba esetén hibával megállrequire_once($fájlnév)



Mindegyik kliens ugyanazon az adaton osztozkodik

Kliensenkénti adattárolás

Tároljuk egy számláló értékét felhasználónként, és minden kérésnél növeljük a számláló értékét eggyel!

session_url.php?counter=1
<?php
print_r($_GET);
$counter = $_GET['counter'] ?? 0;
$counter += 1;
var_dump($counter);
?>
<a href="session_url.php?counter=<?php echo $counter; ?>">Increment</a>
→ űrlap rejtett mezője
<input type="hidden" name="counter" value="4"><?php
print_r($_POST);
$counter = $_POST['counter'] ?? 0;
$counter += 1;
var_dump($counter);
?>
<form action="" method="post">
<input type="hidden" name="counter" value="<?= $counter ?>">
<button>Increment</button>
</form>
<a href="session_hidden.php">Increment (not working)</a>
HTTP kérés és PHP ($_COOKIES)
Cookie: név1=érték1; név2=érték2; név3=érték3HTTP válasz és PHP:
Set-Cookie: név=érték[; expires=dátum][; domain=domain][; path=path][; secure]
// Általános formája
$siker = setcookie($név[, $érték [, $expires = 0 [, $path [, $domain [, $secure = false]]]]]);
// Néhány példa
setcookie('alma', 'piros');
setcookie('körte', 'sárga', time() + 60); //lejárat 60 mp múlva<?php
var_dump($_COOKIE);
$counter = $_COOKIE['counter'] ?? 0;
$counter += 1;
setcookie('counter', $counter);
var_dump($counter);
?>
<a href="session_cookie.php">Increment</a>

Több kliens

Egy kliens különböző kérései

$_SESSIONsession_start()session_destroy()<?php
session_start();
var_dump($_SESSION);
$counter = $_SESSION['counter'] ?? 0;
$counter += 1;
$_SESSION['counter'] = $counter;
var_dump($counter);
?>
<a href="session_php.php">Increment</a>
session_start();
$_SESSION = [];
session_destroy();
.htaccess, .htpasswd
class UserRepository extends JsonStorage {
public function __construct() {
parent::__construct('./data/users.json');
}
}
Űrlap
<?php if (isset($errors['global'])) : ?>
<p><span class="error"><?= $errors['global'] ?></span></p>
<?php endif; ?>
<form action="" method="post">
Username:
<input type="text" name="username">
<?php if (isset($errors['username'])) : ?>
<span class="error"><?= $errors['username'] ?></span>
<?php endif; ?>
<br>
Password:
<input type="password" name="password">
<?php if (isset($errors['password'])) : ?>
<span class="error"><?= $errors['password'] ?></span>
<?php endif; ?>
<br>
<button>Register</button>
</form>
$userRepository = new UserRepository();
function validate($input, &$data, &$errors, $userRepository) {
// username, password not empty
// ...
if (count($errors) === 0) {
if (user_exists($userRepository, $input['username'])) {
$errors['global'] = "User already exists";
}
}
return count($errors) === 0;
}
function user_exists($userRepository, $username) {
$users = $userRepository->filter(function ($user) use ($username) {
return $user['username'] === $username;
});
return count($users) >= 1;
}
function add_user($userRepository, $user) {
$user['password'] = password_hash($user['password'], PASSWORD_DEFAULT);
return $userRepository->insert($user);
}
$data = [];
$errors = [];
if ($_POST) {
if (validate($_POST, $data, $errors, $userRepository)) {
add_user($userRepository, $data);
header('Location: login.php');
exit();
}
}
Űrlap
<?php if (isset($errors['global'])) : ?>
<p><span class="error"><?= $errors['global'] ?></span></p>
<?php endif; ?>
<form action="" method="post">
Username:
<input type="text" name="username">
<?php if (isset($errors['username'])) : ?>
<span class="error"><?= $errors['username'] ?></span>
<?php endif; ?>
<br>
Password:
<input type="password" name="password">
<?php if (isset($errors['password'])) : ?>
<span class="error"><?= $errors['password'] ?></span>
<?php endif; ?>
<br>
<button>Login</button>
</form>
function validate($input, &$data, &$errors, $userRepository) {
// username, password not empty
// ...
if (count($errors) === 0) {
if (!check_user($userRepository, $input['username'], $input['password'])) {
$errors['global'] = "Login error";
}
}
return count($errors) === 0;
}
function check_user($userRepository, $username, $password) {
$users = $userRepository->filter(function ($user) use ($username) {
return $user['username'] === $username;
});
if (count($users) === 1) {
$user = array_values($users)[0];
return password_verify($password, $user["password"])
? $user
: false;
}
return false;
}
function login($user) {
$_SESSION["user"] = $user;
}
session_start();
$userRepository = new UserRepository();
$data = [];
$errors = [];
if ($_POST) {
if (validate($_POST, $data, $errors, $auth)) {
login($data);
header('Location: login.php');
exit();
}
}
session_start();
function is_authenticated() {
return isset($_SESSION["user"]);
}
function logout() {
unset($_SESSION["user"]);
}
Egyszerűsített
session_start();
if (!is_authenticated()) {
header("Location: login.php");
exit();
}
class Auth {
private $userRepository;
public function __construct() {
$this->userRepository = new UserRepository();
}
public function register($user) {
$user['password'] = password_hash($user['password'], PASSWORD_DEFAULT);
return $this->userRepository->insert($user);
}
public function user_exists($username) {
$users = $this->userRepository->filter(function ($user) use ($username) {
return $user['username'] === $username;
});
return count($users) >= 1;
}
public function login($user) {
$_SESSION["user"] = $user;
}
public function check_credentials($username, $password) {
$users = $this->userRepository->filter(function ($user) use ($username) {
return $user['username'] === $username;
});
if (count($users) === 1) {
$user = array_values($users)[0];
return password_verify($password, $user["password"])
? $user
: false;
}
return false;
}
public function is_authenticated() {
return isset($_SESSION["user"]);
}
public function logout() {
unset($_SESSION["user"]);
}
}
Regisztráció
function validate($input, &$data, &$errors, $auth) {
// ...
if (count($errors) === 0) {
if ($auth->user_exists($input['username'])) {
$errors['global'] = "User already exists";
}
}
return count($errors) === 0;
}
$auth = new Auth();
$data = [];
$errors = [];
if ($_POST) {
if (validate($_POST, $data, $errors, $auth)) {
$auth->register($data);
header('Location: login.php');
exit();
}
}
Beléptetés
function validate($input, &$data, &$errors, $auth) {
// ...
if (count($errors) === 0) {
if (!$auth->check_credentials($input['username'], $input['password'])) {
$errors['global'] = "Login error";
}
}
return count($errors) === 0;
}
session_start();
$auth = new Auth();
$data = [];
$errors = [];
if ($_POST) {
if (validate($_POST, $data, $errors, $auth)) {
$auth->login($data);
header('Location: login.php');
exit();
}
}
if ($_POST) {
if (validate($_POST, $data, $errors)) {
$todoRepository->insert([
'title' => $data['title'],
]);
}
}
$todos = $todoRepository->all();
Ötlet: POST konvertálása GET-té átirányítással
if ($_POST) {
if (validate($_POST, $data, $errors)) {
$todoRepository->insert([
'title' => $data['title'],
]);
header('Location: todo.php');
exit();
}
}
$todos = $todoRepository->all();
“Laza” PRG
function validate($input, &$data, &$errors) {
// ...
}
$todoRepository = new TodoRepository();
$data = [];
$errors = [];
if ($_POST) {
if (validate($_POST, $data, $errors)) {
$todoRepository->insert([
'title' => $data['title'],
]);
header('Location: todo.php');
exit();
}
}
$todos = $todoRepository->all();
?>
<form action="" method="post">
Movie: <input type="text" name="title">
<?php if (isset($errors['title'])) : ?>
<span class="error"><?= $errors['title'] ?></span>
<?php endif ?>
<button>Add todo</button>
</form>
<ul>
<?php foreach($todos as $todo) : ?>
<li><?= $todo['title'] ?></li>
<?php endforeach ?>
</ul>
“Extrém” PRG: oldalt megjeleníteni csak GET metódussal lehet!
Olyan adatok, amelyek csak egy kérés idejéig élnek a munkamenetben
(Nálunk: amíg ki nem vesszük őket)
function set_flash_data($key, $value) {
$_SESSION[$key] = $value;
}
function get_flash_data($key) {
$value = $_SESSION[$key] ?? null;
unset($_SESSION[$key]);
return $value;
}
session_start();
$todoRepository = new TodoRepository();
$data = [];
$errors = get_flash_data('errors') ?? [];
$input = get_flash_data('input') ?? [];
if ($_POST) {
if (validate($_POST, $data, $errors)) {
$todoRepository->insert([
'title' => $data['title'],
]);
header('Location: todo.php');
exit();
} else {
set_flash_data('errors', $errors);
set_flash_data('input', $_POST);
header('Location: todo.php');
exit();
}
}
$todos = $todoRepository->all();
?>
<form action="" method="post">
Todo:
<input type="text" name="title" value="<?= $input['title'] ?? '' ?>">
<?php if (isset($errors['title'])) : ?>
<span class="error"><?= $errors['title'] ?></span>
<?php endif; ?>
<button>Add todo</button>
</form>
<ul>
<?php foreach($todos as $todo) : ?>
<li><?= $todo['title'] ?></li>
<?php endforeach ?>
</ul>
<?php var_dump($errors) ?>
<form action="" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<button>Upload</button>
</form>
$errors = [];
if ($_FILES) {
if (array_key_exists('file', $_FILES) &&
$_FILES['file']['error'] == 0) {
$from = $_FILES['file']['tmp_name'];
$to = 'files\\' . $_FILES['file']['name'];
move_uploaded_file($from, $to);
} else {
$errors[] = 'Error during upload!';
}
}
Array
(
[file] => Array
(
[name] => Desert_small.jpg
[type] => image/jpeg
[tmp_name] => C:\eltescorm\tmp\php1750.tmp
[error] => 0
[size] => 18218
)
)
<ul>
<?php foreach($files as $file) : ?>
<li><?= $file ?></li>
<?php endforeach ?>
</ul>
function getFiles($dir) {
$fajls = [];
$d = opendir($dir);
while (($f = readdir($d)) !== false) {
$fajls[] = $f;
}
closedir($d);
return $fajls;
}
$files = getFiles('files\\');
php -S localhost:3000session_start(), $_SESSION