PHP/Obsługa ciastek: Różnice pomiędzy wersjami

Usunięta treść Dodana treść
drobne techniczne
Linia 6:
Serwer w odpowiedzi na żądanie HTTP wysyła nie tylko kod HTML, lecz także zestaw nagłówków pomagających przeglądarce na zidentyfikowanie dostarczanych treści. Nagłówki precyzują typ MIME danych, np. ''text/html'' dla dokumentu HTML, kodowanie znaków, zachowanie się serwerów proxy, ustawienia cache'owania danych itd. PHP posiada funkcję ''header()'' pozwalającą skryptowi wysłać własne nagłówki. Muszą być one jednak zdefiniowane przed wysłaniem jakiegokolwiek kodu HTML (są to przecież NAGŁÓWKI). W przeciwnym wypadku dostaniemy niemiły komunikat ''Cannot add header information''. Programiści często wykorzystują nagłówki do zdefiniowania typu oraz kodowania w nadsyłanym dokumencie:
 
<source lang="php">
<nowiki><?php
<?php
 
// Bedziemy wysylac dokument HTML z kodowaniem UTF-8
header('Content-type: text/html;charset=utf-8');
 
?>
?></nowiki>
</source>
 
Ale nie tylko. Wiele stron udostępnia swe archiwa nie poprzez bezpośredni dostęp do katalogu, w którym są trzymane, ale poprzez specjalny skrypt, który wysyła ich zawartość do ściągnięcia. Nagłówki umożliwiają powiadomienie przeglądarki, że teraz będzie szedł plik o takiej i takiej nazwie, który internauta chce pobrać na swój dysk twardy. Nie będzie on jednak ujawniać katalogu na serwerze, gdzie on się znajduje. Cała komunikacja prowadzona jest za pośrednictwem PHP.
 
<source lang="php">
<nowiki><?php
<?php
if(!isset($_GET['plik'])) // 1
Linia 38 ⟶ 41:
}
?>
?></nowiki>
</source>
 
Powyższy kod może być częścią jakiegoś serwisu, który swoje artykuły udostępnia także w formacie PDF do ściągnięcia, gdyż aktualnie tylko takie pliki można nim wysyłać. Przeanalizujmy go krok po kroku.
Linia 48 ⟶ 52:
Powyższy przykład możemy nieco przerobić tak, aby z powodu podania błędnej nazwy internauta odsyłany był do naszego własnego komunikatu. Nagłówki umożliwiają robienie przekierowań HTTP i właśnie pragniemy pokazać, jak to się robi.
 
<source lang="php">
<nowiki><?php
<?php
if(!isset($_GET['plik']))
Linia 69 ⟶ 74:
}
?></nowikisource>
 
Źródło jest zasadniczo podobne do poprzedniego przykładu. Zmiany widać jedynie w bloku '''else''', gdzie wysyłamy tym razem nagłówek ''Location''. Informuje on przeglądarkę, że treści nie będzie i powinna raczej skontaktować się z podanym plikiem. Innymi słowy, robimy przekierowanie internauty pod inny adres. Protokół HTTP 1.1 wymaga, aby w nagłówku był podany pełen adres do żądanego zasobu. HTTP 1.0 nie miał takich ograniczeń.
Linia 82 ⟶ 87:
Ciastka są ustawiane za pomocą nagłówków HTTP i mają pewien określony termin ważności. Po jego upływie przestają istnieć. Do wysyłania ciastek służy w PHP funkcja ''setcookie()'', a do pobierania wartości tych ustawionych przez wcześniejsze żądania HTTP - specjalna tablica ''$_COOKIE''. Napiszemy teraz prosty skrypt, który robił furorę kilka lat temu, w okresie popularyzacji dynamicznych witryn WWW. Chodzi o umieszczenie prostej informacji dot. ostatniej wizyty internauty u nas. Aby to wykonać, wystarczy przy pierwszym wejściu umieścić na np. miesiąc ciastko z datą ostatniej wizyty, po czym ją sukcesywnie odczytywać.
 
<source lang="php">
<nowiki><?php
<?php
if(!isset($_COOKIE['wizyta']))
{
Linia 94 ⟶ 100:
}
?></nowikisource>
 
