Download as pdf or txt
Download as pdf or txt
You are on page 1of 468

PRZEPŁYW STEROWANIA

W APLIKACJACH INTERNETOWYCH
LOGIKA INTERFEJSU
LOGIKA OBSŁUGI ŻĄDAŃ
LOGIKA BIZNESOWA
MVC: MODEL-VIEW-CONTROLLER
Waldemar Wytwarzanie Aplikacji Internetowych
Korłub KASK ETI Politechnika Gdańska
PHP: kiedyś
2

¨ Oryginalnie PHP wykorzystywano do


tworzenia dynamicznych „wstawek”
w kodzie HTML
Kiedyś <html ... > products.php
<head>
<!--...--> Trochę kodu HTML
</head>
<body>
3 <?php
$mongo = new MongoClient(/*...hasło...*/);
Baza danych Trochę
$db = $mongo->db; kodu PHP
$cat = $_GET['cat']; ?> Obsługa parametrów HTTP
<!--...-->
<table>
HTML Baza danych
<?php foreach ($db->products->find(['cat' => $cat]) as $prod): ?>
<tr>
<td><!--...--></td>
<!--...--> Więcej kodu HTML
<td>
<?php $count = $db->comments
->find(['prod_id' => $prod['_id']]) Baza danych
->count(); ?>

<?php if($count === 0): ?>brak komentarzy<?php endif; ?>


</td>
</tr> PHP HTML
<?php endforeach ?>
</table>
</body> HTML
</html>
Struktura projektu
4

📂/ # główny katalog projektu


├⎯📄 composer.json
├⎯📄 composer.lock
├⎯📂 vendor/ # biblioteki 3rd party
│ ├⎯📄 autoload.php
│ ├⎯📂 composer/
│ ├⎯📂 mongodb/
│ :
├⎯📂 src/ # nasz kod źródłowy
│ ├⎯📄 products.php # wyświetlanie listy produktów
│ ├⎯📄 edit.php # edycja produktu
│ ├⎯📄 delete.php # usuwanie produktu
PHP: kiedyś
5

¨ Powyższe podejście może sprawdzić się jedynie


w najprostszych aplikacjach
¤A nawet w nich szybko staje się niewygodne w rozwoju
i uciążliwe w utrzymaniu
¨ Z czego wynika ten problem?
Kiedyś <html ... > products.php
<head>
<!--...--> HTML: interfejs
</head>
<body>
6 <?php
$mongo = new MongoClient(/*...hasło...*/); Dane aplikacji: PHP:
$db = $mongo->db; logika biznesowa logika
$cat = $_GET['cat']; ?> Logika obsługi żądania HTTP
<!--...-->
<table>
Interfejs Logika biznesowa
<?php foreach ($db->products->find(['cat' => $cat]) as $prod): ?>
<tr>
<td><!--...--></td>
<!--...--> Interfejs
<td>
Logika
<?php $count = $db->comments Logika
->find(['prod_id' => $prod['_id']])
interfejsu ->count(); ?> biznesowa
<?php if($count === 0): ?>brak komentarzy<?php endif; ?>
</td>
</tr> Logika interfejsu
<?php endforeach ?>
</table>
</body> Interfejs
</html>
Problemy – najbardziej palące
7

¨ Przemieszane ze sobą:
¤ Logika obsługi żądań HTTP
¤ Logika biznesowa
¤ Interfejs i logika jego wyświetlania

¨ Brak jasnej kolejności przetwarzania


¤ Za co odpowiada dany fragment? (biznes/interfejs/http)
n Trudne nawigowanie po pliku
n Jak podzielić w zespole pracę (i odpowiedzialność) pomiędzy
programistów i UX designerów?
n Łatwość popsucia logiki biznesowe przy modyfikowaniu interfejsu
¤ Jak reagować na wyniki logiki biznesowej, gdy część
interfejsu została już wygenerowana?
n Brak możliwości zmiany kodu odpowiedzi, nagłówków, przekierowań
Krok 1 <?php products.php
$cat = $_GET['cat']; Logika obsługi żądania HTTP
$mongo = new MongoClient(/*...hasło...*/);
$db = $mongo->db;
8 $products = $db->products->find(['cat' => $cat]); Logika
foreach ($products as $p) biznesowa
$p['count'] = $db->comments->
find(['prod_id'=>$p['_id']])->count();
?>
<!DOCTYPE html>
<html ...>
<body>
<!--...-->
<table>
<?php foreach ($products as $p): ?>
<tr>
<td><!--...--></td>
<!--...-->
<td>
Interfejs i jego logika
<?php if ($p['count'] === 0): ?>
brak komentarzy<?php endif; ?>
</td>
</tr>
<?php endforeach ?>
</table>
</body>
</html>
Krok 2 <?php products.php
$cat = $_GET['cat']; Logika obsługi żądania HTTP
$mongo = new MongoClient(/*...hasło...*/);
$db = $mongo->db;
9 $products = $db->products->find(['cat' => $cat]); Logika
foreach ($products as $p) biznesowa
$p['count'] = $db->comments->
find(['prod_id'=>$p['_id']])->count();

Logika obsługi
Dołączenie pliku odpowiedzi
include 'products_view.php'; z interfejsem: widok HTTP
<!DOCTYPE html>
<html ...> products_view.php
<body>
<!--...-->
<table>
<?php foreach ($products as $p): ?>
<tr>
<td><!--...--></td>
<!--...-->
<td>
<?php if ($p['count'] === 0): ?>
brak komentarzy<?php endif; ?>
</td>
</tr>
<?php endforeach ?>
</table>
</body>
</html>
Struktura projektu
10

📂 src/
├⎯📄 products.php # logika listy produktów
├⎯📄 products_view.php # widok listy produktów
├⎯📄 edit.php # logika edycji produktu
├⎯📄 edit_view.php # widok edycji produktu
├⎯📄 delete.php # logika usuwania produktu
├⎯📄 delete_view.php # widok usuwania produktu

:
Kolejność operacji
11

1. Logika obsługi żądania HTTP


¤ Parametry GET, POST, przychodzące cookies
(w tym sesja)
¤ Żądanie (oraz sesja) zawiera parametry, które są
argumentami dla logiki biznesowej – muszą być
odczytane przed jej uruchomieniem
¤ Przekształca dane z żądania na parametry z domeny
biznesowej
n np. konwersja typów
n Wszystkie parametry w żądaniu są ciągami znaków (string)
n Logika biznesowa może wymagać liczb (np. liczba dostępnych
egzemplarzy produktów), dat w formacie timestamp,
dokumentów itd.
Kolejność operacji
12

2. Logika biznesowa
¤ Powinna być niezależna od protokołu HTTP!
n Code reuse, łatwiejsze testowanie
¤ Przyjmuje argumenty z domeny biznesowej i zwraca
wyniki z domeny biznesowej
¤ Może się nie powieść z przyczyn niezależnych od
aplikacji, np.:
n Brakpołączenia z bazą danych
n Nieudana płatność – błąd w komunikacji z zewnętrzną usługą

¤ …ale nie może spowodować awarii aplikacji


n Konieczność obsługi sytuacji wyjątkowych
Kolejność operacji
13

3. Logika obsługi odpowiedzi HTTP


¤ Kod i nagłówki odpowiedzi, m.in. przekierowania, cookies
(w tym sesja)
¤ Ciało odpowiedzi – wybór widoku (jeśli nie redirect)
n Wybór wyników z logiki biznesowej do wyświetlenie w widoku
¤ Wynika z efektów logiki biznesowej, np.:
n Nieznalezionyprodukt w bazie danych: odpowiedź 404
n Złożenie zamówienia – zmiana stanu po stronie serwera:
odpowiedź 302/303 + nagłówek Location
n Wyświetlenie danych w bazy: odpowiedź 200 + widok

¤ Interpretuje
wyniki z domeny biznesowej w kategoriach
odpowiedzi HTTP dla przeglądarki
Kolejność operacji
14

4. Widok
¤ Prezentujeefekty logiki biznesowej
¤ Musi być przygotowany na wszystkie wartości,
dopuszczalne w domenie biznesowej, np.:
n Pustalista, gdy wyszukiwanie nie dało efektów
n Brak wartości w polach opcjonalnych

¤ Błąd w widoku zawsze jest efektem niedopatrzenia


programisty!
Problemy – ciąg dalszy
15

¨ Osadzenie logiki biznesowej w pliku generującym


kod HTML uniemożliwia jej wykorzystanie w innych
miejscach aplikacji (ang. code reuse)
¤ Znakomicie utrudnia też testowanie

¨ Rozwiązanie: funkcje!
¤W osobnym pliku, który nie generuje żadnej treści dla
przeglądarki
Krok 3 <?php business.php
function get_db()
{
$mongo = new MongoClient(/*...hasło...*/);
$db = $mongo->db;
16
return $db;
}
function get_products_by_category($cat)
{
$db = get_db();
$products = $db->products->find(['cat' => $cat]);
/*...*/
return $products;
}
<?php products.php <!DOCTYPE html>
<html ...> products_view.php
<body>
require_once 'business.php'; <!--...-->
<table>
<?php foreach ($products as $p): ?>
$cat = $_GET['cat']; Wywołanie <tr>
<td><!--...--></td>
logiki biznesowej <!--...-->
$products = <td>
<?php if ($p['count'] === 0): ?>
get_products_by_category($cat); brak komentarzy<?php endif; ?>
</td>
</tr>
include 'products_view.php'; <?php endforeach ?>
</table>
</body>
</html>
Krok 3 <?php edit.php <?php business.php
//...
if($_SERVER['REQUEST_METHOD'] === 'POST'){ function save_product(
if (!empty($_POST['name']) && $id, $product
!empty($_POST['price']) && /*...*/ ) {
17 ) { $db = get_db();
$id = isset($_POST['id']) ? if ($id == null) {
$_POST['id'] : null; $db->products->
$product = [ insert($product);
'name' => $_POST['name'],
'price' => (int)$_POST['price'], } else {
'description' => $_POST['description'] $db->products->update(
]; ['_id'=>new MongoId($id)],
$product);
if(save_product($id, $product)){ }
header('Location: products.php'); return true;
exit; }
}
<!DOCTYPE html>
}
<html ...>
} else {
<body>
if (!empty($_GET['id'])) {
<!--...-->
$id = $_GET['id'];
$product = get_product($id); <form>
} <!--...-->
} </form>
</body>
include 'edit_view.php'; </html> edit_view.php
Kontroler
18

¨ Dotychczasowe rozwiązanie wyróżnia:


¤ Logikę biznesową
¤ Widok

¤ Oraz trzeci komponent, który kontroluje przepływ


sterowania pomiędzy powyższymi – jak go nazwać?
¨ Kontroler – kontroluje przepływ sterowania w celu
obsługi akcji użytkownika:
¤ Odczytywanieprzekazanych parametrów
¤ Wywoływanie właściwej logiki biznesowej

¤ Wybór widoku do prezentacji wyników


Struktura projektu
19

📂 src/
├⎯📄 business.php # funkcje logiki biznesowej
├⎯📄 edit.php # kontroler edycji produktu
├⎯📄 edit_view.php # widok edycji produktu
├⎯📄 products.php # kontroler listy produktów
├⎯📄 products_view.php # widok listy produktów

.
.
.
Problem – jeden z prostszych
20

¨ Widoki walają się pomiędzy plikami z logiką

¨ Rozwiązanie: katalogi!
Struktura projektu
21

📂 src/
├⎯📄 business.php # funkcje logiki biznesowej
├⎯📄 edit.php # kontroler edycji produktu
├⎯📄 products.php # kontroler listy produktów
├⎯📂 views/ # widoki aplikacji
│ ├⎯📄 edit_view.php # widok edycji
│ ├⎯📄 products_view.php # widok listy
│ .
. .
. .
Problemy – ciągle nie koniec
22

¨ Wiele punktów wejścia


¤ Każdy kontroler jest osobnym punktem wejścia
¤ Kłopotliwe zarządzanie globalnymi aspektami aplikacji
n Sesja w obrębie całej aplikacji
n Kontrola dostępu obejmująca wszystkie zasoby

¨ Struktura adresów wymuszona nazwami plików


¤ Listaproduktów: http://example.com/products.php
¤ Edycja produktu: http://example.com/edit.php

¨ Rozwiązanie: front-controller
Front-controller
23

¨ Pojedynczy punkt wejścia do aplikacji


¨ Realizuje globalne aspekty działania aplikacji
¤ Wszystkie, które nie są związane z pojedynczą akcją
¨ Wybiera kontroler do wywołania na podstawie
parametrów żądania
Krok 4 <?php front_controller.php
//obsługa sesji
session_start();
24
//kontrola dostępu
require 'access.php';

//wybór kontrolera do wywołania:


$action_url = $_GET['action'];

switch ($action_url) {
case '/products':
require 'products.php';
break;
case '/edit': Routing
require 'edit.php'; Odwzorowanie adresu
break; na kontroler, który ma
//... obsługiwać dany adres
}
Struktura projektu
25

📂 src/
├⎯📄 business.php # funkcje logiki biznesowej
├⎯📄 edit.php # kontroler edycji
├⎯📄 front_controller.php # front-controller
├⎯📄 products.php # kontroler listy
├⎯📂 views/ # widoki aplikacji
│ ├⎯📄 edit_view.php # widok edycji
│ ├⎯📄 products_view.php # widok listy
: :
Nowy sposób adresacji
26

¨ example.com/front_controller.php?action=/products
¤ Zamiast example.com/products.php

¨ example.com/front_controller.php?action=/edit&id=5
¤ Zamiast example.com/edit.php?id=5

¨ example.com/front_controller.php?action=/checkout
¤ Zamiast example.com/checkout.php
Kolejny problem
27

¨ Te adresy są brzydkie…

¨ Zamiast:
example.com/front_controller.php?action=/products
example.com/front_controller.php?action=/edit&id=5

¨ Wolelibyśmy:
example.com/products
example.com/edit&id=5

¨ Albo nawet: example.com/edit/5

¨ Rozwiązanie: mod_rewrite
mod_rewrite
28

¨ Moduł umożliwiający przepisywanie adresów


¨ Adres z żądania HTTP zostaje zamieniony (przepisany)
na inny, zgodnie ze regułami zdefiniowanymi przez
programistę/administratora
¤ .htaccess– dodatkowa konfiguracja serwera w obrębie
katalogów projektu:
1 Jeśli nie istnieje plik o nazwie
<IfModule mod_rewrite.c>
takiej, jak w żądaniu HTTP…
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ front_controller.php?action=/$1 [QSA]
</IfModule>
3
…na front_controller.php…
2
…przepisz adres…
4 …a adres z żądania umieść 5 …i doklej wszystkie
w parametrze action… inne parametry.
Struktura projektu
29

📂 src/
├⎯📄 .htaccess # konfiguracja mod_rewrite
├⎯📄 business.php # funkcje logiki biznesowej
├⎯📄 edit.php # kontroler edycji
├⎯📄 front_controller.php # front-controller
├⎯📄 products.php # kontroler listy
├⎯📂 views/ # widoki aplikacji
│ ├⎯📄 edit_view.php # widok edycji
│ ├⎯📄 products_view.php # widok listy
: :
Problemy
30

¨ Niewygodne definiowanie routingu


¤ Switch-case

¤ Wymaga edytowania kodu front-controllera

¨ Rozwiązanie:
routingu w postaci odwzorowania adres à kontroler
zdefiniowanego poza front-controllerem
Krok 5 <?php routing.php
$routing = [
'/' => 'index',
31 '/products' => 'products',
'/edit' => 'edit',
//...
];
<?php front_controller.php
session_start(); //obsługa sesji

require 'access.php'; //kontrola dostępu

//wybór właściwego kontrolera do wywołania:


require_once 'routing.php';

$action_url = $_GET['action'];

$controller_name = $routing[$action_url];
require $controller_name . '.php';
Struktura projektu
32

📂 src/
├⎯📄 .htaccess # konfiguracja mod_rewrite
├⎯📄 business.php # funkcje logiki biznesowej
├⎯📄 edit.php # kontroler edycji
├⎯📄 front_controller.php # front-controller
├⎯📄 products.php # kontroler listy
├⎯📄 routing.php # routing
├⎯📂 views/ # widoki aplikacji
│ ├⎯📄 edit_view.php # widok edycji
│ ├⎯📄 products_view.php # widok listy
: :
Problemy
33

¨ Zagrożenie eksplozją liczby plików


¤ Osobny plik dla każdego kontrolera
¤ Wiele małych plików-kontrolerów w projekcie

¨ Rozwiązanie:
¤ Przeniesienie
akcji do funkcji
¤ Grupowanie związanych ze sobą akcji w jednym pliku
Krok 6 <?php controllers.php
require_once 'business.php';

function products()
34 {
$cat = $_GET['cat']; Wcześniej
$products = get_products_by_category($cat); products.php
include 'products_view.php';
}

function edit()
{
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!empty($_POST['name']) &&
!empty($_POST['price']) /* && ...*/
) {
//... Wcześniej
if (save_product($id, $product)){ edit.php
//...redirect...
}
}
} else { /*...*/ }
include 'edit_view.php';
}
Krok 6 <?php routing.php
$routing = [
'/' => 'index',
35 '/products' => 'products', Routing bez zmian
'/edit' => 'edit',
//...
];
<?php front_controller.php
require_once 'controllers.php';

session_start(); //obsługa sesji


require 'access.php'; //kontrola dostępu

//wybór kontrolera do wywołania:


Wywołanie require_once 'routing.php';
variable $action_url = $_GET['action'];
function
$controller_name = $routing[$action_url];
$controller_name();
Struktura projektu
36

📂 src/
├⎯📄 .htaccess # konfiguracja mod_rewrite
├⎯📄 business.php # funkcje logiki biznesowej
├⎯📄 controllers.php # kontrolery
├⎯📄 front_controller.php # front-controller
├⎯📄 routing.php # routing
├⎯📂 views/ # widoki aplikacji
│ ├⎯📄 edit_view.php # widok edycji
│ ├⎯📄 products_view.php # widok listy
: :
Problem
37

¨ Jedynym plikiem, który powinien być serwowany


przez serwer WWW jest front-controller.php
¨ Tymczasem każdy ze skryptów PHP może zostać
wywołany poprzez odpowiednie żądanie HTTP, np.:
¤ example.com/business.php
¤ Uruchomi skrypt business.php z pominięciem
front-controllera…
¤ …z pominięciem realizowanych przez niego operacji
globalnych, np. z pominięciem kontroli dostępu
n Uwaga na skutki uboczne skryptów!
¨ Rozwiązanie: osobny podkatalog jako
DocumentRoot serwera WWW
Struktura projektu
38

📂 src/
├⎯📄 business.php # funkcje logiki biznesowej
├⎯📄 controllers.php # kontrolery
├⎯📄 routing.php # routing
├⎯📂 views/ # widoki aplikacji
│ ├⎯📄 edit_view.php # widok edycji
│ ├⎯📄 products_view.php # widok listy
│ :
├⎯📂 web/ # DocumentRoot
│ ├⎯📄 .htaccess # konfiguracja mod_rewrite
│ ├⎯📄 front_controller.php
│ ├⎯📂 static/ # pliki statyczne (.js,.png
.css, .jpg,
itd. )
Problemy – ciągle nie koniec
39

¨ Kontroler zajmuje się wyświetlaniem widoku


(i realizacją przekierowań)
¤ Kontroler powinien realizować operacje specyficzne dla
danej akcji
¤ Wybór widoku (lub przekierowania) jest specyficzny
dla akcji – zależy od wyników logiki biznesowej
¤ …ale wyświetlanie widoku nie jest specyficzne dla
akcji – każdy widok wyświetlany jest tak samo, gdy już
znamy właściwą nazwę
¨ Widok ma dostęp do wszystkich zmiennych
kontrolera
¤ Nawet do tych, do których nie powinien mieć
Problemy – ciągle nie koniec
40

¨ Rozwiązanie:
¤ Za
operacje uniwersalne dla wszystkich kontrolerów
odpowiada front-controller
n Przeniesienie logiki wyświetlania widoku do front-controllera
¤ Wprowadzenie kontraktu pomiędzy kontrolerem
i widokiem – model
n Jakie dane mają zostać zaprezentowane użytkownikowi?
n Tylko te będą udostępniane przez kontroler dla widoku
Model
41

¨ Zawiera dane, które kontroler przeznaczył do


wyświetlenia w widoku
¨ Może zawierać dane, które z widoku powinny trafić
do kontrolera
¤ np. dane z formularza
¨ Kontroler i widok mogą być modyfikowane
niezależnie od siebie tak długo, jak trzymają się
kontraktu w postaci modelu
Zmiany w kontrolerze
42

¨ Wybieranie widoku zamiast jego wyświetlania


¤ Zamiast include zwrócenie nazwy wybranego widoku
¨ Przekazywanie modelu
¤ Model jest parametrem wejściowym kontrolera – dane
z widoku dostarczane do kontrolera
¤ Model jest również parametrem wyjściowym kontrolera
– dane z kontrolera przeznaczone dla widoku
¤ Argument przekazywany przez referencję
Krok 7 <?php controllers.php
require_once 'business.php';

//...
43
function products(&$model) Obsługa parametrów
{ żądania HTTP

$cat = $_GET['cat']; Wywołanie logiki


biznesowej
$products = get_products_by_category($cat);

Model – jakie dane


zaprezentować w widoku
(tutaj: kolekcja produktów)
$model['products'] = $products;
Wybór widoku do
return 'products_view'; wyświetlenia:
} zwrócenie nazwy
Krok 7 function edit(&$model) controllers.php
{
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!empty($_POST['name']) /* && ...*/ ) {
44 $id = isset($_POST['id']) ? Obsługa
$_POST['id'] : null;
$product = [
parametrów
'name' => $_POST['name'],
HTTP
'price' => (int)$_POST['price'],
'description' => $_POST['description']
];
Wywołanie
if (save_product($id, $product)) { logiki biznesowej
return 'redirect:products';
} Wybór widoku:
}
} elseif (!empty($_GET['id'])) {
przekierowanie
$product = get_product($_GET['id']);
}
Model: edytowany
$model['product'] = $product; produkt

return 'edit_view'; Wybór widoku:


} formularz edycji
Krok 7
<?php front_controller.php
require_once '../dispatcher.php';
45 require_once '../controllers.php';

/* ...aspekty globalne... */

//wybór kontrolera do wywołania:


require_once 'routing.php';

$action_url = $_GET['action'];

$controller_name = $routing[$action_url];

$model = []; dispatching

$view_name = $controller_name($model);

