Witaj, Gościu O nas | Kontakt | Mapa
Wortal Forum PHPEdia.pl Planeta Kubek IRC Przetestuj się!

cURL cz. 3: Zaawansowane funkcje

Funkcje zwrotne

Z pierwszej i drugiej części powinny być Ci znajome stałe CURLOPT_FILE i CURLOPT_INFILE, odpowiadające za zapis i odczyt przesyłanych plików. Czasami jednak operacje na strumieniach nie są tym, czego potrzebujemy. Z pomocą przychodzą funkcje zwrotne, które umożliwiają pełne dostosowanie obsługi danych do naszych potrzeb. Client URL Library udostępnia cztery rodzaje takich funkcji, które zajmują się operacjami takimi, jak odczyt danych, zapis danych, zapis nagłówków i odczytywanie hasła. Omówimy tylko dwie pierwsze, gdyż są one najbardziej pożyteczne. Będzie również słowo o zapisywaniu nagłówków.

Odczyt danych

Pierwszą z możliwości, które daje nam cURL jest odczyt danych. Ich źródło jest dowolne, lecz nasza funkcja zwrotna musi spełniać kilka warunków, aby wyniki jej działania były prawidłowe. Dokumentacja PHP zawiera niestety błędy, więc nie warto się na niej opierać.

Funkcja zwrotna odczytu otrzymuje 3 parametry: uchwyt do wykorzystywanego zasobu cURL, uchwyt do pliku przekazany opcji CURLOPT_INFILE oraz maksymalną długość zwróconego ciągu. Zwracamy łańcuch znaków, gdy odczytaliśmy dane. W przypadku niepowodzenia zwracamy wartość dowolnego innego typu. Pamiętajmy, że odczyt całych danych nie zawsze zawiera się w jednym wywołaniu funkcji. Oto i jej prototyp:

string odczyt(resource $ch, resource $fh, int $limit)

Najwygodniejszym sposobem na wykorzystanie wywołań zwrotnych jest utworzenie klasy, która zajmie się obsługą źródła. Żeby nie komplikować przykładu, odczytamy dane po prostu z pliku. Poniżej znajduje się kod klasy FileReadHandler, która odczytuje dane z pliku, którego nazwę podajemy w konstruktorze.

class FileReadHandler {
	public function __construct($filename) {
		$this->handle = fopen($filename, 'r');
	}
	
	public function read($ch, $fh, $limit) {
		if (feof($this->handle)) {
			return 0;
		}
		return fread($this->handle, $limit);
	}

	private $handle;
}

Obsługę błędów celowo ominąłem, żeby nie robić zbędnego zamieszania. Wykorzystanie klasy jest bardzo proste. Musimy przekazać tylko wartość typu callback opcji CURLOPT_READFUNCTION. Ilustruje to Listing 1.2:

$ch = curl_init('ftp://login:haslo@example.com/upload.txt');
$fh = new FileReadHandler('input.txt');
curl_setopt($ch, CURLOPT_READFUNCTION, array($fh, 'read'));
curl_setopt($ch, CURLOPT_UPLOAD, true);
curl_exec($ch);
curl_close($ch);

Alternatywnym rozwiązaniem będzie utworzenie funkcji, która wykorzysta uchwyt do pliku. Bezpieczniejszą metodą jest jednak utworzenie obiektu, który będzie posiadał swój własny uchwyt. Uchroni nas to przed niechcianymi modyfikacjami wskaźnika pozycji w pliku.

function read_callback($ch, $fh, $limit) {
	if (feof($fh)) {
	    return 0;
	}
	return fread($fh, $limit);
}

$ch = curl_init('ftp://login:haslo@example.com/upload.txt');
curl_setopt($ch, CURLOPT_READFUNCTION, 'read_callback');
curl_setopt($ch, CURLOPT_INFILE, fopen('input.txt', 'r'));
curl_setopt($ch, CURLOPT_UPLOAD, true);
curl_exec($ch);
curl_close($ch);

Zapis danych

W naszych skryptach spotykamy się częściej z zapisem niż odczytem, dlatego warto zapoznać się z funkcją obsługującą drugą z operacji. Spójrzmy na jej prototyp:

int zapis(resource $ch, string $data)

Pierwszy parametr jest zasobem cURL, a drugi zawiera dane, które mamy zapisać. Zwracana liczba całkowita jest liczbą bajtów, które zostały przez nas przetworzone. Jeżeli ta liczba różni się od liczby bajtów parametru $data, zwracany jest błąd. Tyle teorii, czas na kod klasy, której nazwy możecie się już domyśleć.

class FileWriteHandler {
	public function __construct($filename) {
		$this->file = $filename;
		$this->handle = fopen($filename, 'w');
	}
	
	public function write($ch, $data) {
		fwrite($this->handle, $data);
		return strlen($data);
	}

	private $handle;
}

Analogicznie do przykładu z odczytem, musimy przekazać wartość typu callback do opcji CURLOPT_WRITEFUNCTION.

$ch = curl_init('http://example.com');
$fh = new FileWriteHandler('result.txt');
curl_setopt($ch, CURLOPT_WRITEFUNCTION, array($fh, 'write'));
curl_setopt($ch, CURLOPT_NOBODY, false);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_exec($ch);

Zapis nagłówków

Zapis nagłówków działa na podobnej zasadzie jak zapis zwykłych danych, więc możemy do tego celu użyć spokojnie klasy FileWriteHandler. Istnieje jednak jedna subtelna różnica, która uprzyjemnia nieco pracę na nagłówkach. Jeżeli funkcja jest zarejestrowana jako służąca do zapisu danych, dostaje ona fragmenty danych, których znaczenie możemy uznać za niewiadome. Natomiast funkcja zapisująca nagłówki zawsze otrzymuje po jednej linii, co znaczy, że przy każdym wywołaniu otrzymujemy dokładnie jeden nagłówek. Przetwarzanie takich danych jest już bajecznie proste.

Informacje na podobny temat:
Wasze opinie
Wszystkie opinie użytkowników: (0)
Mentax.pl    NQ.pl- serwery z dodatkiem świętego spokoju...   
O nas | Kontakt | Mapa serwisu
Copyright (c) 2003-2024 php.pl    Wszystkie prawa zastrzeżone    Powered by eZ publish Content Management System eZ publish Content Management System