Spis treści

Laboratorium, PHP # 4

Ćwiczenie 1: Dostęp do zewnętrznych danych

Przetestuj działanie poniższych programów. Widzisz różnicę? Zwróć uwagę na napis na środku.

wp.php
<?php
  $c=curl_init('https://www.wikipedia.org');
  curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
  $dane=curl_exec($c);
  curl_close($c);
 
  echo $dane;
?>
wp2.php
<?php
  $c=curl_init('https://www.wikipedia.org');
  curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
  $dane=curl_exec($c);
  curl_close($c);
 
  echo str_replace('Wikipedia','Encyklopedia AGH',$dane);
?>

Ćwiczenie 2: Dostęp do zewnętrznych danych w Wikipedii

Korzystając z serwisu Wikipedia napisz program, który:

  1. zapyta o hasło do znalezienia,
  2. pobierze informacje o w/w haśle,
  3. wyświetli tą informację.

Definicje haseł można uzyskać korzystając z API Wikipedii: https://www.mediawiki.org/wiki/API:Main_page Informacje zwracane są w postaci JSON, np. zapytanie o hasło Makaron (proszę zwrócić uwagę na parametr titles przekazywany metodą GET.):

https://pl.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exintro=&explaintext=&titles=Makaron

zwróci:

{"batchcomplete":"",
 "query":
    {"pages":
      {"136559":
        {"pageid":136559,
         "ns":0,
         "title":"Makaron",
         "extract":"Makaron \u2013 produkt \u017cywno\u015bciowy wytwarzany na bazie m\u0105ki, wody i niekiedy jaj (m\u00f3wimy wtedy o makaronie jajecznym) oraz innych sk\u0142adnik\u00f3w, o szerokiej gamie kszta\u0142t\u00f3w i zastosowa\u0144."
        }
      }
    }
}

W PHP obsługę komunikacji z Wikipedią można zaprogramować w poniższy sposób.

wp3.php
$c=curl_init('https://pl.wikipedia.org/w/api.php?format=json&action=query&prop=extracts&exintro=&explaintext=&titles=Makaron');
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
$dane=curl_exec($c);
curl_close($c);
$tablica=json_decode($dane,true);
 
foreach($tablica['query']['pages'] as $art) {
    echo $art['extract'];
}

Uwaga, jeżeli w haśle wystąpią znaki diakrytyczne należy użyć funkcji: urlencode() przed wysłaniem zapytania do Wikipedii.

Więcej informacji o przetwarzaniu JSON można znaleźć pod adresem: http://www.php.net/manual/en/ref.json.php

Informacje dodatkowe: Wyszukiwanie słów kluczowych w Wikipedii

Wyszukiwanie słów kluczowych może być zrealizowane np. tak:

https://pl.wikipedia.org/w/api.php?format=json&action=query&list=search&srlimit=10&srsearch=wilk

W/w przykład zwróci maksymalnie 10 rekordów (srlimit) danych odnośnie słowa kluczowego „wilk” (srsearch).

Informacje dodatkowe: Dostęp do danych w CouchDB

Korzystając z dowolnego widoku bazy CouchDB napisz w PHP program wyświetlający jako liste (wypunktowanie) kolejne identyfikatory dokumentów zgormadzonych w twojej bazie danych. Alternatywnie możesz skorzystać z wbudowanego widoku _all_dbs zwracającego nazwy baz danych np.: http://awing.kis.agh.edu.pl:5984/_all_dbs

  1. przeczytaj zasób,
  2. dokonaj konwersji JSON-tablica,
  3. wyświetl odpowiednie informacje iterując po tablicy.