build_response($view_name, $model);
Krok 7
<?php dispatcher.php
function build_response($view, $model)
46
{
if (strpos($view, 'redirect:') === 0) {
$url = substr($view, strlen('redirect:')); Redirect
header("Location: " . $url); 302
exit;

} else {
Wyświetlenie
render($view, $model); widoku
}
}

function render($view_name, $model)


{
extract($model);
include 'views/' . $view_name . '.php';
}
Funkcja extract()
47

$model = ['username' => 'Waldemar'];

$model['product'] =
['name' => 'Laptop' /*...*/];

$model['cart'] = [
'Tablet' => 2,
'Smartphon' => 1
]; $username = 'Waldemar';

extract($model); $product =
['name' => 'Laptop' /*...*/];

$cart = [
import elementów z tablicy do 'Tablet' => 2,
lokalnego zasięgu zmiennych 'Smartphon' => 1
];
Drobne porządki
48

¨ Dispatching warto przenieść do osobnej funkcji,


wywoływanej przez front-controller
¤ Uproszczenie konstrukcji front-controllera
¨ Prefiks wywołujący przekierowanie (redirect:)
warto umieścić w stałej
¤ Unikanie literówek
¨ Warto też uporządkować dyrektywy require
Krok 8

49
<?php front_controller.php
require_once '../dispatcher.php';
require_once '../routing.php';
require_once '../controllers.php';

/*...aspekty globalne...*/

//wybór kontrolera do wywołania:


$action_url = $_GET['action'];
dispatch($routing, $action_url);
Krok 8 <?php dispatcher.php
const REDIRECT_PREFIX = 'redirect:';

function dispatch($routing, $action_url)


{
50
$controller_name = $routing[$action_url];
$model = [];
$view_name = $controller_name($model);
build_response($view_name, $model);
}

function build_response($view, $model)


{
if (strpos($view, REDIRECT_PREFIX) === 0) {
$url = substr($view, strlen(REDIRECT_PREFIX));
header("Location: " . $url);
exit;
} else {
render($view, $model);
}
}

function render($view_name, $model)


{
extract($model);
include 'views/' . $view_name . '.php';
}
Struktura projektu
51

📂 src/
├⎯📄 business.php # funkcje logiki biznesowej
├⎯📄 controllers.php # kontrolery
├⎯📄 dispatcher.php # dispatcher
├⎯📄 routing.php # routing
├⎯📂 views/ # widoki aplikacji
│ ├⎯📄 edit_view.php # widok edycji
│ ├⎯📄 products_view.php # widok listy
│ :
├⎯📂 web/ # DocumentRoot
│ ├⎯📄 .htaccess # konfiguracja mod_rewrite
│ ├⎯📄 front_controller.php
│ ├⎯📂 static/ # pliki statyczne (.js,.png
.css, .jpg,
itd. )
Gdy projekt się rozrasta
52

¨ Organizacja modułów
¤ By layer
¤ By feature

¨ Programowanie obiektowe ułatwia organizację


komponentów
53 Et voilà: action-driven MVC
MVC:
§ Model – model
§ View – widok
§ Controller – kontroler
Wzorzec projektowy do modelowania interakcji
z użytkownikiem w warstwie interfejsu aplikacji.
54 Et voilà: action-driven MVC
Action-driven (request-driven) MVC:
§ Adaptacja wzorca MVC do realiów
aplikacji internetowej sterowanej
żądaniami HTTP
MVC: Model-View-Controller
55

Controller
obsługuje akcję
wykonuje akcję użytkownika manipuluje
w interfejsie
aplikacji
Model
zawiera dane
Użytkownik
do przedstawienia
w interfejsie

jest powoduje
View
prezentowany aktualizację
prezentuje model
w sposób czytelny
dla użytkownika
Action-driven (request-driven) MVC
56

przeglądarka
internetowa żądanie
HTTP wybiera kontroler na
odpowiedź podstawie routingu
HTTP (dispatching)
Front-controller Controller
wybiera widok,
zwraca model

wywołuje
Model
generuje dokument Model
hipertekstowy (HTML) renderuje zwraca
wyniki

Logika
View
biznesowa
Kiedyś <html ... >
<head>
<!--...--> HTML: interfejs
</head>
<body>
57 <?php
$mongo = new MongoClient(/*...hasło...*/); Dane aplikacji: PHP:
$db = $mongo->db; logika biznesowa logika
$cat = $_GET['cat']; ?> Logika obsługi żądania HTTP
<!--...-->
<table>
Interfejs Logika biznesowa
<?php foreach ($db->products->find(['cat' => $cat]) as $prod): ?>
<tr>
<td><!--...--></td>
<!--...--> Interfejs
<td>
Logika
<?php $count = $db->comments Logika
->find(['prod_id' => $prod['_id']])
interfejsu ->count(); ?> biznesowa
<?php if($count === 0): ?>brak komentarzy<?php endif; ?>
</td>
</tr> Logika interfejsu
<?php endforeach ?>
</table>
</body> Interfejs
</html> 50 slajdów wcześniej…
Action-driven MVC – składowe
58

¨ Front-controller
¨ Routing

¨ Kontrolery

¨ Modele danych dla widoków

¨ Szablony widoków

✚ Logika biznesowa poza kontrolerem


Symfony (PHP)
59

Action-driven MVCFramework Symfony


Front-controller app.php
Routing W pliku routing.yml/
przez adnotacje @Route
Kontrolery Dziedziczenie po Controller
Modele danych Tablice array() przekazywane do
renderowania widoków
Szablony widoków TWIG
Logika biznesowa Serwisy Symfony
Spring MVC (Java)
60

Action-driven MVC Spring MVC


Front-controller DispatcherServlet
Routing Adnotacje @RequestMapping
Kontrolery Adnotacje @Controller
Modele danych W argumentach kontrolera
Szablony widoków JSP, Thymeleaf, Velocity, …
Logika biznesowa Beany zarządzane
Action-driven MVC
61

¨ Symfony (PHP)
¨ Laravel (PHP)
¨ Spring MVC (Java)
¨ Play Framework (Java/Scala)
¨ Ruby on Rails (Ruby)
¨ Grails (Groovy)
¨ Django (Python)
¨ ASP.NET Core MVC (.NET)
¨ …
MVC w przeglądarce
62

wywołuje kontroler do
obsługi akcji użytkownika
View Controller
przeglądarka internetowa

zostaje
zaprezentowany
HTTP HTTP
response request

Model

Business
serwer
logic
MVC w przeglądarce
63

¨ Front-end – MVC w przeglądarce


¤ JavaScript, TypeScript
¨ Back-end – logika biznesowa po stronie serwera
¤ Usługi internetowe
¨ Niestety wykracza poza zakres kursu
wprowadzającego do aplikacji internetowych (WAI)
¤ Platformy technologiczne (2 rok studiów) – usługi REST
¤ Architektury usług internetowych (3 rok studiów)
64 Przykład: 04-procedural-mvc
65 Pytania?
KONTROLA DOSTĘPU
UWIERZYTELNIANIE I AUTORYZACJA
REJESTRACJA UŻYTKOWNIKÓW
PRZECHOWYWANIE HASEŁ
Waldemar Wytwarzanie Aplikacji Internetowych
Korłub KASK ETI Politechnika Gdańska
Kontrola dostępu
¨ W aplikacja internetowych typowo występuje
potrzeba rozróżnienia dostępnych funkcji i zasobów
w zależności od użytkownika, np.:
¤ Administratorsklepu może edytować produkty
¤ Zalogowany użytkownik może składać zamówienia

¤ Niezalogowany użytkownik może tylko przeglądać


ofertę i dodawać produkty do koszyka
¨ Na kontrolę dostępu składają się:
¤ Uwierzytelnianie– weryfikacja tożsamości użytkownika
¤ Autoryzacja – nadanie uprawnień
Uwierzytelnianie
¨ Weryfikacja tożsamości użytkownika
¨ Polega na sprawdzeniu informacji, którą z dużym
prawdopodobieństwem zna tylko dany użytkownik:
¤ Hasło

¤ Token dostępowy wysłany w wiadomości SMS


¤ Treść wygenerowana z użyciem klucza prywatnego
(kryptografia asymetryczna)
¨ Uwierzytelnianie dwuetapowe/wieloetapowe
¤ Wykorzystanie więcej niż jednej informacji
¤ np. potwierdzanie przelewów w banku internetowym
Autoryzacja
¨ Nadanie uprawnień do wykonywania operacji
i dostępu do zasobów
¨ Najczęściej w oparciu o ustaloną wcześniej
tożsamość użytkownika
¨ Wykorzystuje często metadane przypisane
użytkownikowi, np.:
¤ Przynależność do grup
¤ Przypisane role

¤ Nadane uprawnienia
Użytkownicy
¨ Typowo kontrola dostępu opiera się o bazę
użytkowników aplikacji
¨ Baza musi zawierać informacje umożliwiające
uwierzytelnienie użytkownika, np.:
¤ Hasło lub jego skrót (hash)
¤ Numer telefonu (token dostępowy z wiadomości SMS)

¤ Klucz publiczny (kryptografia asymetryczna)

¨ Najczęściej spotykany sposób uwierzytelniania


użytkowników wykorzystuje parę: login + hasło
Hasła użytkowników
¨ W idealnym świecie użytkownicy aplikacji…
¤ …wybierają długie hasła
¤ …nie stosują wyrażeń słownikowych

¤ …używają dużych i małych liter, cyfr i innych znaków

¤ …nigdy nie zapisują haseł na kartkach


n np. pod klawiaturą, w portfelu, przyklejone do monitora
¤ …nigdy nie używają tego samego hasła w różnych
serwisach
¤ …regularnie zmieniają swoje hasła
Hasła użytkowników
¨ W rzeczywistym świecie nie każdy użytkownik
trzyma się powyższych zasad…
¨ …a wymuszanie zbyt restrykcyjnej polityki haseł
może przynieść skutki odwrotne do oczekiwanych

¨ Autorzy aplikacji i administratorzy powinni


kompensować błędy swoich użytkowników
¤ Albo przynajmniej się starać
Przechowywanie haseł użytkowników

¨ Nie należy przechowywać haseł w postaci jawnej


(ang. plaintext)
¤ Włamanie do bazy à natychmiastowy dostęp do kont
użytkowników
¤ Szczególnie groźne dla użytkowników wykorzystujących to
samo hasło w wielu serwisach
¨ Należy wykorzystywać funkcje hashujące (mieszające)
¤ Skrót hasła nie powinien umożliwiać łatwego odtworzenia
oryginalnego hasła, np. dla hasła p@ssw0rd:
¤ $2y$10$8Bc9/72wX4TRsMoZcCyF/.7
fOs5gteQf4ioarhkzGcikb2iFT03/C
Przechowywanie haseł użytkowników

¨ Wiele funkcji, niegdyś uznawanych za bezpieczne,


obecnie jest łatwa do złamania
¤ Rosnąca moc obliczeniowa komputerów ułatwia ataki
siłowe (ang. brute-force) na funkcje skrótu
¤ Odkrywane są nowe słabości istniejących funkcji

¨ Nie należy stosować funkcji MD5


¤ Niezalecana od 1999 roku (rekomendacja NIST)
¤ Podatna na kolizje

¨ Podobnie nie zaleca się algorytmu SHA-1


Przechowywanie haseł użytkowników

¨ Od PHP 5.5 dostępne są funkcje pomocnicze:


¤ password_hash() – hashowanie
n Algorytm bcrypt bazujący na szyfrze Blowfish

$hash = password_hash('p@ssw0rd', PASSWORD_DEFAULT);

¤ password_verify() – weryfikacja hasła:

if (password_verify('p@ssw0rd', $hash)) {
echo 'Password is valid!';
} else {
echo 'Invalid password.';
}
Rejestracja użytkowników
1. Formularz rejestracji:
<input type="text" name="login" .../>
<input type="password" name="pass" .../>
<input type="password" name="repeat_pass" .../>
<!-- ... -->

2. Pobranie danych z zapytania POST:


$password = $_POST['pass'];
$repeat_password = $_POST['repeat_pass'];
//...

