Professional Documents
Culture Documents
Wykladyall in 1
Wykladyall in 1
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
¨ Przemieszane ze sobą:
¤ Logika obsługi żądań HTTP
¤ Logika biznesowa
¤ Interfejs i logika jego wyświetlania
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
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ą
¤ 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
¨ 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
📂 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
¨ 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
¨ Rozwiązanie: front-controller
Front-controller
23
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
¨ Rozwiązanie: mod_rewrite
mod_rewrite
28
📂 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
¨ 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
$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
¨ 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';
📂 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
📂 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
¨ 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
//...
43
function products(&$model) Obsługa parametrów
{ żądania HTTP
/* ...aspekty globalne... */
$action_url = $_GET['action'];
$controller_name = $routing[$action_url];
$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
}
}
$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
49
<?php front_controller.php
require_once '../dispatcher.php';
require_once '../routing.php';
require_once '../controllers.php';
/*...aspekty globalne...*/
📂 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
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
¨ Szablony widoków
¨ 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
¤ 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)
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" .../>
<!-- ... -->
3. Weryfikacja:
if ($password === $repeat_password){ //...
Rejestracja użytkowników
4. Zahashowanie hasła:
$hash = password_hash($password, PASSWORD_DEFAULT);
6. Redirect:
header('Location: success.php');
exit;
Logowanie
1. Formularz logowania:
<input type="text" name="login" .../>
<input type="password" name="pass" .../>
6. Przekierowanie:
header('Location: profile.php');
exit;
Wylogowanie
¨ Wyczyszczenie danych bieżącej sesji:
¤ Programistyczne:
session_destroy();
//następnie usunięcie cookie
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
¤ 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
¨ 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
session_start();
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
…
nasz …
projekt
…
…
…
Zależności projektu
6
{
"nazwa": "Laptop XYZ",
"producent": "ABC123",
"specyfikacja": {
"CPU": "Intel i7",
"RAM": "8 GB",
"HDD": "1 TB"
}
}
Dokument – reprezentacja w PHP
14
<?php
$dokument = [
"nazwa" => "Laptop XYZ",
"producent" => "ABC123",
"specyfikacja" => [
"CPU" => "Intel i7",
"RAM" => "8 GB",
"HDD" => "1 TB"
]
];
Kolekcja, baza danych, instancja
15
Instancja MongoDB
… bazy
danych
sklep finanse CRM
dokumenty
Dynamiczna struktura danych
17
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();
$db = get_db();
$query = [
'_id' => new ObjectId($id)
];
Identyfikator bazodanowy
$product = $db->products->findOne($query);
Oczekiwany
pojedynczy rezultat
Operatory wyszukiwania
26
$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
$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);
$page = 3;
$pageSize = 3;
$opts = [
'skip' => ($page - 1) * $pageSize,
'limit' => $pageSize
];
$users = $db->users->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;
$query = [
'name' => [
'$regex' => 'laptop',
'$options' => 'i’
]
]; Aktualizowane
pola
$newVals = ['price' => 999];
$db->products->
updateMany($query,['$set' => $newVals]);
use MongoDB\BSON\ObjectID;
$id = '5605b1e9b80de4f1478b4571';
$query = ['_id' => new ObjectId($id)];
$db->products->deleteOne($query);
Przykład: 02-mongodb
37 Pytania?
1
¨ 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
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
¨ Dlaczego?
¤ Kliknięcie w bookmark, odświeżenie strony,
wysłanie linku do innej osoby
¤ Cachowanie odpowiedzi
POST
8
tytul=Wodospad+Skogafoss&autor=WK&ocena=9&opis=J
eden+z+najbardziej+malowniczych+wodospad%C3%B3w+
Islandii
POST
9
¨ 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
<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>
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
//żądanie POST
} else {
//najpewniej GET
}
Formularze: pole tekstowe
18
<?php
$tytul = $_POST['tytul'];
Formularze: pole hasła
19
<?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
<?php
$id = $_POST['id'];
Formularze: pole nieaktywne
24
<form method="post"
enctype="multipart/form-data">
Array (
[name] => giraffe.jpg
[type] => image/jpeg
[tmp_name] => /tmp/php1gzN7z
[error] => 0
[size] => 50094
)
Informacje o nadesłanym pliku
27
$upload_dir = '/var/www/dev/web/upload/';
$file = $_FILES['zdjecie'];
$file_name = basename($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
<?php przelew.php
if($_SERVER['REQUEST_METHOD']==='POST' &&
!empty($_POST['nr_konta'])/* && ... */
) {
$nr_konta = $_POST['nr_konta'];
//...
//zlecenie przelewu
Status: przyjęty
do realizacji Odśwież
POST przelew.php
POST i przycisk Odśwież
37
<?php przelew.php
if ($_SERVER['REQUEST_METHOD']==='POST' &&
!empty($_POST['nr_konta']) /* ... */
) {
$nr_konta = $_POST['nr_konta'];//...
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 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
¤ Znak BOM
Buforowanie odpowiedzi
46
<?php
$imie = 'Waldemar';
nazwa wartość
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
5. Odpowiedź HTTP
2. Lokalizacja
zasobu
Ź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
¨ Język wieloparadygmatowy
¤ Imperatywny, proceduralny
¤ Obiektowy
¤ Funkcyjny
¨ 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
¨ 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
¨ Niezalecany
¤ Usunięty z języka od wersji PHP 7.0
Inne znaczniki dla bloków PHP
29
¨ Znacznik pełny:
<?php
...kod źródłowy...
?>
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
<?php
¨ Sposoby definiowania:
¤W podwójnym cudzysłowie
¤ W pojedynczym cudzysłowie
¤ Składnia heredoc
¤ Składnia nowdoc
<?php
$imie = "Imiesław";
$nazwisko = 'Nazwiskowy';
$wiek = 37;
$wynik = 22.5;
<?php
$imie = "Imiesław";
$nazwisko = 'Nazwiskowy';
$wiek = 37;
$wynik = 22.5;
$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
$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
<?php
$imie = "Imiesław";
$nazwisko = 'Nazwiskowy';
$wiek = 37;
$wynik = 22.5;
$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
echo strlen($imie);
13
echo mb_strlen($imie); 10
Zmienne typu logicznego (boolean)
52
¤ FALSE
¤ Pusta tablica
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
<?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
//zamiast:
<?php echo $zdanie ?>
//forma skrócona:
<?= $zdanie ?>
Instrukcje warunkowe: if
62
<?php
$wynik = 22.5;
} else {
echo "egzamin niezaliczony";
}
Instrukcje warunkowe: if
63
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
$poprawne = true;
alternatywa
} else {
$poprawne = false;
} koniunkcja
<?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
warunek
$i = 0;
for ($i++; $i; $i = 0) {
echo "$i ";
}
Pętle: while i do-while
72
$n = 176; $n = 176;
if ($n % 2 == 0) { if ($n % 2 == 0) {
$n = $n / 2; $n = $n / 2;
} else { } else {
$n = $n * 3 + 1; $n = $n * 3 + 1;
} }
¤ endfor
¤ endforeach
¤ itd.
Kod PHP przeplatany z kodem HTML
74
<!DOCTYPE html>
<html>
<body>
<?php
$power = rand(0, 100000);
echo "Power level: $power<br/>\n";
jabłka
//wyświetlenie zawartości tablicy:
for ($i = 0; $i < count($owoce); $i++) {
pomarańcze
echo $owoce[$i].'<br/>'; banany
}
$klienci = [
'Anna' => 21,
Anna ma 21 lat.
'Marek' => 27,
'Barbara' => 45
Marek ma 27 lat.
]; Barbara ma 45 lat.
//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
include 'sciezka/do/pliku.php';
require 'sciezka/do/pliku.php';
include_once 'sciezka/do/pliku.php';
require_once 'sciezka/do/pliku.php';
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
//...
//wywołanie funkcji:
pozdrowienie('Cześć', 'Waldemar');
Cześć, Waldemar!
Funkcje – argumenty domyślne
95
//...
Witaj, świecie!
//wywołanie funkcji:
pozdrowienie(); Cześć, świecie!
pozdrowienie('Cześć');
pozdrowienie('Cześć', 'Waldemar');
Cześć, Waldemar!
Funkcje – wartości zwracane
96
//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
function pozdrowienie($imie){
return "$powitanie, $imie!";
}
Notice: Undefined variable: powitanie
in example.php on line 5
<?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;
21 7 3 21 21 3
Zwracanie wartości przez referencję
102
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
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);
$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
¤ Biblioteki
Najczęściej wykorzystywane
wersje jQuery
http://trends.builtwith.com/javascript
Popularne rozszerzenia 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
Deweloperska Minified
• jquery-1.8.2.js 261 kB • jquery-1.8.2.min.js 92 KB
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
→ 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
AJAX I’m
PHP
Żądanie
Odpowiedź
html,
xml,
json
AJAX
jQuery
Style CSS
…
Zdarzenie window.onload:
<script >
window.onload = function () {
countDivs('window.onload');
};
</script>
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ść");
’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
https://www.w3schools.com/js/js_let.asp
https://www.w3schools.com/js/js_const.asp
20
Tablice
var litery = ['a', 'b', 'c'];
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(student.imie); console.log(student.imie);
console.log(student['imie']); console.log(student['imie']);
'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
var student = {
'imie': 'Imiesław',
'nazwisko': 'Nazwiskowy',
'nr_albumu': 99999
};
{
"imie": "Imiesław",
"nazwisko": "Nazwiskowy",
"nr_albumu": 99999
}
26
JSON: reprezentacja tekstowa → obiekt
{
"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!
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);
}
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
33
Wyszukiwanie elementów
var divs = document.getElementsByTagName('div');
//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
//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');
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"); }
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; }
45
Local storage
46
Obiekty w Web Storage
var student = {
'imie': 'Imiesław',
'nazwisko': 'Nazwiskowy',
'nr_albumu': 99999,
};
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
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
Laptopy
Panoramiczne, najczęściej format 16:9 lub 16:10
Powyżej 12 cali
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
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
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; }
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;
}
/*...*/
}
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!
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 ' a podw. to " ”>
XML poprawnie sformułowany cd.
1. Znaków < i & używaj tylko do otwierania znaczników i encji –
używaj zamienników < i &
<h1> Tom & Jery </h1> dla <h1> Tom & Jery </h1>
2. Używaj tylko encji predefiniowanych: & < > '
"
Uwaga: każdy znak można zapisać jako &#
i dziesiętny lub szesnastkowy kod znaku w Unicode
np.: ™ 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/
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
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)
Na bazie: https://zoompf.com/blog/2010/03/performance-tip-for-http-downloads,
Żądanie klienta
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
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
Ż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?