Do przesyłania danych wykorzystaj biblioteke CURL (Uwaga: jeżeli dostęp do CouchDB jest chroniony, we wszystkich poniższych adresach HTTP trzeba dodać informacje o nazwie użytkownika i haśle tj.: http://... → http://login:haslo@… ):

curl.php
<?php
  $c=curl_init('http://awing.kis.agh.edu.pl:5984');
  /* zwroc dane jako wartosc */
  curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
  $dane=curl_exec($c);
  curl_close($c);
  echo $dane;
 
  $c=curl_init('http://awing.kis.agh.edu.pl:5984/moja1');
  curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($c, CURLOPT_PUT, 1);
  $dane=curl_exec($c);
  curl_close($c);
  echo $dane;
 
  $dok='{"tresc":"zawartosc dokumentu", "autor":"Wojnicki"}';
  $c=curl_init('http://awing.kis.agh.edu.pl:5984/moja1');
  curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($c, CURLOPT_POST, 1);
  curl_setopt($c, CURLOPT_HTTPHEADER,array('Content-type: application/json'));
  curl_setopt($c, CURLOPT_POSTFIELDS, $dok);
  $dane=curl_exec($c);
  curl_close($c);
  echo $dane;
 
  $c=curl_init('http://awing.kis.agh.edu.pl:5984/moja1/_all_docs');
  curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
  $dane=curl_exec($c);
  curl_close($c);
 
  /* przykład dekodowania JSON */
  $tablica=json_decode($dane,true);
  echo $tablica['total_rows'];  
?>

Uwaga: dane z postaci JSON zwracanej przez CouchDB mogą być konwertowane do tablic asocjacyjnych albo obiektów PHP. W powyższym przykładzie jest to tablica asocjacyjna. Podpowiedź: sprawdź w dokumentacji PHP jakie są dostępne funkcje do przetwarzania JSON: http://www.php.net/manual/en/ref.json.php

Do przesyłania danych można również wykorzystać fopen, jednak aktualnie funkcja ta jest niedostępna na serwerach: borg, charon i student.

curlcouch.php
$h=fopen("http://awing.ia.agh.edu.pl:5984/_all_dbs", "r");
if ($h) {
  while (($bufor=fgets($h))!=false) {
    echo $bufor;
  }
  fclose($h);
}

Informacje na temat używania innych metod HTTP (POST, PUT, DELETE) można znaleźć: http://www.php.net/manual/en/context.http.php

Informacje dodatkowe: Dostęp do bazy CouchDB

Przetestuj działanie skryptu couchshell.php:

couchshell.php
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml">
<header>
<title>CouchShell</title>
  <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<?php
function checked($source,$value) {
  if ($source === $value) echo 'checked="checked"';
}
 
$uri=$_POST['uri'];
if ($_POST['method'] === 'GET' ||
    $_POST['method'] === 'POST' ||
    $_POST['method'] === 'PUT' ||
    $_POST['method'] === 'DELETE' )
   $method=$_POST['method'];
 
$content_type='Content-type: '.$_POST['content'];
$post=$_POST['post'];
?>
</header>
<body>
<h1>Input</h1>
<p>
<form method="POST">
  URI:<br/>
  <textarea rows="4" cols="60" name="uri"><?php echo $uri;?></textarea>
  <br/>
  Method: <input type="radio" name="method" value="GET" <?php checked($method,'GET')?>/> GET
  <input type="radio" name="method" value="POST" <?php checked($method,'POST')?>/> POST
  <input type="radio" name="method" value="PUT" <?php checked($method,'PUT')?>/> PUT
  <input type="radio" name="method" value="DELETE" <?php checked($method,'DELETE')?>/> DELETE
  <br/>
  Content type: <input type="text" name="content" size="40" value="application/json"/>
  <br/>
  POST/PUT:<br/>
  <textarea rows="4" cols="60" name="post"><?php echo stripslashes($post);?></textarea>
  <br/>
  <input type="submit"/> 
  <input type="reset"/>
</form>
</p>
<h1>Output</h1>
<h2>JSON</h2>
<p>
<?php
 
if (isset($uri)){
 
  $c=curl_init($uri);
  curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($c,CURLOPT_CUSTOMREQUEST,$method);
  if ($method === 'POST' || $method === 'PUT') {
    curl_setopt($c, CURLOPT_POSTFIELDS, stripslashes($post));
    curl_setopt($c, CURLOPT_HTTPHEADER,array($content_type));
  }
  $data=curl_exec($c);
  curl_close($c);
  echo $data;
?>
<h2>Decoded JSON</h2>
<pre>
<?php
  print_r(json_decode($data,true));
?>
</pre>
<?php
}
?>
</p>
</body>
</html>

Ćwiczenie 3: Klasy i obiekty, generacja dokumentów PDF

Dostarczona jest struktura danych (np. pochodząca z odczytu z bazy danych) przechowująca informacje o flocie samochodów:

dane.php
// dane: marka samochodu, kolor, nr rej., przebieg, stan techniczny
$dane = array(
  array('VW Passat','srebrny', 'DW5789', 98000, 'dobry'),
  array('Syrena','żółty', 'WA4389', 60000, 'zły'),
  array('Ford Focus','czarny', 'KR1243', 21000, 'dobry'),
  array('Honda Civic','zielony', 'KR9834', 8000, 'dobry')
);

Celem ćwiczenia jest napisanie programu w PHP generującego dokument PDF, który pokaże powyższe dane w postaci tabelarycznej.

Do wykonania ćwiczenia użyj popularnej biblioteki TCPDF https://tcpdf.org/, tam też znajdziesz wiele przykładów jej użycia (Uwaga: dokumentacja klasy: https://tcpdf.org/docs/srcdoc/tc-lib-pdf/classes-Com-Tecnick-Pdf-Tcpdf/ alternatywnie można zaglądnąć do pliku tcpdf.php). Biblioteka jest w całości napisana w PHP. Aktualną wersję możesz pobrać z: https://github.com/tecnickcom/TCPDF/archive/6.3.5.zip Archiwum rozpakuj w katalogu, z Twoimi skryptami PHP (zwróć uwagę na odpowiednie prawa dostępu).

Przykład użycia biblioteki znajdziesz poniżej.

pdf1.php
require_once('TCPDF-6.3.5/tcpdf_import.php');
 
$pdf = new TCPDF('P', 'mm', 'A4', true, 'UTF-8', false); // $orientation='P', $unit='mm', $format='A4', $unicode=true, $encoding='UTF-8'
$pdf->SetFont('dejavusans', '', 10);                     // użyj czcionki DejavuSans, domyślne czcionki PDF nie uwzględniają polskich znaków
$pdf->setPrintHeader(false);                             // wyłącz nagłówki stron
$pdf->setPrintFooter(false);                             // wyłącz stopki stron
$pdf->setMargins(10,10,10,10);                           // ustaw marginesy
 
$pdf->addPage();                                         // dodaj stronę
$pdf->setXY(80,80);                                      // ustaw kursor na pozycji 80x80mm
$pdf->Write(0, 'Przykładowy napis na stronie.');         // dodaj napis
$pdf->Output()                                           // wygeneruj dokument PDF na standardowym wyjściu

Do sporządzenia tabelki możesz użyć metody writeHTML(), która generuje treść na podstawie składni HTML. Z w/w danych wygeneruj tabelkę w HTML, którą przypisz do zmiennej np. $html='<table><thead>…..</thead><tbody>…</tbody></head>' . Możesz użyć poniższego kodu. Więcej przykładów znajdziesz pod adresem: https://tcpdf.org/examples/example_006/

pdf2.php
require_once('TCPDF-6.3.5/tcpdf_import.php');
 
$pdf = new TCPDF('P', 'mm', 'A4', true, 'UTF-8', false);
$pdf->SetFont('dejavusans', '', 10); // domyślne czcionki PDF nie uwzględniają polskich znaków
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
$pdf->setMargins(10,10,10,10);
 
$html='<table>';
 
/* 
   Tutaj powinien być kod generujący zawartość zmiennej $html
   Warto użyć pętli foreach.
   ...
*/
 
$html.='</table>';
 
$pdf->addPage();
$pdf->writeHTML($html);
$pdf->Output();

Ćwiczenie 4: Klasy i obiekty

Napisz klasę Logowanie umożliwiającą obsługę danych do logowania tj. dodawanie par login-hasło, weryfikację hasła, usuwanie par login-hasło. W/w informacje powinny być przechowywane w bazie danych z wykorzystaniem PDO.

Klasa powinna udostępniać następujące metody:

  1. dodaj(login,hasło) – dodawanie pary login-hasło; uwaga hasła powinny być przechowywane w postaci zakodowanej z wykorzystaniem funkcji skrótu np. md5() tj.:
    $zakodowane=md5($haslo);
  2. sprawdz(login,hasło) – zwracającą prawdę, jeżeli login i hasło zgadzają się; uwaga: przy zakodowaniu z użyciem funkcji skrótu, porównać należy wartość funkcji skrótu na podanym haśle, z wartością przechowywaną w bazie danych,
  3. konstruktor – nawiązujący połączenie ze źródłem danych.

Do przetestowania działania klasy możesz użyć poniższego kodu.

ltest.php
<?php
  $logowanie = new Logowanie();
  $logowanie->dodaj('franek','rt56');
  if ($logowanie->sprawdz('franek','rt56'))
    echo 'Hasło prawidłowe';
  if (!$logowanie->sprawdz('franek','xxxx'))
    echo 'Hasło błędne';  
?>
TOP TIP
Zacznij od definicji klasy i wszystkich metod, potem zakoduj weryfikację użytkownika (używając stałych wartości dla nazwy i hasła), potem dodaj komunikację z bazą danych.

PostgreSQL

Dostęp do bazy danych PostgreSQL na charonie albo borgu można zrealizować w poniższy sposób.

pgsql1.php
<?php
$dbh = new PDO('pgsql:host=localhost;dbname=nazwa_bazy_danych', 'nazwa_uzytkownika_bazy', 'haslo_uzytkownika_bazy');
foreach($dbh->query('SELECT * FROM jakas_tabela;') as $row) {
  print_r($row);
}
$dbh = null;
?>

W przypadku korzystania z tego samego serwera dla skrytpow PHP i bazy danych, do PostgreSQL można podłączyć się nie używając hasła w następujący sposób.

pgsql2.php
<?php
$dbh = new PDO('pgsql:dbname=nazwa_uzytkownika_bazy');
foreach($dbh->query('SELECT * FROM jakas_tabela;') as $row) {
  print_r($row);
}
$dbh = null;
?>

MySQL

Dostęp do bazy danych MySQL na serwerze mysql.agh.edu.pl (hsło dostępowe mozna uzyskac przez panel AGH: https://panel.agh.edu.pl/ ) można zrealizować w poniższy sposób.

mysql1.php
<?php
$dbh = new PDO('mysql:host=mysql.agh.edu.pl;dbname=nazwa_bazy_danych','nazwa_uzytkownika_bazy',
    'haslo_uzytkownika_bazy');
foreach($dbh->query('SELECT * FROM jakas_tabela;') as $row) {
  print_r($row);
}
$dbh = null;
?>