3. Weryfikacja:
if ($password === $repeat_password){ //...
Rejestracja użytkowników
4. Zahashowanie hasła:
$hash = password_hash($password, PASSWORD_DEFAULT);

5. Zapis do bazy danych:


$db->users->insert([
'login' => $login,
'password' => $hash
//...
]);

6. Redirect:
header('Location: success.php');
exit;
Logowanie
1. Formularz logowania:
<input type="text" name="login" .../>
<input type="password" name="pass" .../>

2. Pobranie danych z zapytania POST:


$password = $_POST['pass'];
$login = $_POST['login'];

3. Pobranie użytkownika z bazy danych


$user = $db->users->findOne(['login' => $login]);
Logowanie
Hasło Hash hasła
4. Weryfikacja hasła: z formularza z bazy danych
if($user !== null &&
password_verify($password, $user['password'])){
//hasło poprawne
}

5. Zmiana id sesji i zapisanie informacji o użytkowniku:


session_regenerate_id();
$_SESSION['user_id'] = $user['_id'];

6. Przekierowanie:
header('Location: profile.php');
exit;
Wylogowanie
¨ Wyczyszczenie danych bieżącej sesji:
¤ Programistyczne:
session_destroy();
//następnie usunięcie cookie

¤ W wyniku wygaśnięcia sesji po zadanym czasie


nieaktywności
Pytania?
MECHANIZM

Waldemar
Korłub
SESJI
Wytwarzanie Aplikacji Internetowych
KASK ETI Politechnika Gdańska
Protokół HTTP a potrzeby witryn
internetowych
¨ Protokół HTTP jest bezstanowy
¤ Niezależne żądania – serwer otrzymuje zapytanie,
generuje odpowiedź i zamyka połączenie
n $ telnet 192.168.166.20 80
¤ Brak powiązania pomiędzy kolejnymi zapytaniami
¤ Każde zapytanie musi zawierać komplet informacji,
koniecznych do jego przetworzenia
¨ Potrzeby witryn internetowych
¤ Zapamiętanie wyborów użytkownika na jednej podstronie,
w celu zrealizowania funkcjonalności na innej
n Koszyk produktów
n Składanie zamówienia
HTTP Cookies?
¨ Zapisywanie informacji po stronie przeglądarki
¤ Dane przesyłane do klienta w celu zapisania
¤ Potem dołączane do każdego kolejnego żądania

¨ Nie nadaje się do zapisywania informacji


wrażliwych
¤ Łatwość odczytania przez napastnika
n np. numer karty kredytowej użytkownika
¨ Nie można ufać wartościom cookies, które serwer
otrzymuje od klienta
¤ …ani żadnym innym wartościom w żądaniu HTTP
¤ Łatwość modyfikacji w przeglądarce
¤ Łatwość spreparowania złośliwego żądania
Po stronie serwera
¨ Bezpieczeństwo, kontrola nad danymi
¨ Wiele możliwości
¤ Pliki
na dysku, XML
¤ Baza danych

¤ Pamięć operacyjna (szybki dostęp, np. Memcached)

¨ Ale zanim cokolwiek zapiszemy/odczytamy:


jak rozpoznać różnych klientów aplikacji?
Wielodostęp w aplikacjach internetowych

¨ Sklep internetowy obsługuje wielu klientów


równocześnie
¨ Każdy klient sklepu ma własny koszyk
¨ Aby klienci mogli złożyć swoje zamówienia, każdy
koszyk należy zapamiętać
¤ Po stronie serwera
¨ Gdy klient dodaje kolejny produkt lub klika
„Zamów”, który koszyk wybrać?
Jak rozpoznać, że kolejne zapytania HTTP
pochodzą od tego samego klienta?

Istota mechanizmu sesji


Sesja
¨ Sesja
¤ Ciągkolejnych zapytań HTTP, wysyłanych przez tego
samego klienta
¨ Stan sesji
¤ Dane przechowywane pomiędzy kolejnymi zapytaniami
HTTP, składającymi się na sesję
Identyfikator sesji
¨ Każda sesja posiada unikalny identyfikator
¨ Identyfikator jest przekazywany do klienta
(przeglądarki) w momencie otwarcia sesji
¨ Każde żądanie HTTP w ramach sesji musi zawierać
jej identyfikator
¤ Przeglądarka dołącza identyfikator do kolejnych
żądań HTTP, gdy użytkownik nawiguje po stronie
¨ Serwer, otrzymując żądanie z dołączonym
identyfikatorem, wyszukuje właściwą sesję
i udostępnia jej stan (dane) na czas obsługi żądania
Identyfikator sesji
¨ Cechy dobrego identyfikatora sesji:
¤ Długi

¤ Losowy

¤ Generowany nieliniowo
n Brak możliwości odgadnięcia kolejnego identyfikatora na
podstawie aktualnego lub kilku poprzednich

¨ Trudny do odgadnięcia!
¤ Ile warty jest identyfikator sesji?
Przekazywanie identyfikatora sesji
¨ Podstawowe metody przekazywania danych
w protokole HTTP:
¤ Parametry żądania
n GET – dołączone do URI
n POST – w ciele zapytania
n Zawsze obsługiwane

¤ Cookies
n Dołączaneprzez przeglądarkę do każdego zapytania
n Mogą zostać wyłączone
Identyfikator w parametrze GET
lub w adresie żądania
¨ Niebezpieczeństwo ujawnienia identyfikatora
¤ Przesłanie linka (łącznie z identyfikatorem sesji) do
innej osoby
¤ Zapisanie adresu w historii przeglądarki lub
w zakładkach (bookmarks)
n Wchodzenie na stronę zawsze z tym samym id sesji
¤ Ujawnienie identyfikatora w nagłówku Referer
¨ Mechanizm używany w ostateczności, jeśli pliki
cookies nie są dostępne
¤ …lub całkowicie wyłączony w serwisach operujących
na wrażliwych informacjach
Przekazywanie identyfikatora
¨ Cookies
¤ Wystarczy ustawić ciasteczko (setcookie() w PHP)
¤ Przeglądarka zajmie się resztą

¨ Parametry żądań
¤ id musi być dołączony do każdego odnośnika na
stronie i każdego formularza (pole ukryte)
¤ Serwer może robić to automatycznie
Negocjowanie metody przekazywania id

¨ Konieczny wybór jednej z dwóch możliwości:


cookies lub parametry
¤ Preferowane cookies ze względów bezpieczeństwa
¨ Skąd serwer może wiedzieć, czy przeglądarka
zezwala na zapisywanie plików cookies?
¤ Jak można to sprawdzić?
Długość sesji
¨ Przy braku aktywności sesja powinna zostać
zakończona
¤Z punktu widzenia bezpieczeństwa
n Przechwycony identyfikator staje się bezużyteczny, gdy
sesja wygaśnie
n Zabezpieczenie dla użytkowników, który zapomnieli się
wylogować na publicznie dostępnym komputerze
¤Z punktu widzenia zasobów
n Zwolnienie zasobów zajmowanych przez sesję użytkownika
(np. pamięć operacyjna, pamięć dyskowa)
¨ Czas trwania sesji określony w plikach
konfiguracyjnych serwera bądź aplikacji
Lokalizacja danych sesji
¨ W pamięci operacyjnej
¤ np. Memcached
¤ Szybki dostęp, ale ograniczony rozmiar
¤ Bardzo kłopotliwe skalowanie w poziomie

¨ W plikach na dysku
¤ Dowolny rozmiar
¤ Wolniejszy dostęp
¤ Skalowanie w poziomie możliwe, ale wciąż kłopotliwe
n np. współdzielony system plików
¨ W bazie danych
¤ Dowolny rozmiar
¤ Łatwe skalowanie w poziomie
API PHP do obsługi sesji
Sesje w PHP
¨ PHP oferuje kompletne API do obsługi sesji
¤ Generowanie bezpiecznego id sesji
¤ Przekazywanie id do przeglądarki
n Cookies
n Parametry GET i POST
n Negocjacja sposobu przekazywania id

¤ Zapisywanie i odczyt danych w stanie sesji


¤ Obsługa wygaśnięcia sesji

¤ Czyszczenie stanu sesji


Parametry konfiguracyjne
mechanizmu sesji – php.ini
¨ session.use_cookies – używanie cookie do
przekazywania id sesji
domyślnie: On
¨ session.use_trans_sid – używanie parametrów
GET/POST do przekazywania id sesji
domyślnie: Off
¨ session.use_only_cookies – używanie wyłącznie
cookie do przekazywania id (nadpisuje use_trans_sid)
domyślnie: On (od PHP 5.3)
Parametry konfiguracyjne
mechanizmu sesji – php.ini
¨ session.name – nazwa cookie/parametru z id sesji
domyślnie: PHPSESSID
¨ session.cookie_lifetime – czas trwania sesji
domyślnie: do zamknięcia przeglądarki
¨ session.save_handler – lokalizacja danych sesji,
domyślnie: w plikach
¨ session.use_strict_mode – akceptowanie id
z żądania HTTP dla niezainicjowanej sesji,
domyślnie: Off (akceptuje)
¤ Uwaga na ataki session fixation!
Rozpoczęcie sesji

session_start();

¨ Uruchamia nową sesję lub wczytuje stan już


istniejącej (rozpoznanej na podstawie id z żądania)
¨ Przy włączonym session.use_cookies ustawia
cookie w odpowiedzi HTTP – musi być wywołana
przed rozpoczęciem emitowania ciała dokumentu!
¤W przeciwnym razie: Headers already sent
Dostęp do danych sesji
Tablica
superglobalna Wartość skalarna
zapisana w sesji
$_SESSION['name'] = 'Waldemar';

Sprawdzenie obecności
wartości w sesji
if (!isset($_SESSION['cart'])) {
$_SESSION['cart'] = []; //pusty koszyk
}
Tablica zapisana
$_SESSION['cart'][] = [ w sesji: pusty koszyk
'name' => 'Laptop XYZ',
'amount' => '1'
];
Wyczyszczenie danych sesji
session_destroy();
¨ Usuwa wszystkie dane sesji z dysku (lub bazy danych/
memcached)
¤ Nie usuwa zawartości tablicy $_SESSION dla bieżącego żądania
n $_SESSION będzie puste dopiero przy kolejnym żądaniu
¨ Nie zamyka sesji, nie usuwa cookie
¤ Klient może dalej korzystać z tego samego id i zapisywać nowe
dane w stanie sesji przy kolejnych żądaniach HTTP
¨ Całkowite zniszczenie sesji wymaga ręcznego usunięcia
cookie:
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
DEMO: przykład 03-session
¨ Prezentacja mechanizmów w przeglądarce
¤ Identyfikator sesji
¤ Pliki cookies
n Włączona/wyłączona akceptacja plików cookies
n Pliki cookies zapisane w przeglądarce a pliki
w odpowiedziach HTTP serwera
¤ Identyfikator
w parametrach GET/POST
¤ Negocjowanie sposobu przekazywania identyfikatora
Ataki na mechanizm sesji
à wykład na temat bezpieczeństwa
MongoDB
PODSTAWOWE KONCEPCJE
API DLA JĘZYKA PHP
OPERACJE NA DOKUMENTACH
Waldemar Wytwarzanie Aplikacji Internetowych
Korłub KASK ETI Politechnika Gdańska
Sterowniki PHP dla MongoDB
2

¨ Sterownik „mongo” (starszy)


¤ Wersje MongoDB od 2.4 do 3.0 włącznie
n Brak obsługi nowszych: 3.2, 3.4, 3.6…
¤ Wersje PHP do 5.3 do 5.6 włącznie
n Niedostępny dla PHP 7.x
¨ Sterownik „mongodb” (nowszy)
¤ Wszystkie wersje MongoDB od 2.4 wzwyż
¤ Wszystkie wersje PHP od 5.4 wzwyż

¨ Tabela kompatybilności wersji MongoDB z wersjami


sterowników i wersjami PHP:
https://docs.mongodb.org/ecosystem/drivers/php/
Sterowniki PHP dla MongoDB
3

¨ Sterowniki różnią się pod względem API


¤ Należy uważać szukając przykładów/tutoriali/rozwiązań
problemów w Internecie
¤ Przykłady ze strony przedmiotu (eNauczanie) dotyczą
nowszego sterownika „mongodb” i PHP 7.x
n Maszyna wirtualna zawiera sterownik „mongodb” i PHP 7
¨ Sterownik „mongodb” oferuje niskopoziomowy
interfejs do komunikacji z bazą danych
¨ Biblioteka mongo-php-library oferuje wygodniejsze
dla dewelopera wysokopoziomowe API
¤ Należy dodać ją do zależności projektu
4 Composer
Zarządzanie zależnościami projektu
Zależności projektu
5

¨ Zależności naszego projektu zazwyczaj


posiadają własne zależności
¤ My używamy bibliotek, aby
przyspieszyć swoją pracę
¤ Autorzy bibliotek używają innych
bibliotek, aby przyspieszyć swoją
¨ Powstaje drzewo zależności
II poziom zależności …
I poziom zależności


nasz …
projekt




Zależności projektu
6

¨ Zależnościami można zarządzać ręcznie


1. Google.com – szukamy strony projektu
2. Wchodzimy na stronę biblioteki
3. Dział Downloads
4. Pobieramy wersję dystrybucyjną (np. archiwum zip)
5. Rozpakowujemy
6. Kopiujemy pliki biblioteki do naszego projektu
7. I tak dla każdej zależności w drzewie…
¨ Ręczne zarządzanie zależnościami jest czasochłonne,
kłopotliwe i po prostu nudne
Automatyczne zarządzanie zależnościami
7

¨ Narzędzie Composer automatyzuje zarządzanie


zależnościami projektu
¨ Należy zdefiniować zależności I poziomu,
przykładowo:

$ composer require mongodb/mongodb "^1.1"

¨ Nazwa wskazanej biblioteki i jej wersja zostają


dopisane do pliku composer.json
¤ composer.json – zawiera listę zależności I poziomu
Automatyczne zarządzanie zależnościami
8

¨ Composer buduje drzewo zależności projektu


¨ …a następnie automatycznie pobiera wszystkie
wymagane biblioteki
¤ Podkatalog vendor – zawiera zewnętrzne zależności
projektu (3rd party)
¤ Skrypt vendor/autoload.php – umożliwia automatyczne
ładowanie klas z zewnętrznych bibliotek
¨ Zapisany zostaje tzw. lockfile (composer.lock)
¤ lockfile
zawiera informacje o dokładnych wersjach
wszystkich pobranych bibliotek
n Również zależności poziomu II oraz dalszych
Struktura projektu
9

📂/ # główny katalog projektu


├⎯📄 composer.json
├⎯📄 composer.lock
├⎯📂 vendor/ # biblioteki 3rd party
│ ├⎯📄 autoload.php
│ ├⎯📂 composer/
│ ├⎯📂 mongodb/
│ :
├⎯📂 src/ # nasz kod źródłowy
│ ├⎯📄 skrypt.php
│ ├⎯📂 web/ # DocumentRoot
10 MongoDB
MongoDB
11

¨ Baza typu NoSQL


¤ Rezygnacja z gwarancji zapewnianych przez bazy
relacyjne na rzecz innych właściwości
¨ Dane o dynamicznej strukturze
¤ Nie występuje z góry zdefiniowany schemat dla
przechowywanych informacji
¨ Baza dokumentowa
¤ Dokument jako podstawowy nośnik informacji
Dokument
12

¨ Dokument: zbiór par klucz à wartość


¨ Możliwe wartości:
¤ Dane skalarne
¤ Tablice

¤ Inne dokumenty – dokumenty zagnieżdżone


Dokument – reprezentacja JSON
13

{
"nazwa": "Laptop XYZ",
"producent": "ABC123",

"porty": ["4 USB", "HDMI", "Ethernet"],

"specyfikacja": {
"CPU": "Intel i7",
"RAM": "8 GB",
"HDD": "1 TB"
}
}
Dokument – reprezentacja w PHP
14

<?php
$dokument = [
"nazwa" => "Laptop XYZ",
"producent" => "ABC123",

"porty" => ["4 USB", "HDMI", "Ethernet"],

"specyfikacja" => [
"CPU" => "Intel i7",
"RAM" => "8 GB",
"HDD" => "1 TB"
]
];
Kolekcja, baza danych, instancja
15

¨ Zbiór dokumentów tego samego typu tworzy


kolekcję, np.:
¤ Kolekcja produktów w sklepie
¤ Kolekcja zamówień

¨ Wiele kolekcji składa się na bazę danych:


¤ Logicznie powiązane ze sobą kolekcje, np. wszystkie
kolekcje z danymi sklepu internetowego
¨ Pojedyncza instancja MongoDB może hostować
wiele baz danych
¤ Osobne bazy danych pozwalają odseparować od
siebie dane różnych aplikacji
Dokument, kolekcja, baza danych, instancja
16

Instancja MongoDB

… bazy
danych
sklep finanse CRM

użytkownicy zamówienia produkty kolekcje

dokumenty
Dynamiczna struktura danych
17

¨ Nie trzeba definiować kolekcji – zostaną


automatycznie dodane przy pierwszym użyciu
¨ Nie trzeba definiować a priori struktury
dokumentów
¤ Dokumenty budowane ad hoc w zależności od kontekstu
¤ Nie trzeba dostosowywać danych do struktury bazy –
to baza dostosowuje się do otrzymywanych danych
¨ W jednej kolekcji mogą znajdować się dokumenty
o różnej strukturze
¤ np. z polami opcjonalnymi
18 API w PHP do pracy z MongoDB
Połączenie z MongoDB
19

function get_db()
{
$mongo = new MongoDB\Client(
"mongodb://localhost:27017/wai",
[
'username' => 'wai_web',
'password' => 'w@i_w3b',
]);

$db = $mongo->wai;

return $db;
}
Zapisywanie dokumentów
20

$db = get_db();

//dokument opisujący produkt w sklepie:


$product = [
'name' => 'Laptop XYZ',
'price' => 2999,
'manufacturer' => 'ABC',
'description' => 'Ładny laptop.'
];

//zapis do kolekcji products:


$db->products->insertOne($product);

Kolekcja zostanie dodana,


jeśli wcześniej nie istniała
Identyfikator dokumentu
21

¨ Każdy dokument w bazie MongoDB posiada


identyfikator w postaci pola _id
¨ Jeśli pole _id nie zostanie określone jawnie, baza
doda je automatycznie i przydzieli unikalny
identyfikator:
{
"_id": ObjectId("56059e41b80de4f3478b4567"),
"name": "Laptop XYZ",
"price": NumberLong(2999),
"manufacturer": "ABC",
"description": "Ładny laptop."
}
Wyszukiwanie dokumentów
22

$db = get_db();

//wyszukiwanie bez kryteriów dopasowania,


//zwraca wszystkie elementy:
$products = $db->products->find();

Zwrócony kursor umożliwia


iterowanie po wynikach

foreach ($products as $product) {


echo $product['name'] . '<br/>';
}
Wyszukiwanie dokumentów
23

¨ Wyniki można zawęzić wyszukując poprzez przykład


(ang. query by example)
¨ Należy przygotować przykład dokumentu, który ma
zostać odnaleziony
¤ Dokument,
który przypomina spodziewane rezultaty
wyszukiwania
¨ Tak przygotowany przykład należy przekazać jako
kryterium wyszukiwania
Wyszukiwanie by example
24

¨ Cel: wyszukanie towarów w cenie 2999 PLN od


producenta ABC123
¨ Przykład dokumentu: Koniunkcja
$query = [ warunków
'price' => 2999,
'manufacturer' => 'ABC123',
]; Pozostałe pola
dowolnej wartości
¨ Wyszukanie pasujących dokumentów:
$products = $db->products->find($query);
Wyszukiwanie na podstawie _id
25

use MongoDB\BSON\ObjectID; Identyfikator


//... w postaci
$id = "56059e41b80de4f3478b4567"; tekstowej

$query = [
'_id' => new ObjectId($id)
];
Identyfikator bazodanowy

$product = $db->products->findOne($query);

Oczekiwany
pojedynczy rezultat
Operatory wyszukiwania
26

¨ Poza dopasowaniem dokładnych wartości pól


dokumentów, przydają się też dodatkowe operatory
¤ np. wyszukanie towarów w cenie 2500 – 3000 PLN

$query = [
'price' => [
'$gt' => 2500,
'$lt' => 3000
]
];

$products = $db->products->find($query);
Operator alternatywy
27

$products = $db->products->find([
'$or' => [
['price' => ['$lt' => 3000]],
['manufacturer' => 'Apple'],
]
]);

¨ Wyszukanie produktów:
których cena nie przekracza 3000 zł
LUB
wyprodukowanych przez firmę Apple
Wyszukiwanie wyrażeniem regularnym
28

¨ Cel: wyszukać produkty, których nazwa zawiera


frazę „laptop”
Dopasowanie
do pola name
dokumentu
$query = [ 'name' =>
['$regex' => 'laptop', '$options' => 'i']
];
Przy użyciu case insensitive
Szukana
wyrażenia ignorowanie
fraza
regularnego wielkości liter
$products = $db->products->find($query);
Warunki z dokumentami zagnieżdżonymi
29

¨ Warunki mogą odnosić się $product = [


do wartości pól dokumentów "nazwa" => "Laptop",
zagnieżdżonych //...
"specs" => [
¨ Składnia dot notation "CPU" => "Intel i7",
pozwala trawersować "RAM" => "8 GB",
w głąb dokumentów "HDD" => "1 TB"
zagnieżdżonych ]
];

$results = $db->products->
find(['specs.CPU'=>'Intel i7']);
dot notation
Ograniczenie liczby wyników
30

Pominięcie pierwszych
$opts = [ 10 wyników
'skip' => 10,
'limit' => 5 Ograniczenie do
]; maksymalnie 5 wyników

$products=$db->products->find($query, $opts);

foreach ($products as $product) {


//...
}
Stronicowanie
31

$page = 3;
$pageSize = 3;
$opts = [
'skip' => ($page - 1) * $pageSize,
'limit' => $pageSize
];
$users = $db->users->find([], $opts);

foreach ($users as $user) {


//...
}
Sortowanie
32

¨ Produkty w kolejności od najtańszego do


Według ceny
najdroższego: rosnąco
$opts = ['sort' => ['price' => 1]];
$products = $db->products->find([], $opts);

¨ Sortowanie wielokryterialne:
$opts = [
'sort' => [
'price' => -1, Według ceny malejąco
'name' => 1 Jeśli ceny są takie same:
] według nazwy rosnąco
];
$products = $db->products->find([], $opts);
Aktualizacja: podmiana całego dokumentu
33

$id = '5605b1e9b80de4f1478b4571';
$query = ['_id' => new ObjectId($id)];

//pobranie dokumentu:
$product = $db->products->findOne($query);
//nowa cena:
$product['price'] = 2699;

//podmiana dotychczasowego dokumentu na nowy:


$db->products->replaceOne($query, $product);
Aktualizacja: wiele dokumentów
34

$query = [
'name' => [
'$regex' => 'laptop',
'$options' => 'i’
]
]; Aktualizowane
pola
$newVals = ['price' => 999];

$db->products->
updateMany($query,['$set' => $newVals]);

$set: aktualizuje wskazane pola,


inne pozostawia niezmienione
Usuwanie dokumentów
35

use MongoDB\BSON\ObjectID;

$id = '5605b1e9b80de4f1478b4571';
$query = ['_id' => new ObjectId($id)];

$db->products->deleteOne($query);
Przykład: 02-mongodb
37 Pytania?
1

OBSŁUGA ŻĄDAŃ HTTP


GET – POST – FORMULARZE – REDIRECT
UPLOAD PLIKÓW – COOKIES
Waldemar Wytwarzanie Aplikacji Internetowych
Korłub KASK ETI Politechnika Gdańska
Interakcja z użytkownikiem
2

¨ Podstawową motywacją dla aplikacji po stronie


serwera jest konieczność interakcji z użytkownikiem
¤ Reagowanie na akcje użytkownika
¤ Obsługa danych podawanych przez użytkownika

¤ Spersonalizowane treści, uzależnione od wyborów


użytkownika
¨ Protokół HTTP dostarcza mechanizmy wymiany
danych między przeglądarką i serwerem
¨ PHP oferuje dostęp do danych w żądaniach HTTP
i możliwość sterowania odpowiedziami
à API do obsługi żądań HTTP
Rodzaje zapytań HTTP
3

¨ Przeglądarki wykorzystują głównie dwa rodzaje


zapytań HTTP:
¤ GET– pobieranie informacji, bez skutków ubocznych
¤ POST – wysyłanie informacji na serwer

¨ Pozostałe metody są rzadziej wykorzystywane


¤ OPTIONS – negocjacje CORS (Cross-Origin Resource
Sharing)
¤ PUT, DELETE, HEAD – tylko poprzez XMLHttpRequest

¤ TRACE – rzadko obsługiwane przez serwery


n 405 Method Not Allowed
n 501 Not Implemented
GET i POST
4

¨ GET
¤ Nawigacja pomiędzy stronami za pomocą odnośników:
<a href="...">
¤ Pobieranie zasobów, m.in.:
n <img src="plik.png">
n <link href="main.css" rel="stylesheet" .../>
n <script src="main.js">
¤ Obsługa formularzy: <form method="get">
¤ Redirect HTTP 303 See other

¨ POST
¤ Obsługa formularzy: <form method="post">
¤ Redirect HTTP 307 Temporary Redirect
n Jeśli oryginalne zapytanie zostało wysłane metodą POST
GET – dodatkowe parametry
5

¨ Parametry – dołączone do identyfikatora URI –


mają doprecyzować zapytanie użytkownika

Parametry występują Parametry postaci:


po znaku zapytania nazwa=wartość

http://example.com/search.php?query=kot

Kolejne parametry
rozdzielone znakiem &

/products.php?cat=laptops&producent=xyz
GET – parametry w adresie
6

¨ Zapisywane w bookmarkach
¤ Odnośniki bezpośrednie (ang. permalinks) Nie należy
¨ Zapamiętywane w historii przeglądarki przekazywać
danych
¨ Zachowywane przy kopiowaniu adresu
wrażliwych!
¨ Mogą być zapisane w logach serwera
¨ Wysyłane przy każdym odświeżeniu strony
¨ Ograniczony rozmiar parametrów
¤ Max długość adresu URL w przeglądarkach/klientach
n Standard HTTP nie definiuje ograniczenia
n Z empirycznych doświadczeń: ok. 2000 znaków
GET
7

¨ Zapytania typu GET powinny być bezpieczne i co za


tym idzie idempotentne
¤ Bezpieczne
n Nie ma żadnych skutków ubocznych po stronie serwera
n Służy pobieraniu informacji
¤ Idempotentne
n Skutki uboczne wielu identycznych zapytań są takie same jak
skutki pojedynczego zapytania
n Zapytanie bezpieczne jest siłą rzeczy idempotentne

¨ Dlaczego?
¤ Kliknięcie w bookmark, odświeżenie strony,
wysłanie linku do innej osoby
¤ Cachowanie odpowiedzi
POST
8

¨ Parametry przekazywane w ciele żądania HTTP


POST /wai/example.php HTTP/1.1
Accept: */*
Content-Length: 104
Content-Type: application/x-www-form-urlencoded;
charset=utf-8
Host: 192.168.199.11

tytul=Wodospad+Skogafoss&autor=WK&ocena=9&opis=J
eden+z+najbardziej+malowniczych+wodospad%C3%B3w+
Islandii
POST
9

¨ Zapytanie typu POST nie musi być ani bezpieczne


ani idempotentne
¤ Modyfikowanie stanu po stronie serwera
¨ Nie-bookmarkowalne
¨ Nie-cachowalne
¨ Przy odświeżeniu strony przeglądarka powinna
ostrzegać o ponownym wysyłaniu danych
¨ Parametry nie trafiają do logów serwera WWW
¨ Nie ma limitu na rozmiar parametrów
GET i POST – podsumowanie
10

¨ GET
¤ Pobieranie informacji z serwera
n np. wyświetlenie informacji o produkcie
¤ Parametry doprecyzowują zapytanie użytkownika
n np. o który produkt chodzi?

¨ POST
¤ Zmieniają
stan po stronie serwera
¤ Wyzwalają logikę biznesową aplikacji
n np. złożenie zamówienia i realizacja płatności
¤ Parametry są argumentami dla logiki biznesowej
n np. jakie produkty wchodzą w skład zamówienia?
11 Obsługa formularzy w PHP
…i parametrów żądań w ogólności
Parametry GET
12

products.php?cat=laptops&producent=xyz
echo $_GET['cat']; laptops
echo $_GET['producent']; xyz
echo $_GET['sku'];
Notice: Undefined index: sku
in example.php on line 9

Test obecności
if(!empty($_GET['sku'])){
parametru
$sku = $_GET['sku'];
echo "Wybrano produkt o id: $sku";
} else {
echo "Nie określono parametru";
}
Tablica $_GET
13

¨ Daje dostęp do wszystkich parametrów zapytania


typu GET
¨ Zmienna superglobalna
¤ Dostępna z każdego miejsca w kodzie, bez używania
słowa kluczowego global
Parametry POST
14

<form method="post">
<label>
<span>Tytuł:</span>
<input type="text" name="tytul"/>
</label>

<label>
<span>Autor:</span>
<input type="text" name="autor"/>
</label>

<textarea placeholder="Opis..."
name="opis"></textarea>

<input type="submit" value="Zapisz"/>


</form>
Parametry POST
15

<input type="text" name="tytul"/>


<?php
$tytul = $_POST['tytul'];
$autor = $_POST['autor'];
$opis = $_POST['opis'];

//zapisanie do bazy danych...


?>
<div>
<h1><?= $tytul ?></h1>
<span>Autor: <?= $autor ?></span>

<p><?= $opis ?></p>


</div>
Obsługa formularzy
16

<input type="text" name="tytul"/>


1. GET – wyświetlenie formularza

2. POST – submit

<?php
$tytul = $_POST['tytul'];

3. Wyświetlenie wyników*

* Docelowo z wykorzystaniem
idiomu POST-REDIRECT-GET
Jakie żądanie trafiło na serwer?
17

¨ W wielu sytuacjach istotne jest, czy serwer otrzymał


żądanie GET czy POST
¨ Tablica superglobalna $_SERVER zawiera
informacje o kontekście wywołania skryptu PHP
if($_SERVER['REQUEST_METHOD'] === 'POST'){

//żądanie POST

} else {

//najpewniej GET

}
Formularze: pole tekstowe
18

<input type="text" name="tytul"/>

<?php
$tytul = $_POST['tytul'];
Formularze: pole hasła
19

<input type="password" name="pass"/>

<?php
$password = $_POST['pass'];
Formularze: pole radio
20

<span>Płeć:</span>
<label>
<input type="radio"
name="plec"
value="mezczyzna"/>
Mężczyzna
</label>
<label> <?php
$plec = $_POST['plec'];
<input type="radio"
name="plec"
value="kobieta"/> mezczyzna
Kobieta
</label>
Formularze: checkboksy
21

<span>Kategoria:</span>
<label>
<input type="checkbox"
name="kategorie[]"
value="akcja"/> Akcja
</label> <?php
<label> $kategorie =
<input type="checkbox"
$_POST['kategorie'];
name="kategorie[]"
value="dramat"/> Dramat
print_r($kategorie);
</label>
<label> Array
<input type="checkbox" (
name="kategorie[]" [0] => akcja
value="komedia"/> Komedia [1] => komedia
</label> )
Formularze: checkboksy
22

<span>Kategoria:</span>
<label>
<input type="checkbox"
name="kategorie[akcja]"
value="true"/> Akcja
</label> <?php
<label> $kategorie =
<input type="checkbox"
$_POST['kategorie'];
name="kategorie[dramat]"
value="true"/> Dramat
print_r($kategorie);
</label>
<label> Array
<input type="checkbox" (
name="kategorie[komedia]" [akcja] => true
value="true"/> Komedia [komedia] => true
</label> )
Formularze: pole ukryte
23

<input type="hidden" name="id"/>

Nie wyświetla się w przeglądarce

<?php
$id = $_POST['id'];
Formularze: pole nieaktywne
24

<input type="text" name="tytul"


value="AP1784"
disabled="disabled"/>

Niedostępne w PHP – przeglądarka nie wysyła


wartości pól oznaczonych jako disabled!
Formularze: upload plików
25

<form method="post"
enctype="multipart/form-data">

<input type="file" name="zdjecie"/>

<input type="submit" value="Wyślij"/>


</form>
Upload plików
26

¨ Informacje o przesłanych plikach dostępne są


w tablicy superglobalnej $_FILES:
<?php
$zdjecie = $_FILES['zdjecie'];
print_r($zdjecie);

Array (
[name] => giraffe.jpg
[type] => image/jpeg
[tmp_name] => /tmp/php1gzN7z
[error] => 0
[size] => 50094
)
Informacje o nadesłanym pliku
27

¨ name – oryginalna nazwa pliku


¨ type – typ MIME odczytany z nagłówków żądania
HTTP (typowo określony na bazie rozszerzenia pliku)
¨ tmp_name – lokalizacja pliku w katalogu
tymczasowym na serwerze
¨ size – rozmiar pliku print_r($_FILES['zdjecie'])
Array (
¨ error – informacja [name] => giraffe.jpg
o ewentualnych [type] => image/jpeg
[tmp_name] => /tmp/php1gzN7
błędach uploadu [error] => 0
[size] => 50094
)
Obsługa nadesłanego pliku
28

¨ Pliki umieszczane są początkowo w lokalizacji


tymczasowej
¨ Jeśli pliki mają być trwale zapisane na serwerze,
należy je przenieść do lokalizacji docelowej
¤ Uwaga na uprawnienia do katalogu docelowego
Obsługa nadesłanego pliku
29

$upload_dir = '/var/www/dev/web/upload/';

$file = $_FILES['zdjecie'];
$file_name = basename($file['name']);

$target = $upload_dir . $file_name;

$tmp_path = $file['tmp_name'];

if(move_uploaded_file($tmp_path, $target)){
echo "Upload przebiegł pomyślnie!\n";
}
Sprawdzanie typu MIME pliku
30

¨ Nie można polegać na typie MIME odczytanym


z nagłówków żądania HTTP
¤ Zmylenie przeglądarki zmianą rozszerzenia pliku
¤ Spreparowanie złośliwego żądania przez napastnika

¨ Należy sprawdzić sygnaturę pliku (ang. magic number):


$finfo = finfo_open(FILEINFO_MIME_TYPE);
$file_name = $_FILES['zdjecie']['tmp_name'];
$mime_type = finfo_file($finfo, $file_name);

if ($mime_type === 'image/jpeg') {


echo 'Poprawny format.';
}
31 Idiom POST-REDIRECT-GET
GET, POST i… nic więcej
32

<?php przelew.php
if($_SERVER['REQUEST_METHOD']==='POST' &&
!empty($_POST['nr_konta'])/* && ... */
) {
$nr_konta = $_POST['nr_konta'];
//...

//zlecenie przelewu

echo "Status: przyjęty do realizacji";


} else { ?>
<form method="post">
<input type="text" name="nr_konta"/>
<!-- ... -->
<input type="submit" value="OK"/>
</form>
<?php } ?>
GET przelew.php
33
false
<?php
if($_SERVER['REQUEST_METHOD']==='POST' &&
!empty($_POST['nr_konta'])/* && ... */
) {
$nr_konta = $_POST['nr_konta'];
//...
Wykonanie części else:
//zlecenie przelewu wyświetlenie formularza

echo "Status: przyjęty do realizacji";


} else { ?>
<form method="post">
<input type="text" name="nr_konta"/>
<!-- ... -->
<input type="submit" value="OK"/>
</form>
<?php } ?>
POST przelew.php
34
true
<?php Sprawdzenie
if($_SERVER['REQUEST_METHOD']==='POST' && poprawności
!empty($_POST['nr_konta'])/* && ... */ danych: true
) {
$nr_konta = $_POST['nr_konta'];
//...
Wykonanie
//zlecenie przelewu
logiki
biznesowej
echo "Status: przyjęty do realizacji";
} else { ?>
<form method="post">
<input type="text" name="nr_konta"/>
<!-- ... -->
<input type="submit" value="OK"/>
</form>
<?php } ?>
Użytkownik klika Odśwież (F5)
35