Trzy pierwsze parametry ''setcookie()'' są najważniejsze (ma ona ich trochę więcej). Jest to kolejno: nazwa ciastka, jego wartość oraz data ważności w sekundach od 1.1.1970. Data, a nie okres ważności, stąd przy jego ustawianiu przydaje się funkcja ''time()''. W powyższym skrypcie sprawdzamy, czy ustawialiśmy już ciastko dla danego internauty. Jeśli nie, tworzymy je i wyświetlamy komunikat powitania. W przeciwnym wypadku także aktualizujemy wartość, ale też wyświetlamy datę ostatniej wizyty odczytaną właśnie z ciastka.
Linia 100 ⟶ 106:
Zauważ, że wywołanie ''setcookie()'' nie nadpisuje wartości w tablicy ''$_COOKIE''. Dlatego bez problemu można uprościć powyższy skrypt:
 
<source lang="php">
<nowiki><?php
<?php
setcookie('wizyta', time(), time() + 30 * 86400);
if(!isset($_COOKIE['wizyta']))
Linia 111 ⟶ 118:
}
?></nowikisource>
 
Aby istniejące ciastko skasować, wywołujemy funkcję ''setcookie()'' z jakąś przeszłą datą ważności:
 
<source lang="php">
<nowiki><?php
<?php
setcookie('wizyta', '', 0);
?></nowikisource>
 
=== Funkcje buforowania wyjścia ===
Istnieją sytuacje, kiedy musimy wysłać jakiś kod HTML przed wysłaniem nagłówków HTTP, jednak tradycyjne metody nie pozwalają na to. W PHP można ten problem omijać, używając funkcji buforowania wyjścia. Ogólnie rzecz biorąc, przechwytują one treść wysyłaną przez '''echo''' albo '''print''', zapisując ją do specjalnego bufora. Opróżniamy go samodzielnie na samym końcu skryptu, symulując efekt równoczesnego wysyłania nagłówków i kodu HTML. Pokażemy to na przykładzie:
 
<source lang="php">
<nowiki><?php
<?php
ob_start();
Linia 142 ⟶ 151:
ob_end_flush();
?>
?></nowiki>
</source>
 
Zwróć uwagę, że przed stworzeniem ciastka skrypt wysyła już kod HTML. Dlatego wszystkie instrukcje zawarliśmy między funkcjami ''ob_start()'' i ''ob_end_flush()''. Pierwsza inicjuje buforowanie wyjścia, a druga kończy je, wysyłając jego zawartość do przeglądarki.
Linia 148 ⟶ 158:
Buforowanie wyjścia może też posłużyć do celów algorytmicznych, kiedy musimy przechwycić wysyłany kod, aby go jeszcze dodatkowo obrobić. Naraz można mieć otwartych kilka buforów działających zgodnie z zasadą stosu, tj. ostatni otwarty bufor będzie pierwszym, z którego pobierzemy zawartość. Poniżej prezentujemy mały skrypt cenzorski. Przechwytuje on tekst i cenzuruje go, chyba że internauta zna sposób aktywujący prawdziwą treść. Jest to coś w sam raz dla walczących z dyktaturami opozycjonistów.
 
<source lang="php">
<nowiki><?php
<?php
ob_start();
Linia 178 ⟶ 189:
}
?></nowikisource>
 
Buforowanie wyjścia jest też podstawą tzw. kompresji GZip. Jest to kompresowanie treści strony przed wysłaniem tak, aby zajmowała mniejszą objętość, przez co użytkownik szybciej ją pobierze. Kompresję wspierają wszystkie nowoczesne przeglądarki (np. Opera, Firefox).
Linia 184 ⟶ 195:
Aby uruchomić kompresję GZip, twoja wersja PHP musi mieć doinstalowaną bibliotekę ''zlib''. Wtedy możesz rozpocząć buforowanie poniższym kodem:
 
<source lang="php">
ob_start('ob_gzhandler');
ob_implicit_flush(0);
</source>
 
Parametr przekazywany do ''ob_start()'' to nazwa tzw. uchwytu (handlera) służącego do modyfikacji zbuforowanej treści. ''ob_gzhandler'' jest jednym z predefiniowanych uchwytów, zajmującym się właśnie kompresją GZip. Druga z funkcji nakazuje wywołanie uchwytu dopiero, gdy będziemy mieli już cały kod HTML. Musimy o niej pamiętać dlatego, że nie można skompresować danych wyjściowych partiami - musi to być przeprowadzone w sposób ciągły. PHP samodzielnie wykrywa, czy przeglądarka użytkownika posiada obsługę tej możliwości, dlatego nie musisz o tym pamiętać.