¨ Użytkownik chce sprawdzić, czy status przelewu się


zmienił: klika Odśwież
¨ Przeglądarka ponawia poprzednie zapytanie:
POST przelew.php z takimi samymi parametrami
<?php
if($_SERVER['REQUEST_METHOD']==='POST' &&
true
!empty($_POST['nr_konta'])/* && ... */
) {
$nr_konta = $_POST['nr_konta'];
//... Wykonanie
logiki
//zlecenie przelewu
biznesowej
echo "Status: przyjęty do realizacji"; PO RAZ
} else { ?> <!-- ... --> <?php } ?> DRUGI!
Problem wielokrotnego submitu
36

<form method="post"> POST przelew.php


<!-- ... -->
</form>
Zlecenie
200 OK przelewu

Status: przyjęty
do realizacji Odśwież
POST przelew.php
POST i przycisk Odśwież
37

¨ Współczesne przeglądarki ostrzegają przed


ponownym wysłaniem zapytania POST
¤ Gdyby tylko użytkownicy czytali komunikaty…
¤ …i wiedzieli jak je interpretować
POST i zmiany stanu
38

¨ Żądanie POST, które zmieniło stan po stronie


serwera, nie powinno zwracać informacji dla
użytkownika, a jedynie odpowiedź Redirect
(grupa 3xx) dla przeglądarki
¨ Przeglądarka zrealizuje przekierowanie pod adres
umieszczony w nagłówku Location
¤ Docelowa strona powinna prezentować status
wykonanej operacji
¨ Jeśli nie nastąpiła zmiana stanu, przekierowanie nie
jest konieczne
¤ np. błędnie wypełniony formularz
Idiom POST-REDIRECT-GET
39

<form method="post"> POST przelew.php


<!-- ... -->
</form>
Zlecenie
302 Found przelewu
Location: status.php?id=17
Obsługa
przekierowania GET status.php?id=17
Pobranie
200 OK statusu

Status: przyjęty Odśwież


do realizacji GET status.php?id=17
POST-REDIRECT-GET
40

<?php przelew.php
if ($_SERVER['REQUEST_METHOD']==='POST' &&
!empty($_POST['nr_konta']) /* ... */
) {
$nr_konta = $_POST['nr_konta'];//...

//zlecenie przelewu Identyfikator zlecenia


$id = /* ... */;
Strona statusu
$url = "status.php?id=$id";
header("Location: $url");
Przekierowanie
exit; HTTP 302
} ?>
Zakończenie skryptu
<form method="post">
<!-- ... -->
</form>
Strona statusu
41

status.php

<?php
$id = $_GET['id'];
$przelew = /* pobranie z bazy danych */;
echo "Status: " . $przelew['status'];
Przekierowania, nagłówki i ciało
42
odpowiedzi HTTP
¨ Przekierowania (3xx) są realizowane poprzez
nagłówki odpowiedzi HTTP
¤ Kododpowiedzi, np. 302
¤ Nagłówek Location

HTTP/1.1 302 Found


Content-Length: 0
Content-Type: text/html; charset=UTF-8
Location: status.php
Server: Apache
...
Przekierowania, nagłówki i ciało
43
odpowiedzi HTTP
¨ Nagłówki i kod odpowiedzi muszą być ustawione
przed rozpoczęciem emitowania ciała odpowiedzi
(dokumentu HTML)
¨ Rozpoczęcie emitowania ciała odpowiedzi
powoduje wysłanie nagłówków
¨ Próba zmiany nagłówków po rozpoczęciu
emitowania ciała zakończy się niepowodzeniem
i komunikatem:
„Cannot modify header information – headers
already sent”
Struktura odpowiedzi HTTP
44

HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Length: 283 nagłówki
Content-Type: text/html; charset=UTF-8
Server: Apache

<!DOCTYPE html>
<html>
<head>
<title>Przelew</title>
</head>
<body> ciało
<form method="post">
<!-- ... -->
</form>
</body>
</html>
Ciało odpowiedzi HTTP
45

¨ Dowolna treść na standardowym wyjściu skryptu


PHP jest traktowana jako ciało odpowiedzi
¨ Uwaga na białe znaki – one również traktowane są
jako ciało odpowiedzi HTTP
¤ Znakinowego wiersza
¤ Spacje

¤ Znak BOM
Buforowanie odpowiedzi
46

¨ Ustawienie output_buffering w php.ini


¨ Ustawienie zależne od konfiguracji serwera
¤ Włączenie/wyłączenie buforowania, rozmiar bufora
¨ Standardowe wyjście jest buforowane przed
przekazaniem do serwera WWW
¨ Pozwala częściowo obejść problem
„headers already sent”, ale nie stanowi rozwiązania
¤ Jedynym solidnym rozwiązaniem jest prawidłowa struktura
skryptów!
¨ Głównym celem buforowania jest poprawa wydajności
komunikacji: interpreter PHP <=> serwer WWW
¤ …a nie zamiatanie pod dywan błędów programisty
Prawidłowa struktura skryptów PHP
47

¨ Wszelkie operacje zmieniające nagłówki lub kod


odpowiedzi wykonywane przed kodem HTML
¨ Bloki PHP rozpoczynane w pierwszym wierszu pliku
¤ Bez znaków nowego wiersza przed <?php
¤ Bez znaku BOM

¨ Kod HTML dopiero po wykonaniu całej logiki


biznesowej i logiki obsługi żądania
¤ Więcej na wykładzie o przepływie sterowania
w aplikacjach internetowych
¨ W plikach zawierających wyłącznie kod PHP
(np. funkcje narzędziowe) pominięty znacznik ?>
48 HTTP Cookies
HTTP Cookies
49

¨ Umożliwiają zapisanie informacji po stronie


przeglądarki użytkownika
¨ Są dołączane do każdego zapytania, kierowanego
pod adres, z którego przeglądarka je otrzymała
¤ Cookies o dużym rozmiarze znacząco zwiększają
rozmiar każdego zapytania HTTP!
¨ Cookies są ustawiane przez nagłówki HTTP – muszą
być ustawione przed rozpoczęciem emitowania
treści strony
Zapisywanie informacji w cookies
50

<?php
$imie = 'Waldemar';

//o zasięgu sesji przeglądarki:


setcookie("imie_session", $imie);

nazwa wartość

//z podanym czasem ważności i zakresem:


setcookie("imie", $imie, time()+3600, "/");

nazwa wartość czas ważności: zakres:


timestamp cała domena
Cookies w odpowiedzi HTTP
51

HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Length: 274
Content-Type: text/html; charset=UTF-8
Server: Apache
Set-Cookie: imie=Waldemar;
expires=Thu, 24-Sep-2015 20:56:13 GMT;
path=/
Set-Cookie: imie_session=Waldemar
X-Powered-By: PHP/5.4.45-0+deb7u1

...
Odczytywanie cookies
52

Sprawdzenie
dostępności
cookie
if (isset($_COOKIE['imie'])) {

$imie = $_COOKIE['imie'];
}
Pobranie
wartości
cookie
Usuwanie cookies
53

¨ Nadpisanie cookie z czasem ważności w przeszłości


¤ Wszystkie parametry poza wartością cookie muszą być
identyczne jak w oryginalnym wywołaniu setcookie()
setcookie("imie", $imie, time() + 3600, "/");

setcookie("imie", '', time() – 3600*24, "/");

¨ Podanie false jako wartości


¤ Wszystkie parametry poza wartością i czasem
ważności muszą być identyczne jak w oryginalnym
wywołaniu setcookie()
setcookie("imie", false);
Przykład: 01-cookies
Tablica superglobalna $_REQUEST
55

¨ Zawiera wszystkie parametry z tablic $_GET i


$_POST (oraz opcjonalnie $_COOKIE)
¨ Przydatna, gdy nie ma znaczenia w jaki sposób
parametr został przesłany
¨ Konfigurowana w php.ini:
¤ request_order = "GP" – domyślne ustawienie
n Najpierw GET, potem POST, parametry o tej samej nazwie
nadpisują poprzednią wartość
¤ request_order = "GCP" – uwzględnia również dane
z cookies
Przepływ sterowania
56

Przeglądarka 1. Żądanie HTTP Serwer HTTP

GET, POST, parametry żądania

5. Odpowiedź HTTP
2. Lokalizacja
zasobu

3. Wywołanie skryptu PHP

Parametry, nagłówki żądania,


pliki cookies
Skrypt PHP
57 Pytania?
PHP: WPROWADZENIE
KRÓTKA HISTORIA
CHARAKTERYSTYKA JĘZYKA
PODSTAWOWE ELEMENTY SKŁADNIOWE
Waldemar Wytwarzanie Aplikacji Internetowych
Korłub KASK ETI Politechnika Gdańska
Dlaczego PHP?
2

¨ Powszechnie powtarzane przesądy na temat PHP:


¤ PHP umiera (jako język)
¤ Nikt już nie używa PHP

¤ Wszyscy przepisują stare aplikacje w PHP na


Node.js/Ruby on Rail/Django/Springa/dowolny inny
język bądź framework jaki pojawił się na rynku
w ciągu ostatnich 20 lat
¤ Nikt nie wybiera PHP do realizacji nowych projektów
Znaczenie PHP we współczesnym
3
Internecie: listopad 2017

Źródło: https://w3techs.com/technologies/overview/programming_language/all
Znaczenie PHP we współczesnym
4
Internecie: październik 2016

Źródło: https://w3techs.com/technologies/overview/programming_language/all
Znaczenie PHP we współczesnym
5
Internecie: wrzesień 2015

Źródło: https://w3techs.com/technologies/overview/programming_language/all
6
Internecie: listopad 2017
Znaczenie PHP we współczesnym

Źródło:
http://w3techs.com/technologies/market/programming_language
7
Internecie: październik 2016
Znaczenie PHP we współczesnym

Źródło:
http://w3techs.com/technologies/market/programming_language
Rynek pracy: 7.11.2017
8
Rynek pracy: 7.11.2017
9
Dlaczego PHP?
10

¨ Łatwy do nauki
¨ Mnogość bibliotek i rozszerzeń
¨ Łatwy dostęp do hostingu
¤ Ogromna liczba darmowych serwisów
¨ Dynamiczny rynek frameworków
¨ Łatwość znalezienia pracy

¨ Pogłoski o śmierci PHP krążą po świecie od 20 lat


¤ …a PHP dzielnie napędza większość stron
internetowych
11 Krótka historia
Krótka historia: przed PHP
12

¨ Początki WWW: plain HTML – 1991


¤ Statyczne strony
¤ Ten sam dokument serwowany za każdym
razem, niezależnie od kontekstu
¤ Brak możliwości generowania treści w sposób
dynamiczny
Krótka historia: przed PHP
13

¨ CGI – Common Gateway Interface – 1993


¤ Wywołanie aplikacji napisanej w dowolnym
języku ogólnego przeznaczenia
¤ Wyjście aplikacji odpowiedzią dla
przeglądarki
¤ Łatwe modelowanie logiki przetwarzania
zapytań
¤ Kłopotliwe generowanie dokumentów HTML
¤ Aplikacja generuje dokument hipertekstowy
Krótka historia: przed PHP
14

¨ SSI – Server Side Includes


¤ Zestaw komend umieszczanych w komentarzach
dokumentu HTML
¤ Serwer przetwarza komendy przed odesłanie
odpowiedzi do przeglądarki
¤ Pozwala na wywołanie skryptu CGI

¤ Dokument hipertekstowy z dołączonymi


elementami dynamicznymi
Krótka historia
15

¨ PHP 1.0 – 1995, Rasmus Lerdorf


¤ Oryginalnie zestaw aplikacji dla CGI
¤ Początkowo PHP nie miał być językiem programowania

¨ PHP 2.0 – 1996-1997


¤ Dynamiczny rozwój w stronę samodzielnego języka
¤ Instrukcje osadzone w komentarzach HTML

¨ PHP 3.0 – 1998


¤ Pierwsza wersja przypominająca współczesny język PHP
¤ Łatwe rozszerzanie języka o nowe moduły

¤ Podstawowa obsługa programowania obiektowego


Krótka historia
16

¨ PHP 4.0 – 2000


¤ Zend Engine, znaczna poprawa wydajności
¤ CLI – interfejs dla wiersza poleceń

¨ PHP 5.0 – 2004


¤ Zend Engine 2.0, poprawa wydajności
¤ Nowy model obiektowy
¤ 5.1 – 2005 – PDO
¤ 5.2 – 2006 – obsługa formatu JSON
¤ 5.3 – 2009 – przestrzenie nazw, goto, domknięcia, PHAR
¤ 5.4 – 2012 – domieszki, wbudowany serwer HTTP
¤ 5.5 – 2013 – generatory, finally, OpCache w standardzie
¤ 5.6 – 2014 – funkcje o zmiennej liczbie parametrów
PHP 7.0
17

¨ Wydanie: grudzień 2015


¨ Główny nacisk na zwiększenie spójności języka
¤ Usunięcie wszystkich elementów przestarzałych
(ang. deprecated)
¤ Spójne wykorzystanie wyjątków do sygnalizacji
błędów czasu wykonania
¤ Jednolite zasady dereferencji zmiennych
n Zamiast zbioru wyjątków i przypadków szczególnych
¤ Działanie przesunięć bitowych uspójnione między
różnymi platformami
¤ Działanie rzutowań float à integer uspójnione między
różnymi platformami
PHP 7.0
18

¨ Zmiany niekompatybilne z wcześniejszymi wersjami


¤ Możliwe błędy w działaniu już istniejących aplikacji
¨ Istotne zmiany „pod maską”:
¤ Zend Engine 3.0 – znaczna poprawa wydajności
¤ Rozdzielenie parsera i kompilatora przez wprowadzenie
AST (Abstract Syntax Tree)
n Otwiera drogę dla nowych konstrukcji językowych
¨ Nowe rozwiązania, zwiększające siłę wyrazu języka
z punktu widzenia dewelopera
¤ Klasy anonimowe
¤ Typy skalarne w deklaracjach typów argumentów
¤ Deklaracje typów zwracanych
PHP 7.0 – jak szybko się przyjmie?
Listopad 2017
19 Źródło: http://w3techs.com/technologies/details/pl-php/5/all
PHP 7.0 – jak szybko się przyjmie?
Październik 2016
20 Źródło: http://w3techs.com/technologies/details/pl-php/5/all
21 Charakterystyka języka
PHP
22

¨ Język skryptowy z dynamicznym typowaniem


¤ Do PHP 3 – kod źródłowy interpretowany w czasie
działania aplikacji
¤ Od PHP 4
n Kod źródłowy kompilowany do kodu pośredniego
(nie natywnego) w momencie uruchomienia skryptu
n Kod pośredni wykonywany przez Zend Engine
n Kod pośredni może zostać zachowany pomiędzy
uruchomieniami dla zwiększenia wydajności
¤ Od PHP 5 – możliwość deklarowania typów argumentów
funkcji
¤ Od PHP 7 – możliwość deklarowania typów wartości
zwracanych z funkcji
PHP
23

¨ Język z garbage collectorem


¤ Automatyczny przydział i zwalnianie pamięci

¨ Język wieloparadygmatowy
¤ Imperatywny, proceduralny
¤ Obiektowy

¤ Funkcyjny

¤Z obsługą mechanizmu refleksji


24 Podstawowe elementy składniowe
Gdzie umieścić kod źródłowy?
25

¨ Typowo pliki z rozszerzeniem .php


¨ Kod PHP umieszczony w blokach:
<?php
...kod źródłowy...
?>

¨ Instrukcje w bloku <?php ... ?> wykonywane linia


po linii – nie ma funkcji main
¨ Pozostała zawartość pliku jest przekazywana
bezpośrednio na wyjście
¤ Również znaki niedrukowalne
n Poza znakiem nowego wiersza bezpośrednio po ?>
Inne znaczniki dla bloków PHP
26

¨ Znaczniki skrócone:
<?
...kod źródłowy...
?>

¨ Niezalecany
¤ Wymaga ustawienia short_open_tag w pliku
konfiguracyjnym php.ini à nieprzenośny
¤ Znacznik otwierający <? koliduje z preambułą XML:
<?xml version="1.0" encoding="utf-8"?>
¤ …oraz ze składnią instrukcji przetwarzania XML:
<?xml-stylesheet type="text/css" href="me.css"?>
Inne znaczniki dla bloków PHP
27

¨ Znaczniki w stylu ASP (do PHP 5.6):


<%
...kod źródłowy...
%>

¨ Niezalecany
¤ Wymaga ustawienia asp_tags w pliku
konfiguracyjnym php.ini à nieprzenośny
¤ Usunięte z języka od wersji PHP 7.0
Inne znaczniki dla bloków PHP
28

¨ Znacznik script (do PHP 5.6):


<script language="php">
...kod źródłowy...
</script>

¨ Niezalecany
¤ Usunięty z języka od wersji PHP 7.0
Inne znaczniki dla bloków PHP
29

¨ Skrócony znacznik echo:

<?= pojedyncze_wyrażenie ?>

¨ Od PHP 5.4 zawsze dostępny – niezależnie od


konfiguracji
¤ Wcześniej uzależniony od ustawienia short_open_tag
¨ Nie koliduje z instrukcjami przetwarzania XML:
<?= zamiast <?
¨ Szersze omówienie przy okazji instrukcji echo
Znaczniki zalecane – podsumowanie
30

¨ Znacznik pełny:
<?php
...kod źródłowy...
?>

¨ Skrócony znacznik echo (od PHP 5.4.0):


<?= pojedyncze_wyrażenie ?>
PHP w kontekście aplikacji internetowej
31

<!DOCTYPE html> index.php


<html>
<head>
<title>Strona główna</title>
</head>
<body>
<h1>Witaj świecie!</h1>
<p>
Wersja PHP:
<?php
echo phpversion();
?>
</p>
</body>
</html>
Przepływ sterowania
32

Przeglądarka użytkownika 1. Żądanie HTTP Serwer HTTP

GET /index.php

5. Odpowiedź HTTP
2. Lokalizacja
6. Wyświetlenie 4. Zwrócenie zasobu
odpowiedzi dokumentu
HTML

3. Wywołanie
skryptu PHP index.php
Treść wysyłana do przeglądarki
33

<!DOCTYPE html>
<html>
<head>
<title>Strona główna</title>
</head>
<body>
<h1>Witaj świecie!</h1>
<p>
Wersja PHP:
5.6.12-0+deb8u1
</p>
</body>
</html>
Przegląd składni
34

¨ Zmienne ¨ Tablice
¤ Podstawowe typy ¤ Proste zastosowania
¨ Stałe ¤ Odwzorowania
¤ const i define() klucz à wartość
¨ Instrukcja echo ¨ Dołączanie plików
¤ Skrócony znacznik echo ¤ include, include_once
¤ require, require_once
¨ Instrukcje warunkowe
¤ Operatory logiczne ¨ Funkcje
¤ if … else
¤ Nazwane i anonimowe
¤ Argumenty referencje
¤ switch
¤ Argumenty domyślne
¨ Pętle
¤ for, foreach ¨ Zmienne zmienne i funkcje
¤ While
¤ ang. variable variables
Zmienne
35

¨ Nazwy wszystkich zmiennych poprzedzone są


znakiem $
¨ Nazwa musi zaczynać się od litery lub znaku
podkreślenia, po którym następuje dowolna liczba
liter, cyfr lub znaków podkreślenia
¨ W nazwach zmiennych rozróżniana jest wielkość
liter
¨ Zmienne mogą być definiowane w dowolnym
miejscu
¨ Nie występują deklaracje typów
Zmienne – przykładowe definicje
36

<?php

$imie = "Imiesław"; //string


$nazwisko = 'Nazwiskowy'; //string
$wiek = 37; //integer
$wynik = 22.5; //float
$zakwalifikowany = true; //boolean
$kopia_wyniku = $wynik; //float
Ciągi znaków
37

¨ Sposoby definiowania:
¤W podwójnym cudzysłowie
¤ W pojedynczym cudzysłowie

¤ Składnia heredoc

¤ Składnia nowdoc

¨ Ciągi znaków mogą być wielolinijkowej niezależnie


od sposobu ich definiowania
Ciągi w podwójnym cudzysłowie
38

¨ Pozwalają na wykorzystywanie sekwencji


sterujących, np.:
¤ \n – znak końca wiersza
¤ \t – znak tabulacji

¤ \x41 – litera A (kod z tablicy ASCII)

¨ Są parsowane pod kątem występujących w nich


odwołań do zmiennych
Ciągi w podwójnym cudzysłowie
39

<?php

$imie = "Imiesław";
$nazwisko = 'Nazwiskowy';
$wiek = 37;
$wynik = 22.5;

$zdanie ="Użytkownik $imie uzyskał $wynik pkt";


//"Użytkownik Imiesław uzyskał 22.5 pkt"
Ciągi w pojedynczym cudzysłowie
40

¨ Nie są parsowane pod kątem zmiennych


¨ Obsługują jedynie dwie sekwencje sterujące:
¤ \' – pojedynczy apostrof
¤ \\ – pojedynczy backslash
Ciągi w pojedynczym cudzysłowie
41

<?php

$imie = "Imiesław";
$nazwisko = 'Nazwiskowy';
$wiek = 37;
$wynik = 22.5;

$zdanie ='Użytkownik $imie uzyskał $wynik pkt';


//'Użytkownik $imie uzyskał $wynik pkt'
Heredoc
42

¨ Oferuje parsowanie zmiennych i obsługę sekwencji


sterujących jak w przypadku podwójnego
cudzysłowu
¨ Pozwala na wygodniejsze definiowanie
wielowierszowych ciągów znaków
Heredoc
43

$imie = "Imiesław";
$nazwisko = 'Nazwiskowy';
$wiek = 37;
$wynik = 22.5;

$zdanie = <<<ETYKIETA
Użytkownik $imie $nazwisko ($wiek lat)\n
uzyskał wynik: $wynik pkt
ETYKIETA;

/*
* Użytkownik Imiesław Nazwiskowy (37 lat)
* uzyskał wynik: 22.5 pkt
*/
Nowdoc
44

¨ Nie obsługuje parsowania zmiennych ani żadnych


sekwencji sterujących
¤ Nawet tych, które występują dla ciągów
w pojedynczym cudzysłowie
¨ Składnia przypomina heredoc, jednak nazwa
etykiety musi być podana w pojedynczym
cudzysłowie
Nowdoc
45

$imie = "Imiesław";
$nazwisko = 'Nazwiskowy';
$wiek = 37;
$wynik = 22.5;

$zdanie = <<<'ETYKIETA'
Użytkownik $imie $nazwisko ($wiek lat)\n
uzyskał wynik: $wynik pkt
ETYKIETA;

/*
* Użytkownik $imie $nazwisko ($wiek lat)\n
* uzyskał wynik: $wynik pkt
*/
Operator konkatenacji
46

¨ Pozwala na budowanie ciągu znaków poprzez


połączenie kilku wyrażeń
¨ W języku PHP operatorem konkatenacji jest znak
kropki .
Operator konkatenacji
47

<?php
$imie = "Imiesław";
$nazwisko = 'Nazwiskowy';
$wiek = 37;
$wynik = 22.5;

$zdanie = "Użytkownik " . $imie . ' ' .


$nazwisko . " uzyskał " . $wynik . 'pkt';
//Użytkownik Imiesław Nazwiskowy uzyskał 22.5pkt
Operator indeksowania
48

¨ Dostęp do poszczególnych elementów ciągu jest


możliwy przy użyciu operatora indeksowania:
$nazwisko = 'Nazwiskowy';

$nazwisko[1] = '@'; //N@zwiskowy


$nazwisko[4] = '1'; //N@zw1skowy
$nazwisko[7] = '0'; //N@zw1sk0wy

¨ Uwaga na znaki wielobajtowe!


¤ np. polskie znaki diakrytyzowane: ą, ć, ę itd. w UTF-8
Znaki wielobajtowe
49

$imie = "świętosław"; Plik ze skryptem


echo $imie; zakodowany przy
świętosław użyciu UTF-8
$imie[0] = 'Ś';
echo $imie;
świętosław
$imie[0] = 'S';
echo $imie; S�więtosław

$imie = "świętosław";
echo strlen($imie); 13

# ś w i ę t o s ł a w
# 1 2 3 4 5 6 7 8 9 10
Stringi i Unicode
50

¨ Ciągi znaków w PHP są traktowane jako ciągi


pojedynczych bajtów
¨ Niektóre strony kodowe wykorzystują więcej niż
jeden bajt do zapisania pojedynczego znaku
¨ W szczególności strony kodowe dla zestawu
znaków Unicode
¤ UTF-8 – 2-bajtowe kody m.in. dla polskich znaków
diakrytyzowanych
¤ UTF-16 – przynajmniej 2-bajtowe kody dla wszystkich
znaków
¤ UTF-32 – 4-bajtowe kody dla wszystkich znaków
Stringi i Unicode
51

¨ Operator indeksowania i wiele funkcji operują na


bajtach ciągu a nie na znakach
¨ Dla ciągów zawierających znaki wielobajtowe
istnieje zestaw specjalnych metod mb_...()
$imie = "świętosław";

echo strlen($imie);
13

echo mb_strlen($imie); 10
Zmienne typu logicznego (boolean)
52

¨ Reprezentują wartości prawdy lub fałszu


¨ Mogą być zainicjowane stałymi:
¤ TRUE

¤ FALSE

¨ W odwołaniach do powyższych stałych nie ma


znaczenia wielkość liter!
$prawda = TRUE;
$tez_prawda = true;
$g_prawda = TrUe;
Rzutowanie na typ boolean
53

¨ Jeśli operator, funkcja lub instrukcja sterująca


wymaga typu bool nastąpi automatyczne rzutowanie
¨ Na wartość FALSE rzutowane są:
¤ Liczba całkowita 0 (zero)
¤ Liczba zmiennoprzecinkowa 0.0 (zero)

¤ Pusty ciąg znaków oraz ciąg "0"

¤ Pusta tablica

¤ Wartość NULL (oraz niezainicjowane zmienne)

¤ Obiekt klasy SimpleXML utworzony z pustych tagów

¨ Na wartość TRUE – wszystkie pozostałe wartości


Typ specjalny: NULL
54

¨ Wartość NULL reprezentuje zmienną, której nie


przypisano żadnej wartości
¨ W odwołaniach do stałej NULL nie ma znaczenia
wielkość liter
$zmienna = null;
Stałe
55

¨ Pozwalają na zdefiniowanie wartości, które nie


zmieniają się w czasie działania skryptu duh…
¨ Ich nazwy nie są poprzedzone znakiem $
¨ Zwyczajowo nazwy stałych pisane są dużymi
literami
¤W stałych definiowanych przez programistę, wielkość
liter jest rozróżniana
¨ Dwie składnie definiowania stałych:
¤ Funkcja define()

¤ Słowo kluczowe const od PHP 5.3.0


define() i const
56

¨ Słowo kluczowe const


¤ Przetwarzane na etapie generowania kodu
pośredniego – przed uruchomieniem skryptu
¤ Może zawierać wyłącznie wartości możliwe do
określenia przed uruchomieniem
¨ Funkcja define()
¤ Przetwarzana w czasie działania skryptu
¤ Wartość stałej może bazować na wartościach znanych
dopiero w czasie wykonania
Stałe – przykładowe definicje
57

const PI = 3.14;
define('E', 2.71);

$katalog = '/opt/upload';
$plik = 'data.xml';

//niepoprawne!
const SCIEZKA = $katalog . '/' . $plik;

//poprawne!
define('SCIEZKA', $katalog . '/' . $plik);
Możliwe wartości stałych
58

¨ Wartości skalarne
¤ boolean

¤ integer

¤ float

¤ string

¨ Tablice
¤ Od PHP 5.6 – przy użyciu const
¤ Od PHP 7.0 – również przy użyciu define()
Instrukcja echo
59

¨ Pozwala wypisać treść na standardowe wyjście


skryptu
¨ W kontekście aplikacji internetowej: wypisana treść
staje się częścią dokumentu HTML, który zostanie
odesłany do przeglądarki
Instrukcja echo
60

<?php
$imie = "Imiesław";
$wynik = 22.5;
$zdanie = "Użytkownik $imie uzyskał $wynik pkt";
?>
<div>
<p>
<?php echo $zdanie ?>
</p>
</div>
----------------------------------------------------
//Przeglądarka otrzymuje:
<div>
<p>
Użytkownik Imiesław uzyskał 22.5 pkt
</p>
</div>
Skrócony znacznik echo
61

¨ Wypisywanie wartości pojedynczych wyrażeń


w kodzie HTML jest często wykonywaną operacją
¨ Skrócony znacznik echo ułatwia tę czynność
¤ Od PHP 5.4 dostępny niezależnie od konfiguracji
serwera

//zamiast:
<?php echo $zdanie ?>

//forma skrócona:
<?= $zdanie ?>
Instrukcje warunkowe: if
62

<?php
$wynik = 22.5;

if ($wynik > 20) {


echo "ocena: 5";

} elseif ($wynik > 10) {


echo "ocena: 3";

} else {
echo "egzamin niezaliczony";
}
Instrukcje warunkowe: if
63

¨ Instrukcja if oczekuje wyrażenia typu boolean


¨ Jeśli otrzyma wyrażenie innego typu,
automatycznie wykonane zostanie rzutowanie:
<?php
$imie = 'Imiesław'; //ciąg znaków: string

if ($imie) {
echo "Witaj, $imie!";
} else {
echo 'Pusty ciąg lub ciąg "0"';
}

//wyświetli:
//Witaj, Imiesław!
Operatory porównań: == oraz ===
64

¨ Operator równości: ==
¤ Porównuje wartości zmiennych
¤ Jeśli zmienne są różnego typu, najpierw wykonuje
rzutowanie, następnie porównanie
¨ Operator identyczności: ===
¤ Porównujewartości i typy zmiennych
¤ Nie wykonuje żadnych rzutowań – jeśli typy są różne
zwraca FALSE bez porównywania wartości
Równość i identyczność
65

<?php
$odpowiedz = "42"; //string
Różne typy à FALSE
if ($odpowiedz === 42) {
echo "identyczne - taki sam typ i wartość";
Ciąg znaków rzutowany na liczbę,
porównanie arytmetyczne à TRUE
} elseif ($odpowiedz == 42) {
echo "równe - ta sama wartość";

} else {
echo "nierówne";
}
Pozostałe operatory
66

¨ Zaprzeczenie identyczności: !==


¨ Zaprzeczenie równości: != lub <>
¨ Inne porównania: <, >, <=, >=
¨ Nowe w PHP 7:
¤ $a ?? $b ?? $c – zwraca pierwszą wartość != NULL
¤ $a <=> $b – spaceship operator – zwraca:
n 0,
gdy $a == $b
n Wartość mniejszą niż 0, gdy $a < $b
n Wartość większą niż 0, gdy $a > $b
Złożone warunki
67

if ($ext == '.jpg' || $ext == '.png') {

$poprawne = true;
alternatywa
} else {
$poprawne = false;
} koniunkcja

if ($rozmiar_pliku < 1024*1024 && $poprawne) {


echo "Plik poprawny!";
}
Operator trójargumentowy
68

<?php

//zamiast:
if ($wiek > 18) {
$bilet = 'normalny';
} else{
$bilet = 'ulgowy';
}

//postać skrócona:
$bilet = $wiek > 18 ? 'normalny' : 'ulgowy';
Instrukcje warunkowe: switch
69

switch ($status) {
case 200:
echo "OK";
break;
case 404:
echo "Nie znaleziono";
break;
case 500:
echo "Błąd serwera";
break;
default:
echo "Nierozpoznany status";
}
Pętle: for
70

for(/* inicjalizacja */ ; /* warunek */ ; /* krok */){


/* ciało pętli */
}
inicjalizacja

warunek

for($i=0; $i<5; $i++){ ciało


echo "$i "; pętli
}

01234 krok koniec


Pętle: for
71

¨ Pętla for akceptuje dowolne poprawne wyrażenia


dla inicjalizacji, warunku i kroku pętli
for ($a = 5, $b = 7; //inicjalizacja
$a * $b < 600; //warunek
$a += 7, $b += 5 //krok 57
) { 12 12
echo "$a $b<br/>"; 19 17
} 26 22

$i = 0;
for ($i++; $i; $i = 0) {
echo "$i ";
}
Pętle: while i do-while
72

$n = 176; $n = 176;

while ($n > 1) { do {

echo "$n "; echo "$n ";

if ($n % 2 == 0) { if ($n % 2 == 0) {
$n = $n / 2; $n = $n / 2;
} else { } else {
$n = $n * 3 + 1; $n = $n * 3 + 1;
} }

} } while ($n > 1);


Alternatywna składnia instrukcji sterujących
73

¨ Gdy instrukcje sterujące są przeplatane z kodem


HTML, składnia wykorzystująca nawiasy klamrowe
może stać się nieczytelna
¨ Alternatywna składnia wykorzystuje słowa
kluczowe:
¤ endif

¤ endfor

¤ endforeach

¤ itd.
Kod PHP przeplatany z kodem HTML
74

<?php if ($zalogowany) { ?>


<div class="user-panel">
<?php if ($uzytkownik_premium) { ?>
<div>
<?php foreach ($promocje as $promo) { ?>
<?php if (is_active($promo)) { ?>
<p>
<span>...</span>
...
</p>
<?php } ?>
<?php } ?>
</div>
<?php } ?> Co zamykają te obco
</div> wyglądające nawiasy?
<?php } else { ?>
<div class="sign-in">
...
</div>
<?php } ?>
Alternatywna składnia
75

<?php if ($zalogowany): ?>


<div class="user-panel">
<?php if ($uzytkownik_premium): ?>
<div>
<?php foreach ($promocje as $promo): ?>
<?php if (is_active($promo)): ?>
<p>
<span>...</span>
...
</p>
<?php endif ?>
<?php endforeach ?>
</div>
<?php endif ?>
</div>
<?php else: ?>
<div class="sign-in">
...
</div>
<?php endif ?>
exit oraz die
76

¨ Instrukcje sterujące exit oraz die pozwalają na


zakończenie przetwarzania skryptu w dowolnym
momencie
¨ Skrypt nie wyemituje żadnej dodatkowej treści do
wysłania do przeglądarki
¨ Obie instrukcje są równoważne i mogą być
wywołane przy użyciu składni wywołania funkcji:
exit;
exit();
die;
die();
die – przerwanie skryptu
77

<!DOCTYPE html>
<html>
<body>
<?php
$power = rand(0, 100000);
echo "Power level: $power<br/>\n";

if ($power > 9000) {


echo '<img src="over9000.jpg"/>';
die;
}
?> <!DOCTYPE html>
</body> <html>
</html> <body>
Power level: 88244<br/>
<img src="over9000.jpg"/>
Tablice w PHP
78

¨ W PHP nie wyróżnia się specjalizowanych


kontenerów
¨ Pojedynczy typ array może być użyty jako:
¤ Tablica indeksowana od zera
¤ Wektor o zmiennej długości
¤ Słownik
¤ Hash mapa
¤ Kolejka
¤ Stos
¤ Tablica wielowymiarowa
¤ I wiele innych…
Tablice w PHP
79

¨ W istocie uporządkowane odwzorowania typu:


klucz à wartość
¨ Gdy nie podano jawnych kluczy, domyślnie
indeksowane od zera liczbami całkowitymi
¨ Zmienny rozmiar – powiększane w miarę
dodawania kolejnych elementów
¨ Operator indeksowania $tablica[klucz]
umożliwia dostęp do poszczególnych elementów
tablicy
Tablice – proste zastosowania
80

//tablica indeksowana od zera


$owoce = array('jabłka', 'pomarańcze', 'banany');

//skrócona składnia (od PHP 5.4), indeksowanie od 0


$warzywa = ['marchew', 'pietruszka', 'seler'];

jabłka
//wyświetlenie zawartości tablicy:
for ($i = 0; $i < count($owoce); $i++) {
pomarańcze
echo $owoce[$i].'<br/>'; banany
}

for ($i = count($warzywa)-1; $i >= 0; $i--){ seler


echo $warzywa[$i] . '<br/>'; pietruszka
}
marchew
Jeszcze jedna pętla: foreach
81

foreach ($owoce as $owoc) {


echo $owoc.'<br/>';
} jabłka
pomarańcze
banany

foreach (array_reverse($warzywa) as $warzywo) {


echo $warzywo.'<br/>';
} seler
pietruszka
marchew
Tablice – operacje na elementach
82

$warzywa = ['marchew', 'pietruszka', 'seler'];

//dodawanie nowych elementów:


$warzywa[] = 'burak';
$warzywa[] = 'cukinia';
$warzywa[] = 'ogórek';
Array
//zmiana wartości elementów: (
$warzywa[1] = 'kapusta'; [0] => marchew
$warzywa[5] = 'fasola'; [1] => kapusta
[2] => seler
[3] => burak
[4] => cukinia
print_r($warzywa);
[5] => fasola
)
Tablice – własne klucze
83

$klienci = [ //początkowa tablica


'Anna' => 21,
'Marek' => 27,
'Barbara' => 42
];

//dodawanie kolejnych wartości:


$klienci['Zbigniew'] = 35;
$klienci['Karolina'] = 32;

//pobieranie wartości na bazie klucza:


echo $klienci['Anna'] . '<br/>';

//test czy klucz istnieje w tablicy:


if (array_key_exists('Michał', $klienci))
echo $klienci['Michał'];
else
echo "Klient nie istnieje";
Pętla foreach – druga postać
84

$klienci = [
'Anna' => 21,
Anna ma 21 lat.
'Marek' => 27,
'Barbara' => 45
Marek ma 27 lat.
]; Barbara ma 45 lat.

foreach ($klienci as $imie => $wiek) {


echo "$imie ma $wiek lat.".'<br/>';
}

//dla porównania:
foreach ($klienci as $wiek) echo "$wiek ";
21 27 45
Tablice – wartości różnych typów
85

<?php
$zdjecie = [
'tytul' => 'Wodospad Skogar', #string
'nazwa_pliku' => 'img_9604.jpg',
'ocena' => 8.7, #float
'liczba_odslon' => 1365, #int
'publiczne' => true, #boolean
];
?>

<div>
<h1><?= $zdjecie['tytul'] ?></h1>
<img src="<?= $zdjecie['nazwa_pliku'] ?>"
alt="<?= $zdjecie['tytul'] ?>"/>
</div>
Tablice wielowymiarowe
86

<?php
$zdjecia = [
['tytul' => 'A', 'ocena' => 8.7],
['tytul' => 'B', 'ocena' => 9.1],
['tytul' => 'C', 'ocena' => 5.4], Array(
]; [0] => Array(
[tytul] => A
[ocena] => 8.9
//dostęp do elementów: )
echo $zdjecia[2]['tytul']; [1] => Array(
$zdjecia[0]['ocena'] = 8.9; [tytul] => B
[ocena] => 9.1
)
print_r($zdjecia); [2] => Array(
[tytul] => C
[ocena] => 5.4
)
)
Dołączanie plików – motywacje
87

¨ Rozdzielenie rozległego kodu aplikacji internetowej


na mniejsze, łatwiejsze do utrzymywania fragmenty
¨ Wydzielenie fragmentów które wykorzystywane są
w wielu miejscach, np.:
¤ Nagłówek strony, stopka, menu – dołączane do każdej
podstrony (logika interfejsu)
¤ Funkcje wykorzystywane w wielu miejscach logiki
biznesowej strony
Dołączanie plików: include
88

include 'sciezka/do/pliku.php';

¨ Dołącza wskazany plik i wykonuje zawarty w nim


kod PHP
¨ Kod jest wykonywany tak, jakby był umieszczony
w miejscu instrukcji include – ma dostęp do
wszystkich zmiennych w danym zasięgu
¨ Jeśli plik nie istnieje, wyemitowane zostanie
ostrzeżenie (E_WARNING), działanie skryptu nie
zostanie przerwane
¤ Dołączanie plików opcjonalnych
Dołączanie plików: require
89

require 'sciezka/do/pliku.php';

¨ Jeśli plik nie istnieje, wyemitowany zostanie błąd,


a działanie skryptu zostanie przerwane
¤ Dołączanie plików wymaganych do działania
¨ Pozostałe aspekty działania jak przy instrukcji
include
include_once oraz require_once
90

include_once 'sciezka/do/pliku.php';

require_once 'sciezka/do/pliku.php';

¨ Jeśli plik został już wcześniej dołączony, nie zostanie


dołączony ponownie
¨ Pozwalają uniknąć problemów z redefinicją funkcji,
wartości zmiennych itp. gdy ten sam plik zostanie
dołączony w dwóch różnych miejscach
Funkcje
91

¨ Umożliwiają podział kodu źródłowego na logiczne


fragmenty, wywoływane w celu zrealizowania logiki
aplikacji
¨ Mogą przyjmować argumenty i zwracać wartości
¨ Mogą by wywoływane w wielu miejscach
¤ Code reuse
¤ Powtarzalne czynności, funkcje narzędziowe

¨ W nazwach funkcji wielkość liter nie jest


rozróżniana
¤ Alezaleca się by dla czytelności w wywołaniach
używać takiej samej wielkości jak w definicji funkcji
Funkcje
92

function pozdrowienie()
{
echo "Witaj, świecie!";
}

//...

//wywołanie funkcji:
pozdrowienie();

Witaj, świecie!
Funkcje – argumenty
93

function pozdrowienie($imie)
{
echo "Witaj, $imie!";
}
Niewymagana definicja typów
argumentów.
Typy możliwe do zdefiniowania:
PHP 5.6: array, callable, klasy
//... PHP 7.0: wszystkie typy (poza null)

//wywołanie funkcji:
pozdrowienie('Waldemar');

Witaj, Waldemar!
Funkcje – argumenty
94

function pozdrowienie($powitanie, $imie)


{
echo "$powitanie, $imie!";
}

//...

//wywołanie funkcji:
pozdrowienie('Cześć', 'Waldemar');

Cześć, Waldemar!
Funkcje – argumenty domyślne
95

function pozdrowienie($powitanie = 'Witaj',


$imie = 'świecie')
{
echo "$powitanie, $imie!";
}

//...
Witaj, świecie!
//wywołanie funkcji:
pozdrowienie(); Cześć, świecie!
pozdrowienie('Cześć');
pozdrowienie('Cześć', 'Waldemar');
Cześć, Waldemar!
Funkcje – wartości zwracane
96

function pozdrowienie($powitanie, $imie)


{
return "$powitanie, $imie!";
}
PHP 5.6: brak możliwości zdefiniowania typu zwracanego
PHP 7.0: opcjonalna definicja typu zwracanego
//...

//wywołanie funkcji:
$komunikat = pozdrowienie('Cześć', 'Waldemar');

//...
Cześć, Waldemar!
echo $komunikat;
Funkcje – zmienne lokalne i statyczne
97

function fun()
{
1 1
$zmienna_lokalna = 0; 1 2
static $zmienna_statyczna = 0; 1 3
1 4
$zmienna_lokalna++;
$zmienna_statyczna++; 1 5

echo "$zmienna_lokalna $zmienna_statyczna\n";


}

for ($i = 0; $i < 5; $i++) fun();

echo $zmienna_lokalna; Niedostępne poza funkcją!


echo $zmienna_statyczna; Notice: Undefined variable
Dostęp do zmiennych globalnych
98

¨ Zmienne zdefiniowane poza funkcją nie są


domyślnie dostępne w obrębie funkcji
¤ Poza zmiennymi superglobalnymi
<?php
$powitanie = "Witaj";

function pozdrowienie($imie){
return "$powitanie, $imie!";
}
Notice: Undefined variable: powitanie
in example.php on line 5

echo pozdrowienie("Waldemar"); , Waldemar!


Słowo kluczowe global
99

<?php
$powitanie = "Witaj";

function pozdrowienie($imie){
global $powitanie;
return "$powitanie, $imie!";
}
Wprowadzenie zmiennej globalnej
$powitanie do zasięgu funkcji

Witaj, Waldemar!

echo pozdrowienie("Waldemar");
Przekazywanie argumentów przez
100
referencje
¨ Domyślnie argumenty funkcji są przekazywane
przez wartość
¤ Funkcjaotrzymuje lokalną kopię zmiennej
¤ Zmiana wartości argumentu w obrębie funkcji nie
wpływa na wartość oryginalnej zmiennej
¨ Dodanie symbolu & przed nazwą argumentu
w definicji funkcji powoduje przekazywanie
argumentu przez referencję
¤ Zmiany wartości argumentu w obrębie funkcji zmieniają
wartość zmiennej przekazanej w momencie wywołania
Przekazywanie argumentów przez
101
referencje
function oblicz($a, $b) function oblicz(&$a, $b)
{ {
$a = $a * $b; $a = $a * $b;
echo $a . ' '; echo $a . ' ';
} }

$punkty = 7; $punkty = 7;
$skala = 3; $skala = 3;

oblicz($punkty, $skala); oblicz($punkty, $skala);

echo "$punkty $skala”; echo "$punkty $skala”;

21 7 3 21 21 3
Zwracanie wartości przez referencję
102

¨ Domyślnie kod wywołujący funkcję otrzymuje kopię


wartości zwracanej
¤ np. kopię zmiennej lokalnej funkcji
¨ Dodanie symbolu & w definicji funkcji (przed nazwą)
i w miejscu wywołania powoduje zwrócenie wartości
przez referencję
Zwracanie wartości przez referencję
103

function &find_contractor($name)
{
static $yellow_pages = [];

if (!isset($yellow_pages[$name])) {
$yellow_pages[$name] = [
'rendezvous' => 1,
'status' => 'PENDING'
]; Modyfikuje tablicę
} $yellow_pages

return $yellow_pages[$name];
}

$contractor = &find_contractor('WK');
//...
$contractor['status'] = 'CONFIRMED';
Funkcje anonimowe (domknięcia)
104

¨ Nie posiadają nazwy – stąd anonimowe duh…


¨ Mogą być przypisane do zmiennej lub przekazane
jako argument
¤ Najczęściej wywołania zwrotne (ang. callback)
$callback = function ($status) {
if ($status === 200) {
//...
} else {
//...
}
};

load_data($db, $callback);
Zmienne zmienne
105
(ang. variable variables)
¨ W języku PHP nie ma wskaźników HURRA! :)
¨ Czasami nie wiadomo z góry którą zmienną bądź
funkcję należy wywołać w kodzie – można to ustalić
dopiero w czasie działania skryptu
¤ Szczególnie we frameworkach, gdzie funkcje
biznesowe są implementowane przez użytkowników
i w ogóle nie są znane autorom frameworka
¨ Potrzebny jest mechanizm odwoływania się do
zmiennych i funkcji bez znajomości ich nazw a priori
Zmienne zmienne
106
(ang. variable variables)
¨ Odwołanie do zmiennej, której nazwa zapisana jest
w innej zmiennej
¤ Nazwa może być określona w czasie działania skryptu
$imie = 'Waldemar';

$wybrana_zmienna = 'imie';

echo $$wybrana_zmienna;
Waldemar
//tak samo jak:
echo $imie;
Zmienne funkcje
107
(ang. variable functions)
¨ Wywołanie funkcji, której nazwa zapisana jest
w zmiennej
function pozdrowienie($imie){
return "Witaj, $imie!";
}

$wybrana_funkcja = 'pozdrowienie';

echo $wybrana_funkcja('Waldemar');

Witaj, Waldemar!
//tak samo jak:
echo pozdrowienie('Waldemar');
Zmienne funkcje i zmienne zmienne
108

function pozdrowienie($imie){
return "Witaj, $imie!";
}

$imie = 'Waldemar';

$wybrana_funkcja = 'pozdrowienie';
$wybrana_zmienna = 'imie';

echo $wybrana_funkcja($$wybrana_zmienna);

//tak samo jak: Witaj, Waldemar!


echo pozdrowienie($imie);
Zmienne zmienne zmienne zmienne zmienne…
109

$nazwa = 'zmienna';
$zmienna = 'wartosc';
$wartosc = 'nazwa';
zmienna
echo $nazwa . '<br/>'; wartosc
echo $$nazwa . '<br/>'; nazwa
echo $$$nazwa . '<br/>'; zmienna
echo $$$$nazwa . '<br/>'; wartosc
echo $$$$$nazwa . '<br/>'; nazwa
echo $$$$$$nazwa . '<br/>';
//...
Zmienne funkcje i zmienne zmienne
110

¨ Nie należy nadużywać tych mechanizmów


¤ Czytelność kodu
¨ Przeznaczone do specyficznych zastosowań
w specyficznych sytuacjach
¤ Frameworki

¤ Biblioteki

¨ Przykłady rzeczywistego (i uzasadnionego)


zastosowania na dalszych wykładach
111 Pytania?
JQUERY
Krystyna Wytwarzanie Aplikacji Internetowych
Dziubich KASK ETI Politechnika Gdańska
• Trudności z napisaniem uniwersalnego kodu
– pomocne frameworki języka JS :

Dokumentacja, przewodniki jQuery: docs.jquery.com


-> http://docs.jquery.com/Browser_Compatibility

Najczęściej wykorzystywane
wersje jQuery

http://trends.builtwith.com/javascript
Popularne rozszerzenia jQuery:

Używane wersje jQuery:

http://blog.builtwith.com/2011/10/31/jquery-version-and-usage-report/
3
jQuery (http://jquery.com)
 Programistyczna biblioteka JavaScript zaprojektowana do
uproszczenia tworzenia JS wykonywanych po str.klienta

 Dostosowana do różnych przeglądarek


 Ułatwia manipulację drzewem DOM
 wybieranie elementów drzewa DOM,
 ustawianie ich atrybutów, dodawanie, usuwanie
 Ułatwia tworzenie animacji i efektów
 Ułatwia obsługę zdarzeń
 Ułatwia użycie AJAX-a

 Oprogramowanie darmowe, open source


 Wykorzystywane w dynamicznych stronach
 HTML i aplikacjach webowych
 (demo: dancing-menu, imagemenu, memory-game)
Przykłady z: http://www.hscripts.com/scripts/jquery/
Wersja deweloperska a wer. minified

 Deweloperska  Minified
• jquery-1.8.2.js 261 kB • jquery-1.8.2.min.js 92 KB

(function( window, undefined ) { (function(E,B){function ka(a,b,d){if(d===B&&a.nodeType===1){d


=a.getAttribute("data-
"+b);if(typeof d==="string"){try{d=d==="true"?true:d==="false
// Use the correct document accordingly with window "?false:d==="null"?null:!c.isNaN(d)?parseFloat(d):Ja.test(d)?
argument (sandbox) c.parseJSON(d):d}catch(e){}c.data(a,b,d)}else d=B}return d}fu
var document = window.document; nction U(){return false}function ca(){return true}function la
var jQuery = (function() { (a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function
Ka(a){var b,d,e,f,h,l,k,o,x,r,A,C=[];f=[];h=c.data(this,this
.nodeType?"events":"__events__");if(typeof h==="function")h=
// Define a local copy of jQuery h.events;if(!(a.liveFired===this||!h||!h.live||a.button&&a.ty
var jQuery = function( selector, context ) { pe==="click")){if(a.namespace)A=RegExp("(^|\\.)"+a.namespace.
split(".").join("\\.(?:.*\\.)?")+"(\\.|$)");a.liveFired=this;
// The jQuery object is actually just the i var J=h.live.slice(0);for(k=0;k<J.length;k++){h=J[k];h.origTy
pe.replace(X,"")===a.type?f.push(h.selector):J.splice(k--
nit constructor 'enhanced' ,1)}f=c(a.target).closest(f,a.currentTarget);o=0;for(x=f.leng
th;o<x;o++){r=f[o];for(k=0;k<J.length;k++){h=J[k];if(r.select
return new jQuery.fn.init( selector, contex or===h.selector&&(!A||A.test(h.namespace))){l=r.elem;e=null;i
t ); f(h.preType==="mouseenter"||
}, h.preType==="mouseleave"){a.type=h.preType;e=c(a.relatedTarge
t).closest(h.selector)[0]}if(!e||e!==l)C.push({elem:l,handleO
bj:h,level:r.level})}}}o=0;for(x=C.length;o<x;o++){f=C[o];if(
// Map over jQuery in case of overwrite d&&f.level>d)break;a.currentTarget=f.elem;a.data=f.handleObj.
_jQuery = window.jQuery, data;a.handleObj=f.handleObj;A=f.handleObj.origHandler.apply(
f.elem,arguments);if(A===false||a.isPropagationStopped()){d=f
.level;if(A===false)b=false;if(a.isImmediatePropagationStoppe
d())break}}return b}}function Y(a,b){return(a&&a!=="*"?a+".":
"")+b.replace(La,
Selektory
• Pozwalają wybierać grupy elementów z drzewa DOM
• Bazują na selektorach z CSS 1-3
<div id="mainDiv">
<div>
Wewnętrzny div
</div>
<div class="poem-line">
Stylowy div
</div>
<div>
<p title="Tytuł">Pierwszy akapit</p>
<p>Drugi akapit</p>
<p>Trzeci akapit</p>
</div>
</div>
Child – bezpośrednie dziecko
$("#mainDiv > *")

DIV id=mainDiv

DIV

DIV class=poem-line

DIV
P title=Tytuł
P
P
Descendant
$("#mainDiv *")

DIV id=mainDiv

DIV

DIV class=poem-line

DIV
P title=Tytuł
P
P
Class
$(".poem-line")

DIV id=mainDiv

DIV

DIV class=poem-line

DIV
P title=Tytuł
P
P
Attribute
$("[title]")

DIV id=mainDiv

DIV

DIV class=poem-line

DIV
P title=Tytuł
P
P
All
$("*")
DIV id=mainDiv

DIV

DIV class=poem-line

DIV
P title=Tytuł
P
P
Element
$("p")

DIV id=mainDiv

DIV

DIV class=poem-line

DIV
P title=Tytuł
P
P
jQuery API
• Użycie funkcji $ jest równoznaczne z użyciem
obiektu jQuery
• Wywołania komend można łączyć w łańcuchy
komend
• Funkcja $ zwracająca obiekt jQuery, na którym
wykonuje się kolejne komendy
• Każda z komend również zwraca obiekt
jQuery
jQuery API / przykład: test1.html

<div id="mainDiv">
<p>
Litwo! Ojczyzno moja! ty jesteś jak zdrowie.
<span style="display: none">Komentarz 1</span>
</p>
<p>
Ile cię trzeba cenić, ten tylko się dowie,
<span style="display: none">Komentarz 2</span>
</p>
</div>
$("#mainDiv")
.addClass("poem-text")
.children("p")
.addClass("poem-line")
.children("span")
.addClass("poem-comment")
.toggle("fast");
Atrybuty i style
.addClass() , .removeClass() oraz .toggleClass()
Dodawanie, usuwanie, przełączanie klas
.css()
Dostęp do styli
.attr()
Dostęp do atrybutów
.val()
Dostęp do wartość np. texboxa
.text() oraz .html()
Dostęp do innerText oraz innerHtml
Trawersowanie DOM
.add()
Dodaje zbiór elementów do aktualnego zbioru
.children()
Wybiera dzieci każdego z elementów aktualnego zbioru
.find()
Wybiera potomków każdego z elementów aktualnego
zbioru
.each()
Pozwala wywołać funkcję na każdym z elementów
aktualnego zbioru
Zdarzenia
$(document).ready()
Po załadowaniu drzewa
Przed załadowaniem obrazków
Możliwość podpięcia z kilku miejsc (jak delegat)

$(element).load()
Po załadowaniu elementu
Dopuszczalne elementy:
Image
Script
Frame
Iframe
Window
Zdarzenia
 Standardowe zdarzenia znane z aplikacji
desktopowych
 .focus() / .blur()
 .change()

 .click()

 .keydown() / .keyup()

 .mousemove()

<script type="text/javascript">
$('#docum').mousedown( function () {
$('#log').append('<div>Handler for .mousedown() called.</div>');
});
</script>
AJAX w jQuery
.ajax()
Wysyła asynchroniczne żądanie AJAX
Najbardziej rozbudowana funkcja
.get()
Wysyła żądanie metodą get
.post()
Wysyła żądanie metodą post
.load()
Pobiera zawartość strony i umieszcza ją we wskazanym elemencie

 Różnice w API pomiędzy przeglądarkami : JS/05-


ajax/index.html
Pluginy w JQuery
Przykład pluginu: http://sorgalla.com/jcarousel/
 Pobrać i załączyć styl oraz js
<link rel="stylesheet" type="text/css" href="tango/skin.css" >
<script type="text/javascript" src="jquery.jcarousel.min.js"></script>
 Zbudować strukturę z listą grafik
<div id="plugin"><p>przykład wykorzystania pluginu http://sorgalla.com/jcarousel/ </p>
<ul id="mycarousel" class="jcarousel-skin-tango">
<li><img src="./zdj/1.jpg" width="75" height="75" alt="" onclick="laduj(this);" ></li>
<li><img src="./zdj/8.jpg" width="75" height="75" alt="" onclick="laduj(this);" ></li>
</ul></div>
 Dodać funkcję js:
function mycarousel_initCallback(carousel) {…. }
 Zdefiniować w js wystartowanie karuzeli
$(document).ready(function () { jQuery('#mycarousel').jcarousel({
auto: 2,
wrap: 'last',
initCallback: mycarousel_initCallback
});
});
[Demo: przykład_plugin/testjquery.html ]
jQuery UI
jqueryui.com
• Komponenty interfejsu użytkownika
• Efekty
• Widżety
• Tematy
Literatura uzupełniająca:
• jquery.com oraz jqueryui.com
• Lynn Beighley: „jQuery for dummies”; Wiley 2010; isbn:978-0-470-58445-3
• http://www.syncfusion.com/resources/techportal/ebooks: jQuery_Succinctly
C.Lindley 2014
• 1500+ Best Jquery Plugins & Tutorials: http://www.jqueryrain.com/
• http://jquery.com/browser-support/
• http://learn.jquery.com/
• http://trends.builtwith.com/javascript
• 15 Most Popular jQuery Plugins of June 2012 :
http://www.moretechtips.net/2012/07/15-most-popular-jquery-plugins-of-june.html
JavaScript
Dynamika w przeglądarce
DOM: Document Object Model
AJAX: Asynchronous JavaScript and XML
Biblioteka jQuery

Waldemar Korłub Wytwarzanie Aplikacji Internetowych


Krystyna Dziubich KASK ETI Politechnika Gdańska
Statyczne strony: HTML+CSS
 Statyczny HTML
 Serwowanie tej samej treści wszystkim użytkownikom przy
każdym żądaniu danego zasobu
 Zmiana treści wymaga modyfikacji zawartości pliku po
stronie serwera
 Style CSS
 Statyczne reguły stylów dla elementów dokumentów HTML
 Style uzależnione od akcji użytkownika na stronie
◼ np.pseudoklasy :hover, :focus, :checked
◼ Dynamiczne zmiany stylów w reakcji na działania użytkownika
◼ Brak możliwości modyfikowania struktury dokumentu HTML

→ Hipertekst i Hipermedia
2
Dynamiczne strony
 Dynamika po stronie klienta – przeglądarki
 Modyfikowanie treści, struktury, wyglądu dokumentu
HTML już po jego załadowaniu w przeglądarce
◼ Bez komunikacji z serwerem,
 JavaScript (+ DOM osadzone w HTML) CSS

 Dynamika po stronie serwera I’m


 Generowanie dokumentu HTML przez aplikację PHP
działającą po stronie serwera
◼ Zamiast serwowania statycznego pliku HTML
 Serwowanie różnych treści, np. w zależności od:
◼ Użytkownika: „Masz 2 nowe zaproszenia”
◼ Dnia: „Pogoda na dziś: …”
◼ PHP, Ruby on Rails, Python, ASP.NET MVC, Java ServerFaces…
3
Dynamiczne strony
 Asynchroniczna komunikacja z serwerem
 Wykorzystanie dynamiki w przeglądarce do pobrania
nowych treści z serwera, który może generować je
dynamicznie
 Bez przeładowywania całej strony

 AJAX I’m
PHP
Żądanie
Odpowiedź
html,
xml,
json

Strona klienta Strona serwera


/przeglądarka/ /serwer www + aplikacja/ 4
DHTML: Dynamic HTML
 Zbiór technik po stronie klienta (przeglądarki),
pozwalających na wytworzenie interaktywnej witryny
 JavaScript
 API DOM

 AJAX

 jQuery

 Style CSS

…

 Pozwala modyfikować wygląd, zawartość i strukturę


dokumentu HTML już po jego załadowaniu przez
przeglądarkę internetową 5
JavaScript
 Pierwsza wersja – rok 1995, przeglądarka
Netscape Navigator 2.0
 Mocha → LiveScript → JavaScript
 JavaScript – nazwa marketingowa
 Przyciągnięcie uwagi deweloperów na fali szybko
rosnącej popularności języka Java
 Zamieszanie nazewnicze i dezorientacja wśród
deweloperów
 JavaScript i Java to dwa odrębne, niezależne
języki programowania
6
JavaScript
 JScript – Internet Explorer 3.0, 1996 rok
 Bazował na języku JavaScript i oferował własne
rozszerzenia
◼ Niekompatybilności z językiem JavaScript, różnice w API
◼ Brak standardu
 ECMAScript – specyfikacja (standard) języka
skryptowego
 Prace rozpoczęte po koniec 1996 roku
 Ma definiować jednolity standard unifikujący języki
JavaScript i JScript
◼ Kompatybilność między przeglądarkami
7
JavaScript – dziś
 Wszystkie popularne przeglądarki interpretują JavaScript
 https://en.wikipedia.org/wiki/JavaScript
https://www.w3schools.com/js/js_versions.asp
 Wszystkie implementacje bazują na standardzie ECMAScript
 Cel standardu jakby spełniony…
 Różne implementacje dostarczają własne rozszerzenia
 np. dodatkowe API, metody rozszerzające istniejące API
 Problemy z kompatybilnością w różnych przeglądarkach
 Mime Type (dokument RFC 4329)
◼ <script type="application/javascript"> ...</script>
◼ <script type="text/javascript"> ...</script> // przestarzały mime type
◼ <script>...</script> // w HTML5 type nie jest oczekiwany
8
JavaScript – typowe zastosowania
 Modyfikowanie struktury i treści dokumentu po
załadowaniu strony (API DOM)
 Reagowanie na działania użytkownika w przeglądarce
 np. kliknięcie przycisku, wskazanie elementu kursorem
 Walidacja danych w formularzach bez wysyłania
żądań do serwera
 Komunikacja asynchroniczna – AJAX
 Wyświetlanie reklam
 np. Google AdWords, Amazon Advertising
 Statystyki odwiedzin
 np. Google Analytics
9
Przegląd języka JavaScript
Miejsce i czas wykonania
Gdzie umieścić kod JavaScript?
 Zewnętrzny plik .js
<script src="external.js"></script>

 Kod JavaScript osadzony w pliku HTML5 (inline script)


<div> a tu skrypcik
<script>
var divs = document.getElementsByTagName('div');
console.log('DIVs count: ' + divs.length);
</script>
</div>

 Kod JavaScript w atrybutach obsługi zdarzeń


<button onclick="console.log('click!')">OK</button>
11
Kiedy kod JavaScript jest wykonywany?
Przykład 01-where-and-when
 Kod w atrybucie obsługi zdarzenia
 w momencie wystąpienia zdarzenia
 Kod osadzony w pliku HTML
 W chwili jego napotkania Przed załadowaniem
całego dokumentu HTML
 Kod w zewnętrznym pliku .js
 W chwili jego dołączenia
◼ Bez atrybutów async i defer
 Kod w zew. pliku JS + async
 Kod w zew. pliku JS + defer
http://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html
12
Kontrolowanie momentu uruchomienia
skryptów przykł: 02-onload
 Umieszczenie kodu JavaScript w funkcjach:
function countDivs(msg) {
var divs = document.getElementsByTagName('div');
console.log(msg + ': ' + divs.length);
}

 Zdarzenie window.onload:
<script >
window.onload = function () {
countDivs('window.onload');
};
</script>

 Zdarzenie wywoływane po załadowaniu dokumentu HTML


i wszystkich zewnętrznych zasobów (np. pliki graficzne)
13
Kontrolowanie momentu uruchomienia
skryptów
 Często nie chcemy czekać na załadowanie zewnętrznych
zasobów –wystarczy sam dokument HTML (DOMContentLoaded)
<script >
document.addEventListener ("DOMContentLoaded", function(event ) {
console.log("DOM fully loaded and parsed"); } );
</script>

 Obsługa takiego zdarzenia nie jest kompatybilna między


różnymi przeglądarkami
 Wrócimy do problemu przy okazji biblioteki jQuery
 $(document).ready()

14
Rozróżnianie zawartości bloku <script>
 Obiekt hosta (head/window) dla kodów JS wykonywanych np. w
przeglądarce /przykład: 03-01wstep/obiketWindow.html
 udostępnia środowisko do wykonywania kodu JS;
 Jego metody są dostępne z poziomu kodu JS
 nie jest częścią ECMAScript, dostępne metody zależnie od implementacji w
danej przeglądarce (IE 9 - 143 elementy, FF17 - 182)
 np.IE: prompt(), onload, onsubmit, status, history, navigator, location,
localStorage , execScript , setTimeout, ….
◼ window.console.log("cześć"); lub console.log("cześć");

 JS jako język – struktura języka, natywne obiekty JS i ich metody


 Zmienne, pętle, obiekty wbudowane, math.pi, String.substring(poz1,poz2),…
 Wykorzystywane interfejsy np. DOM
 /przykład: 03-01wstep/obiektDocumet.html
 nodeValue, removeChild() (FF17 – 221, IE9 – 235)
15
Zadanie własne

Przyzwoicie jest rozróżniać składowe


umieszczane w bloku script!
Przeanalizuj:
03-01wstep/przykład_czystyJS.html (demo
debuger)
kontra
03-01wstep/przyklad_JS_Window.html
oraz
03-01wstep/przykład_DOM.html
Przegląd języka JavaScript
Podstawowe elementy składniowe
Zmienne- typy prymitywne
var imie = 'Imiesław';
var nazwisko = "Nazwiskowy"; // typeof nazwisko zwróci ’string’
var wiek = 22; // typeof wiek zwróci ’number’
var punkty = 17.5; // jw..
var zdanie = imie + ' ' + nazwisko +
' (' + wiek + ' l.) zdobył: ' +
punkty + ' pkt.';
console.log(zdanie);
//Imiesław Nazwiskowy (22 l.) zdobył: 17.5 pkt.
var x; //typeof x zwróci ’undefined’
var y= null; //typeof y zwróci ’object’
wiek = false; //typeof wiek zwróci ’boolean’
 Bez deklaracji typów /brak silnego typowania/
18
Zadanie własne

Jaka będzie wartość zmiennej lub wynik porównania?


var x = 2018 +”WAI”;
var x = ’WAI3’+ 20 + 1;

’4’ === 4;
4 === Number(4);

var x ='ala';
var y = new String('ala');
console.log(x===y);
console.log(x==y);
19
Deklarowanie zmiennych var/let/const

 Dobra praktyka
 Zakres widoczności zmiennej
 Redeklaracja zmiennej

Więcej o zakresach widoczności zmiennych na:


 https://www.w3schools.com/js/js_variables.asp

 https://www.w3schools.com/js/js_let.asp

 https://www.w3schools.com/js/js_const.asp

20
Tablice
var litery = ['a', 'b', 'c'];

for (var i = 0; i < litery.length; i++) {


console.log(litery[i]);
}

//wartości różnych typów:


var t2 = ['abc', 1, 1.5];

//tablice zagnieżdżone – wielowymiarowe:


var t3 = [t2, ['def', 2, 2.5]];

console.log(t3[1][0]);
d?ef
21
Tablice
 Brak deklaracji rozmiaru tablicy
 Możliwość dodawania kolejnych elementów do już
istniejącej tablicy
 Rozmiar zostanie dostosowany automatycznie
var litery = ['a', 'b', 'c'];
litery[litery.length] = 'd';
litery[litery.length] = 'e'; 6
litery[litery.length] = 'f';

console.log('Rozmiar tablicy: '+litery.length);

for (var i = 0; i < litery.length; i++) {


console.log(litery[i]);
}
22
Obiekty przykład: 03-01wstep/obikektyJS_JSON.html

Object literal method Keyword „new”

var student = { var student = new Object();


'imie': 'Imiesław',
'nazwisko': 'Nazwiskowy', student.imie = 'Imiesław’;
'nr_albumu': 999999 student.'nazwisko’ ='Nazwiskowy’;
}; student .'nr_albumu'= 999999;

console.log(student.imie); console.log(student.imie);
console.log(student['imie']); console.log(student['imie']);

 Oba sposoby definiowania obiektów poprawne,


 „Object literal method” szybsza w działaniu
23
Obiekty
var student = {
'imie': 'Imiesław',
'nazwisko': 'Nazwiskowy',
'nr_albumu': 999999,

'email': function() {
return 's'+this.nr_albumu+'@student.pg.edu.pl';
}
};

console.log(student.email());

s999999@student.pg.gda.pl
24
JSON: JavaScript Object Notation
 Oryginalnie: notacja pozwalająca zapisywać obiekty
języka JavaScript w postaci tekstowej
 Obiekt jako zbiór par: klucz → wartość
 Konwersje:
◼ Obiekt → reprezentacja tekstowa
◼ Reprezentacja tekstowa → funkcjonalny obiekt

 Współcześnie: powszechnie wykorzystywany format


wymiany danych w Internecie
 Mały narzut na dane (np. w porównaniu do formatu XML)
 Szybkie parsowanie danych
przykład: 03-01wstep/obikektyJS_JSON.html
25
JSON: obiekt → reprezentacja tekstowa

var str = JSON.stringify(student);

var student = {
'imie': 'Imiesław',
'nazwisko': 'Nazwiskowy',
'nr_albumu': 99999
};

{
"imie": "Imiesław",
"nazwisko": "Nazwiskowy",
"nr_albumu": 99999
}
26
JSON: reprezentacja tekstowa → obiekt

var object = JSON.parse(str);

{
"imie": "Imiesław",
"nazwisko": "Nazwiskowy",
"nr_albumu": 99999
}

console.log(object.imie);

27
Funkcje
function greeting(name){
return 'Hello, ' + name + '!';
}

result = greeting('Waldemar');

console.log(result);
Hello, Waldemar!

 Bez deklaracji typów argumentów i typów wartości


zwracanych

28
Funkcje anonimowe

brak nazwy

window.onload = function () {
greeting('Waldemar');
};

29
Funkcje anonimowe – callback
//w zewnętrznej bibliotece:
function fetch_data_from_server(callback) {
/*...pobranie danych z serwera...*/
var result = /*...*/;
callback(result);
}

//w naszym skrypcie:


var handle_result = function (result) {
//przetwarzanie otrzymanego argumentu
};

fetch_data_from_server(handle_result);
30
Instrukcje sterujące
function gcd(a, b) {
if (a == 0) {
return b;
} pętle
while (b != 0) {
if (a > b) {
a = a - b; instrukcje
} warunkowe
else {
b = b - a;
}
} Składnia bazująca
na językach
return a; C/C++
}
31
DOM: Document Object Model

<html>
<head>
<title>My title</title>
</head>
<body>
<a href="" >My link</a>
<h1>My header</h>
</body>
</html>
DOM: Document Object Model
 DOM – Obiektowy model dokumentu
 Niezależna od platformy i języka konwencja
reprezentacji dokumentu HTML, XHTML oraz XML i
dostępu do jego treści w celu jej modyfikacji
 W postaci drzewa elementów

 API DOM – zestaw interfejsów do operowania na


drzewie dokumentu
 Pozwala na wyszukiwanie elementów dokumentu,
ich modyfikację, usuwanie i dodawanie nowych

33
Wyszukiwanie elementów
var divs = document.getElementsByTagName('div');

var age_inputs = document.getElementsByName('age');

var posts = document.getElementsByClassName('post');

//pojedynczy element:
var header = document.getElementById('header');

//pojedynczy element:
var post_title = document.querySelector('div#body div.post h1');

//zbiór elementów:
var titles = document.querySelectorAll('div#body div.post h1');

34
Modyfikacja elementów
// w html:
<div><img id="I1" src="1.png" alt="logo"
onmouseover="changeImage()" /></div>
// w JS
function changeImage() {
//wyszukanie elementu do usunięcia:
var image2 = document.getElementsByTagName('img')[0];
//modyfikacja atrybutu elementu:
image2.src = "2.jpg";
}

35
Usuwanie elementów

//wyszukanie elementu do usunięcia:


var header = document.getElementById('h12');

//usunięcie elementu:
header.parentNode.removeChild(header);
div
img src="1.png"
var header p id="h12"

Ala ma kota

36
Dodawanie elementów
//nowy element <div>:
var div = document.createElement('div');

//nowy element tekstowy:


var text = document.createTextNode('abc');

//dodanie elementutekstowegodo elementu<div>


div.appendChild(text);

//dodanie elementu <div> do dokumentu


document.body.appendChild(div);
Ile razy zaangażowany komponent graficzny?

37
Typy węzłów
DOM Level 2 : node.nodeType
 Node.ELEMENT_NODE == 1

 Node.ATTRIBUTE_NODE == 2

 Node.TEXT_NODE == 3

 Node.CDATA_SECTION_NODE == 4

 Node.ENTITY_REFERENCE_NODE == 5

 Node.ENTITY_NODE == 6

 Node.PROCESSING_INSTRUCTION_NODE == 7

 Node.COMMENT_NODE == 8

 Node.DOCUMENT_NODE == 9

 Node.DOCUMENT_TYPE_NODE == 10

 Node.DOCUMENT_FRAGMENT_NODE == 11

 Node.NOTATION_NODE == 12

38
Demo DOM
 Dostępność API DOM
 http://www.quirksmode.org/dom/w3c_core.html

 Przykład 03_02-dom
 Narzędzia deweloperskie
 Drzewo dokumentu
39
Sprawdzać obsługę funkcji a nie wersję przeglądarki
– if (document.layers){ …}
– var iedom=document.all||document.getElementById
– var ns4up = (document.layers) ? 1 : 0;
– Łapanie wyjątków gdy użyty element niedostępny w
przeglądarce
try { var b = document.getElementsByClassName("tu"); alert(b); }
catch (e) { alert(e.message);}
– Sprawdzenie dostępności funkcji
if ( typeof document.getElementsByClassName === "undefined" ) { //.. Funkcja
nie jest zdefiniowana .. } else { b = document.getElementsByClassName("tu"); }

var hasVideo = !!(document.createElement('video').canPlayType);


//!! Zamienia wynik w wartość logiczną
if (hasVideo) { //możesz spokojnie używać znacznika video…… }
Czasochłonność JS+DOM //Edge

41
Web Storage API
Web Storage API (HTML5)
 Pozwala na zapisywanie danych po stronie przeglądarki
 Dane postaci: klucz (string) → wartość (string)
 Konieczność serializacji wszystkich przechowywanych wartości
do postaci tekstowej
 QUOTA_EXCEEDED_ERR – w przypadku przepełnienia
magazynu
 Local Storage
 Dane utrzymywane pomiędzy kolejnymi uruchomieniami
przeglądarki
 Session Storage
 Dane niszczone w chwili zamknięcia okna przeglądarki
43
WebStorage API / cookies
 Ciasteczka
 do przetrzymywania małych porcji danych 4KB ;
przesyłane do i z serwera aby utrzymać wartość
między stronami; widoczne w nagłówkach protokołu;
np. identyfikator użytkownika, odwiedzane strony –
dla spersonalizowanych reklam;

 WebSorage
 Obiekty sessionStorage, localStorage przetrzymują
dane lokalnie (do kilku MB) między kolejnymi
wołaniami stron z danej domeny w ramach okna,
zakładki i między restartami przeglądarki

44
Local storage
function count_clicks() {
if (window.localStorage) { //local storage supported
if (localStorage.clickcount) {
localStorage.click_count = Number(localStorage.click_count) + 1;

} else { localStorage.click_count = 1; }

var div = document.getElementById("result");

div.innerHTML = "Licznik kliknięć: " +


localStorage.click_count;
}
}

45
Local storage

//w pliku HTML:


<div id="result" onclick="count_clicks();">
Licznik kliknięć
</div>

 Przykład 04-web-storage //np. chrom

46
Obiekty w Web Storage
var student = {
'imie': 'Imiesław',
'nazwisko': 'Nazwiskowy',
'nr_albumu': 99999,
};

//zapisanie reprezentacji tekstowej


localStorage.student = JSON.stringify(student);

//odczytanie danych i konwersja na obiekt


var object = JSON.parse(localStorage.student);

console.log(object.imie);

47
Usuwanie elementów

//Local storage
localStorage.removeItem("click_count");

//Session storage
sessionStorage.removeItem("lastname");

48
AJAX
AJAX
 Asynchronous JavaScript and XML
 Asynchroniczne pobieranie danych z serwera już po
załadowaniu strony do przeglądarki
 Zamiast przeładowywać całą stronę, pobierany jest
jedynie jej fragment, który zostaje wyświetlony
w przeglądarce przy użyciu API DOM
 Powszechnie wykorzystywany na stronach
internetowych (np. Moja PG, eNauczanie)
 Różnice w API pomiędzy przeglądarkami
 Przykład przy okazji biblioteki jQuery
50
Żądania synchroniczne
Kompletny dokument HTML Kompletny dokument HTML
Przeglądarka

aktywność oczekiwanie na aktywność oczekiwanie na aktywność


użytkownika załadowanie użytkownika załadowanie użytkownika
strony strony
żądanie żądanie
HTTP HTTP
odpowiedź odpowiedź
HTTP HTTP

przetwarzanie przetwarzanie
Serwer żądania żądania
51
Żądania asynchroniczne: AJAX
Przeglądarka

aktualizacja aktualizacja
aktywność fragmentu strony fragmentu strony
użytkownika z użyciem API DOM

żądanie żądanie
HTTP HTTP
odpowiedź odpowiedź
HTTP HTTP

przetwarzanie przetwarzanie
Serwer żądania żądania
52
Interakcja z AJAX’em
Interakcja z AJAX’em
1. Klient (użytkownik) generuje zdarzenie
2. Utworzenie i konfiguracja obiektu XMLHttpRequest (w
przeglądarce).
3. Obiekt XMLHttpRequest tworzy (generuje) żądanie
4. Żądanie jest przetwarzane przez serwlet (tutaj strona
validate.php)
5. Wynikiem strony validate.php jest dokument XML (!!)
6. Obiekt XMLHttpRequest wywołuje funkcję callback() i
przetwarza rezultat
7. DOM HTML jest uaktualniany

54
Literatura pomocnicza:
❑ D.Goodman,M. Morrison, P. Novitski, T.G. Rayl: „JavaScript Bible, Seventh
Edition”; 2010 Wiley Publishing; isbn:978-0-470-52691-0
❑ http://www.syncfusion.com/resources/techportal/ebooks JavaScript_Succinctly
❑ http://www.w3schools.com/jsref/jsref_statements.asp
❑ http://www.w3schools.com/jsref/dom_obj_document.asp
❑ http://www.w3schools.com/jsref/dom_obj_event.asp
❑ https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded
RESPONSYWNE
INTERFEJSY
Klasy urządzeń klienckich
Responsywne style CSS
Waldemar Wytwarzanie Aplikacji Internetowych
Korłub KASK ETI Politechnika Gdańska
Klasy urządzeń klienckich
 Desktopy z zewnętrznymi monitorami
 Laptopy
 Tablety
 Smartphony
Klasy urządzeń klienckich
 Desktopy z zewnętrznymi monitorami
 Panoramiczne, najczęściej format 16:9 lub 16:10
 Powyżej 19 cali

 Rozdzielczości: 1440x900, 1680x1050, 1920x1080


i wyższe
 Mysz i klawiatura

 Laptopy
 Panoramiczne, najczęściej format 16:9 lub 16:10
 Powyżej 12 cali

 Rozdzielczości: 1366x768, 1280x800 i wyższe

 Mysz, klawiatura, ekran dotykowy


Klasy urządzeń klienckich
 Tablety
 Orientacja pozioma lub pionowa, formaty 4:3, 16:9,
16:10 i inne
 Od 7 do 12 cali
 Rozdzielczości: 800x600, 1366x768, 1920x1080
i wyższe
 Ekran dotykowy

 Smartphony
 Najczęściejużywane w orientacji pionowej
 Od 3,5 do 6 cali
 Rozdzielczości: 480x800, 800x1280, 1080x1920 i wyższe
 Ekran dotykowy
Desktop vs smartphone

1 Orientacja pozioma vs orientacja pionowa

2 19+ cali vs ok. 5 cali

3 Mysz i klawiatura vs ekran dotykowy

4 Duża moc obliczeniowa vs procesory mobilne

5 Szybkie, stałe łącze vs Internet mobilny


Interfejs nie-responsywny

Przykład: 01-not-responsive
Wymagania dla stron mobilnych
 Wyeliminowanie konieczności skalowania strony
i przewijania w poziomie
 Dopasowanie układu i rozmiaru elementów do obszaru
wyświetlania (ang. viewport) przeglądarki mobilnej
 Dopasowanie rozmiaru czcionek w interfejsie

 Ograniczenie dystansu od szczytu strony do


początku jej zasadniczej treści
 Ograniczenie konieczności przewijania w pionie
 Optymalizacja pod kątem obsługi palcami, a nie
kursorem myszy
 np. kłopotliwe zdarzenie :hover
Jak spełnić te wymagania?
 Wymuszenie obszaru renderowania strony
o szerokości wyświetlacza:
<meta name="viewport"
content="width=device-width, initial-scale=1">
 Wykorzystanie całej szerokości ekranu
 np. eliminacja zbędnych marginesów
 Unikanie wyświetlania wielu elementów sąsiadujących
ze sobą w poziomie
 Unikanie bezwzględnych wymiarów dla elementów
determinujących układ strony
 Ukrywanie elementów poza zasadniczą treścią strony
Jak spełnić te wymagania?
 Różne zestawy stylów dla różnych urządzeń
//style wspólne dla wszystkich urządzeń main.css
body {
font-family:'Signika Negative',sans-serif; /*czcionka*/
}

//style dla smartphonów


@media (max-width: 768px) { /*...*/ }

//style dla tabletów


@media (min-width: 768px) and
(max-width: 992px) { /*...*/ }

//style dla desktopów/laptopów


@media (min-width: 992px) { /*...*/ }
Obszar wyświetlania strony
 Szerokość obszaru wyświetlania w dyrektywie
@media nie musi przekładać się na rzeczywistą
rozdzielczość wyświetlacza
 Natywna rozdzielczość ekranu a rozdzielczość
efektywna
 skalowanie
 dp - density independent pixels– jednostka wirtualna,
zalecana przy tworzeniu układu interfejsu użytkownika
w systemach Android; wyraża wymiary i położenie w
sposób niezależny od gęstości pikseli (dpi).
Responsywny interfejs

Przykład: 02-responsive
Organizacja zestawów stylów CSS
 Różne podejścia:
 Osobne zbiory atrybutów dla każdej grupy urządzeń
 Często też osobne dokumenty HTML, dedykowane urządzeniom
 Optymalizacja interfejsu dla każdej grupy z osobna
 Desktop-first
 Domyślne style dla dużych urządzeń
 Małe urządzenia dziedziczą style po dużych
 W blokach @media { /*…*/ } zmieniane są style elementów,
które nie spełniają mobilnych wymagań
 Mobile-first
 Domyślne style dla urządzeń przenośnych
 Duże urządzenia dziedziczą po małych
 W blokach @media { /*…*/ } optymalizowane są style
elementów, które mogą skorzystać na większej przestrzeni
Desktop-first
/* style dla desktopów/laptopów */
aside { width: 214px; float: left; }
main { width: 690px; margin-left: 242px; }

/* style dla urządzeń mobilnych */


@media (max-width: 768px) {
main, aside {
width: auto;
margin: 0px;
}

aside {
float: none;
}

/*...*/
}
Desktop-first
 Istniejące już strony, do których dodawany jest
interfejs dla urządzeń mobilnych
 Istniejące elementy należy dostosować do mniejszych
ekranów
 Jeśli jakiś element zostanie pominięty, interfejs
będzie niepoprawnie wyświetlany na małym ekranie
Mobile-first
/* style dla urządzeń mobilnych */
main, aside {
width: auto;
margin: 0px;
}

/* style dla desktopów/laptopów */


@media (min-width: 992px) {
aside { width: 214px; float: left; }
main { width: 690px; margin-left: 242px; }

/*...*/
}
Mobile-first
 Większość nowych aplikacji internetowych
 Jeśli interfejs mieści się na małym ekranie,
to tym bardziej zmieści się na dużym
 Może nie będzie optymalny…
 …ale zawsze poprawny!

 Jeśli jakiś element zostanie pominięty, wyświetli się


przynajmniej poprawnie
Literatura uzupełniająca:
 http://www.w3schools.com/html/html_responsive.asp
 http://www.w3schools.com/Css/css_responsive_intro.asp
 http://learn.shayhowe.com/advanced-html-
css/responsive-web-design/
PRZEGLĄDARKA
I JEJ OTOCZENIE
Krystyna Wytwarzanie Aplikacji Internetowych
Dziubich KASK ETI Politechnika Gdańska
Web…
 Web Page - pojedyncza strona HTML
 http://julian.eti.pg.gda.pl/dydaktyka.html
 XHTML 1.1
 Web Site – zbiór stron logicznie powiązanych
 http://julian.eti.pg.gda.pl/
◼ http://julian.eti.pg.gda.pl/index.html,
◼ http://julian.eti.pg.gda.pl/dydaktyka.html
◼ http://julian.eti.pg.gda.pl/publikacje.html
 Web Application – aplikacja (np. kod PHP, JSP, ASP) działająca po
stronie serwera www i komunikująca się z przeglądarką klienta
 http://sklep.jack-wolfskin.pl/
 HTML 5
DOCTYPE
 Deklaracja typu dokumentu
 http://www.w3schools.com/tags/tag_doctype.asp
 <!DOCTYPE html>

 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01


Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"


"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
Weryfikacja poprawności

 https://validator.w3.org/  http://jigsaw.w3.org/
#validate_by_uri+with_o css-validator/
ptions
XML poprawnie sformułowany
1. Rozpoczyna się deklaracją XML
<?xml version= ” 1.1” encoding= ” UTF-8” standalone= ” yes” ?>
2. Znacznik początkowy <coś> posiada zawsze znacznik
końcowy </coś>
3. Elementy puste kończą znaki /> np. <pusty />
4. Zawiera dokładnie jeden element główny, który zawiera
wszystkie inne elementy
5. Elementy nie mogą się przeplatać
<osoba> <imie> Agata </osoba> </imie>
6. Wartości atrybutów zawarte są w cudzysłowach ” lub ‘
<img src=„poranek.jpg” alt=‘Bóg rzekł: „Niech się stanie światłość...” i tak
się stało’ />
<element text=”cudzysłów pojed. to &apos; a podw. to &quot; ”>
XML poprawnie sformułowany cd.
1. Znaków < i & używaj tylko do otwierania znaczników i encji –
używaj zamienników &lt; i &amp;
<h1> Tom &amp; Jery </h1> dla <h1> Tom & Jery </h1>
2. Używaj tylko encji predefiniowanych: &amp; &lt; &gt; &apos;
&quot;
Uwaga: każdy znak można zapisać jako &#
i dziesiętny lub szesnastkowy kod znaku w Unicode
np.: &#8482; dla znaku ™
3. Nazwy znaczników i atrybutów muszą zaczynać się od litery lub
podkreślenia dalej mogą być litery, cyfry, podkreślenia, znaki – i
kropki.
4. Komentarze oznaczamy: <!-- to jest komentarz -->
X/HTML - poprawność
Tak jak każdy dokument XML, dokument XHTML powinien być:
 poprawny składniowo (well-formedness) – zgodny z regułami
XML;
można ją sprawdzić wysyłając dokument z typem treści
ustawionym na application/xhtml+xml i otwierając w
obsługującej XHTML przeglądarce, w przypadku błędu ma
ona obowiązek nie wyświetlić dokumentu
dla IE – zmieniamy nazwę lokalnego pliku xhtml na .xml,
próbujemy otworzyć (jeżeli poprawny składniowo – drzewko
xml)
 poprawny strukturalnie - walidacja (validity) – zgodność z
regułami określonymi w skojarzonym z danym typem dokumentu
schemacie (DTD wymieniony w dyrektywie Doctype)
7
składniowo? | strukturalnie?

<!DOCTYPE html>
<html lang="pl">
<body>
<p> test
</body>
</html>
XHTML 1.0 Strict
<?xml version="1.0" encoding="iso-8859-2" ?>
<!DOCTYPE html PUBLIC -//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<?xml-stylesheet type= "text/css" href="style.css" ?>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="pl"
lang="pl">
<head>
<title>Przykładowy dokument XHTML</title>
<meta http-equiv="Content-Type"
content="application/xhtml+xml; charset=iso-8859-2" />
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<p xml:lang="en" lang="en">Example of XHTML 1.0
Strict</p>
</body>
</html>
Przykładowy dokument kompatybilny z HTML
9
Jaki HTML stosować?
 Standardy w3c: https://www.w3.org/TR/

 Wystarczająco dojrzały, ale może nie już przejrzały


 implementowany w przeglądarkach (… na różnych
urządzeniach)
 https://www.w3schools.com/tags/ref_html_browsersupp
ort.asp
 https://html5test.com/index.html
Media Type
Media Type HTML4 XHTML 1.0
text/html should may

application/ xhtml + xml must not should


application / xml must not may
text / xml must not may

 Typ text/html –typ do przesyłania dokumentów HTML, jednak dopuszczalne


przejściowo do dokumentów XHTML 1.0 (wówczas traktowane są one jak zwykły
HTML (nie jest sprawdzana poprawność składniowa, powstaje tzw. „zupa
znaczników”).
 Typ application/xhtml+xml – jest to typ mediów stworzony specjalnie dla XHTML.
Przeglądarki obsługujące ten typ automatycznie sprawdzają zgodność dokumentu z
zasadami XML. Odpowiednikiem wysłania pliku z tym typem jest na dysku lokalnym
zmiana rozszerzenia pliku z .html (lub .htm) na .xhtml (lub .xht).
 Typy application/xml i text/xml – są to natywne typy zawartości XML, można z
nich korzystać w przypadku każdej wersji XHTML
 Inne: text/plain, text/css, image/png, application/javascript, video/mp4, ….
multipart/form-data (formularz wysyłany metodą post)
Jak to wygląda od spodu?
Timing / chronometraże
Nagłówki żądania (Request)
Google Chrome v.61 Narzędzia Deweloperskie
Nagłówki odpowiedzi (Response)
Treść odpowiedzi
http://julian.eti.pg.gda.pl/dydaktyka.html

❑ DOMContentLoaded (event): wejściowy HTML sparsowany i załadowany do obiektu


DOM /bez czekania na załadowanie obrazków, css, zawartości ramek/
❑ Load (event): czas wystąpienia zdarzenia ładowania strony/strona cała załadowana/
Żądania przewidujące
Żądania przewidujące
 klient -> serwer  serwer -> klient
Negocjowanie treści
 Content Negotiation polega na wygenerowaniu odpowiedzi na
żądanie klienta w postaci najbardziej odpowiadającej jego
potrzebom i odesłaniu jej z odpowiednim typem zgodnym z
przygotowaną zawartością.
 server-driven negotiation /proactive negotiation
 agent-driven negotiation /reactive negotiation
Negocjowanie na podstawnie nagłówków HTTP

Serwer weryfikuje nagłówki nadesłane przez klienta pod kątem


informacji o tym czego oczekuje klient
 Accept: określa typy zawartości jakie akceptuje klient np.
text/xml, application/xml, application/xhtml+xml, text/html;q=0.9,
text/plain;q=0.8, image/png,*/*;q=0.5
co preferuje klient?
 Accept-Charset: określa zbiór znaków jaki może zawierać odpowiedź aby
była akceptowana przez klienta
 Accept-Encoding: określa kodowanie zawartości dla odpowiedzi aby była
ona akceptowalna np. compress;q=0.5, gzip;q=1.0
 Accept-Language: określa preferowany typ języka naturalnego (fr, ang, pl)
dla zawartości odpowiedzi
 User-Agent : zawiera informacje o przeglądarce
 Quality values (qvalue) – wartość określająca względną wartość dla
parametru z którym występuje; wartość q jest z zakresu <0,1>
 Wartość q=1 domyślnie jeśli nie podano inaczej
 Zero oznacza że parametr nie jest akceptowany przez klienta

21
Komponenty przeglądarki *
user interface: pasek adresu,
przycisk wstecz/przód, menu
zakładek, itp. ; z wyjątkiem okna
zawierającego wyświetlaną stronę.
browser engine: zarządza akcjami
miedzy interfejsem użytkownika a
silnikiem wyświetlania.
rendering engine : odpowiedzialny
za wyświetlenie żądanej treści. Jeśli
jest to HTML, to silnik parsuje jego
zawartość oraz CSS i wyświetla treść
na ekranie.
Networking: dla żądań sieciowych
typu HTTP (poza interfejsem niezależnym od
platformy wykorzystuje różne implementacje na
różnych platformach)
JavaScript interpreter: Parsowanie i wykonywanie kodu JavaScript
Data storage (persistence layer): przechowuje różne dane UI backend: do rysowania
lokalnie w: cookies, localStorage, sessionStorage, IndexedDB, podstawowych widgetów jak pole
WebSQL i wewnętrzny system plików. wyboru, okno. Tylko ogólny interfejs
który nie jest zależny od platformy.
Rendering engines - np.Trident

Firefox - Gecko,
Safari –WebKit,
Internet Explorer -Trident,
Chrome and Opera (ver. 15+) - Blink.
Rendering engine –WebKit main flow

Kolejność rysowania dla


elementu blokowego:
• Kolor tła;
• Obraz tła;
• Ramka;
• Dzieci;
• Kontur /obrys

How Browsers Work (in 4 min): http://www.youtube.com/watch?v=7fXhE5ErUCM


Drzewo DOM <-> drzewo wyświetlania

 DOM tree - Render tree


 Render tree nie ma pozycji ani wielkości;
 wyznaczenie ich to utworzenie układu na stronie (Layout) w ramach Viewport
(widoczna część okna przeglądarki)
Pytania?
PROTOKOŁY
INTERNETOWE
Waldemar Wytwarzanie aplikacji internetowych
Korłub KASK ETI Politechnika Gdańska
Co się dzieje po wpisaniu adresu w
oknie przeglądarki internetowej?
URI, URL, URN
 URL – Uniform Resource Locator
 Ustandaryzowany adresu zasobu (dokumentu,
obrazu, pliku…) w sieci
 składa się z następujących części:
◼ [schemat protokołu] [separator np. ://] [lokalizacja
zasobu specyficzna dla schematu]
◼ http://www.imdb.com
◼ ftp://astro.caltech.edu
 URI
 Uniform Resource Identifier [RFC 2369]
 wskazuje w sposób szczególny na zasób w
Internecie
 może to być nazwa, adres lub obydwa atrybuty.
URI, URL, URN
 URI
 Zazwyczaj krótki łańcuch znaków, zapisany
zgodnie z określoną w standardzie
składnią
 Łańcuch ten określa nazwę lub adres
zasobu, którego dotyczy dany URI
 Składa się z URL (adresu, lokalizacji) i/lub
URN (nazwa)
 URN – Uniform Resource Name
 Nazwa zasobu
 Nie określa gdzie zasób się znajduje i jaki
jest schemat dostępu (NID i NSS)
Typy adresów URL
 Ogólny (bezwzględny) – przykłady:
protokół://lokalizacja_serwera:port/ścieżka_na_serwerze?parametry
http://my.host:1234/resource?p1=1&p2=2

protokół://użytkownik:hasło@LokalizacjaSerwera:port/ścieżkaNaSerwerze
ftp://nobody:unknown@ftp.site/index.html

schemat:użytkownik@lokalizacja_serwera
mailto:user@my.mail

schemat://user:pass@adres.com:8042/gdzies/index.php?param=animal&name=mysz#paragraf
\______/\_________/ \__/\_________/ \___/ \_/ \_________/ \_________/ \__/
scheme userinfo hostname port path filename extension parameter(s) query fragment

 Względny
 Może pomijać schemat, nazwę hosta, ścieżkę i nawet
nazwę pliku, np.: /login, /users?sort=asc
DNS: Domain Name System
 Nazwy domenowe (np. pg.edu.pl) są czytelne dla
człowieka i łatwe do zapamiętania
 Typowo zawierają nazwę świadczonej usługi
 Aby połączyć się z docelowym serwerem konieczna
jest jednak znajomość jego adresu IP
 np. 153.19.40.170, 216.58.215.78
 Serwery DNS odpowiadają za translację (ang.
lookup) nazwy domenowej na adres IP serwera
 Usługa reverse lookup realizuje odwrotną operację
 Polecenie dig umożliwia odpytywanie serwerów DNS
DNS
Eclipse.eti.pg.gda.pl
153.19.55.226

153.19.55.226

Adres w przeglądarce:
eclipse.eti.pg.gda.pl
HTTP: Hypertext Transfer Protocol
 Znając adres IP docelowego serwera możemy się z
nim połączyć
 Następnie należy poinstruować serwer, jakie zasoby
chcemy pobrać
 Konieczny jest pewien protokół komunikacyjny
zarozumiały dla klienta i dla serwera
HTTP: Hypertext Transfer Protocol
 Protokół warstwy aplikacyjnej
 Komunikacja w modelu żądanie-odpowiedź (request-
response) pomiędzy klientami i serwerami
 Domyślny port: 80
 Klient: typowo przeglądarka internetowa
 Serwer WWW
 oprogramowanie, które zazwyczaj działa jako tzw. demon
(daemon, usługa systemowa)
 oczekuje na żądania od klientów i przesyła w odpowiedzi
dokumenty z serwera
HTTP: Hypertext Transfer Protocol
 Protokół bezstanowy (stateless)
 Serwer nie utrzymuje stanu konwersacji z klientem
pomiędzy żądaniami
 Przesyłane komunikaty mają określoną strukturę
 Zarówno żądanie, jak i odpowiedź składają się z:
 Komendy/statusu (z dokładnie określonym formatem)
 Nagłówków (niekiedy opcjonalne)

 Opcjonalnej treści oddzielonej od komendy i nagłówków


pojedynczą pustą linią (ang. entity body)
HTTP

Na bazie: https://zoompf.com/blog/2010/03/performance-tip-for-http-downloads,
Żądanie klienta

Zasób pod tym adresem

Host: www.allegro.pl:80 – połączenie TCP

GET /index.html HTTP/1.1


Host: www.allegro.pl
<>
Proponowana
wersja protokołu
Komenda żądania

Nagłówek Ulokowanie zasobu w katalogu wirtualnym


HTTP – typy zapytań
 GET - uzyskanie zasobu o podanym URI
 POST – (od HTTP 1.0) przesłanie danych do zasobu
o podanym URI, dane zawarte są w treści żądania
 HEAD - (od HTTP 1.0) jak GET, ale w odpowiedzi
uzyskujemy sam nagłówek
 LINK - (tylko HTTP 1.0) i UNLINK - (tylko HTTP 1.0)
– tworzy relacje między zasobami
 OPTIONS (od HTTP 1.1) - uzyskanie informacji o
metodach akceptowalnych przez dany zasób lub
serwer
HTTP – typy zapytań
 PUT (od HTTP 1.1) - umieszczenie na serwerze
zasobu w podanym URI, zawartość zasobu
określona jest przez treść żądania
 DELETE (od HTTP 1.1) - usunięcie z serwera zasobu
o podanym URI
 TRACE (od HTTP 1.1) - wykonanie rodzaju testu
przesłania wiadomości w pętli zwrotnej na samym
serwerze - odpowiedź do faktycznego klienta
zawiera to co klient przesłał
 CONNECT (od HTTP 1.1) – używana przez proxy
do tworzenia tuneli
GET i POST
 GET służy do pobrania określonego zasobu (zazwyczaj
pierwsze żądanie)
 Razem z URL można dołączyć dodatkowe parametry:
http://server/file?variable=val&variable2=val
 Większość serwerów www ma limit długości żądania (od
1024 – 4096 znaków)
 Format przesyłanych danych to URL encode - symbole
zastępowane %XX (np. %2E), spacje zamieniane na +
(w starszych wersjach)
 POST – brak ograniczenia z GET
 Wysyłanie dodatkowych informacji (parametrów) oprócz
właściwego żądania
 Przesyłane informacje są w kodowane w wybranym
standardzie MIME lub URL encode
Odpowiedź serwera

Linia statusu
Nagłówki

HTTP/1.1 200 OK
Date: Mon, 23 Sep 2016 22:38:34
GMTServer: Apache/1.3.27 (Unix) (Red-Hat/Linux)
Last-Modified: Wed, 08 Jan 2016 23:11:55
Content-Length: 438 Linia pusta
Connection: close
Content-Type: text/html
Content-Length: 32

--frontier Body
This is the text body of the document
--frontier
Format odpowiedzi
 Pierwsza linia odpowiedzi ma postać
WERSJA_HTTP KOD_ODPOWIEDZI STATUS

 Wersja HTTP: wersja obsługiwana przez serwer, nie


musi odpowiadać wersji w żądaniu
 Ciąg znaków HTTP/1.0 lub HTTP/1.1
 Kod odpowiedzi: numeryczny, trzyznakowy,
pierwsza cyfra określa klasę odpowiedzi
 Status: krótki ciąg znaków wyjaśniający zwrócenie
takiego, a nie innego kodu odpowiedzi
Klasy/kody odpowiedzi
 1xx: klasa informacyjna,
 żądanie zostało odebrane i jego przetwarzanie jest
kontynuowane, np. 100 - kontynuacja procesu
 2xx: klasa odpowiedzi pozytywnych
 żądanie zostało poprawnie odebrane, zrozumiane i
zaakceptowane np. 200 - po prostu OK
 3xx: klasa przekierowania,
 należy podjąć dodatkową czynność, aby ukończyć
żądanie, np. 301 - zasób przeniesiony na stałe, 302 -
zasób przeniesiony czasowo, 304 - brak modyfikacji
Klasy/kody odpowiedzi
 4xx - klasa błędów klienta,
 żądanie zostało niepoprawnie sformułowane lub nie
może zostać spełnione
 np. 400 - nieprawidłowe zapytanie, 403 - dostęp do
zasobu zabroniony, 404 - zasób nie znaleziony
 5xx - klasa błędów serwera,
 wystąpił błąd po stronie serwera podczas
przetwarzania poprawnego żądania
 np. 500 - wewnętrzny błąd serwera, 501 - metoda
niezaimplementowana
Żądanie HTTP w przeglądarce
HTTP – historia wersji
 HTTP/0.9 – 1991
 HTTP/1.0 – 1996
 HTTP/1.1 – 1997
 …długo…
 …długo…
 …nic…
 Odświeżona specyfikacja HTTP/1.1 – 2014
 Uwzględnienie w specyfikacji typowych praktyk
stosowanych przez przeglądarki i serwery HTTP
 HTTP/2.0 – 2015
Specyfikacje protokołów
 HTTP 0.9, HTTP 1.0 RFC1945
 HTTP 1.1 (RFC 2616)
 RFC7230 — HTTP/1.1 Message Syntax and Routing,
 RFC7231 — HTTP/1.1 Semantics and Content,
 RFC7232 — HTTP/1.1 Conditional Requests,
 RFC7233 — HTTP/1.1 Range Requests,
 RFC7234 — HTTP/1.1 Caching,
 RFC7235 — HTTP/1.1 Authentication.
 HTTP 2.0
 RFC7540 — Hypertext Transfer Protocol Version 2
(HTTP/2)
 RFC7541 — HPACK: Header Compression for HTTP/2
HTTP/1.0 vs HTTP 1.1
 trwałe połączenia
 potokowość z wykorzystaniem trwałych połączeń,
 dopracowany mechanizm pamięci podręcznej
cache,
 mechanizm wirtualnych hostów
 serwowanie innych zasobów w zależności od nazwy
hosta w polu nagłówkowym Host z jednego adresu IP
 Rewizja HTTP/1.1 z 2014: zniesienie limitu dwóch
równoczesnych połączeń trwałych od tego samego
klienta
 …który i tak był od lat ignorowany przez przeglądarki
HTTP/1.0 vs HTTP 1.1
 przesyłanie wiadomości o nieznanym z góry
rozmiarze,
 przesyłanie fragmentów zasobu,
 porzucenie wsparcia dla HTTP/0.9
 nowe komendy
 URI zasobu ogólny lub względny w HTTP 1.0, w 1.1
tylko względny (ogólny może wystąpić tylko w
przypadku łączenia przez serwer proxy)
Wybrane aspekty HTTP - Nagłówki
 Wyróżnia się 4 kategorie nagłówków (HTTP/1.1):
 ogólne (ang. general header fields), które maja˛
zastosowanie zarówno dla żądania jak i odpowiedzi: Date,
Pragma,
 dotyczące żądania (ang. request header fields), które
pozwalają przekazać serwerowi dodatkowe informacje na
temat żądania i klienta: Authorization, From, If-
Modified-Since, Referer, User-Agent,
 dotyczące odpowiedzi (ang. response header fields), które
pozwalają przekazać klientowi dodatkowe informacje na
temat serwera i lokalizacji zasobu: Location, Server,
WWW-Authenticate,
 dotyczące zasobu (ang. entity header fields), które definiują
opcjonalne metainformacje: Allow, Content-Encoding,
Content-Length, Content-Type, Expires, Last-
Modified.
Wybrane aspekty HTTP - Nagłówki
 Host Żądanie (HTTP 1.1)
 Nazwa i ewentualnie port serwera. Wymagane przy łączeniu
bezpośrednim, bez proxy.
 Location Odpowiedź
 URI zasobu w przypadku przekierowania.
 Content-Type Żądanie/Odpowiedź
 Typ MIME przesyłanej treści
 Content-Length Żądanie/Odpowiedź
 Długość w bajtach przesyłanej treści
 Accept Żądanie
 Specyfikacja typów MIME zasobów akceptowalnych przez
klienta
Wybrane aspekty HTTP - Nagłówki
 Allow Odpowiedź
 Lista metod akceptowalnych przez serwer lub zasób
 User-Agent Żądanie
 Identyfikator przeglądarki
 Referer Żądanie
 URI zasobu, z poziomu którego wystąpiło żądanie
 Connection Żądanie/Odpowiedź
 (HTTP 1.1) Rodzaj połączenia: Keep-Alive lub Close
Bezpieczny HTTP, czyli HTTPS
 Bezpieczna wersja HTTPS (od Secure).
 Kodowanie sesji poprzez użycie protokołów
SSL (Secure Socket Layer) lub TLS (Transport
Layer Security).
 Domyślny port 443

 SSL (Secure Socket Layer) - protokół


kryptograficzny opracowany przez Netscape
Bezpieczny HTTP, czyli HTTPS
 W ramach sesji SSL używa się kryptografii
przy pomocy algorytmów asymetrycznego
 (parakluczy: publiczny i prywatny) oraz
symetrycznego (jeden klucz)
 Wszystkie dane przed wysłaniem kodowane
są własnym kluczem symetrycznym
 Bezpieczeństwo transmisji zależy głównie od
rozmiaru kluczy. Za wystarczające uznaje się
(jeszcze) 128 bitów dla klucza sesji i 1024 dla
klucza publicznego
Komunikacja HTTPS
Przebieg sesji połączenia przez SSL:

1. Wymiana certyfikatów (CA) pomiędzy klientem i


serwerem. CA zawiera uwierzytelnione informacje o
właścicielach i klucze publiczne. Przeglądarka może
podać własny CA, jeżeli brakuje CA użytkownika

2. Uzgodnienie algorytmu kryptograficznego opartego o


klucz symetryczny - wybierany jest zawsze najmocniejszy
algorytm znany obu stronom

3. Wygenerowanie osobno przez klienta i serwer tzw.


symetrycznego klucza sesji

4. Wymiana kluczy sesji zakodowanych kluczem


publicznym "rozmówcy"

5. Odkodowanie kluczy sesji przy pomocy własnego


klucza prywatnego i rozpoczęcie wymiany danych

Na bazie: https://zoompf.com/blog/2010/03/performance-tip-for-http-downloads,
HTTP/2.0
 Bazuje na protokole SPDY, opracowanym przez
Google
 Opublikowany w RFC 7540, w maju 2015
 Obsługa przez serwery:
http://isthewebhttp2yet.com/measurements/adopti
on.html
 Zachowuje wysoką kompatybilność z 1.1 (komendy,
statusy, większość nagłówków, adresy URI)
HTTP/2.0
 Zmniejszenie opóźnienia w ładowaniu stron poprzez:
 kompresję danych w nagłówkach
 rozwiązanie blokowania pierwszego żądania

 ładowanie elementów w sposób jawnie równoległy

 wykorzystanie pojedynczego połączenia na poziomie


gniazd do transmisji wielu żądań i odpowiedzi.
 wykorzystanie protokołu UDP

 wykorzystanie mechanizmu push


Ramka HTTP 2.0
Przesyłanie ramek w obrębie
dwukierunkowego połączenia

Żródło: na podstawie High Performance Browser Networking,Ilya Grigor, O'Reilly Media, 2013
HTTP/1.1 vs HTTP/2
Serwery HTTP
 Apache
 NGINX
 IIS
 Tomcat
 Jetty
 JBoss
 …
Rzeczywisty kanał komunikacyjny
Pytania?

You might also like