Podobno PHP5 jest językiem obiektowym, niektórzy twierdzą nawet, że językiem czwartej generacji. Ja bym go nazwał językiem obiektowalnym, bo zaiste, można w nim programować obiektowo, jednak sam język ani do tego nie zachęca, ani procesu nie ułatwia. Znakomita większość funkcji bibliotecznych obiektowości zwyczajnie nie obsługuje. Ciekawsze jednak są wyjątki, które w PHP są… niemal bezużyteczne.

Autorzy języka uznali, że najważniejsza jest zgodność wstecz za wszelką cenę. Zamiast jednak przygotować moduł, który dostarczałby API zgodnego ze starszymi wydaniami i zmodernizować rdzeń funkcjonalności bibliotecznej, postanowili ciągnąć za sobą brzemię średniowiecznych początków języka. Złośliwi mówią, że wystarczy zamienić część znaków dolara na małpki i otrzymamy poprawny kod Perla, a usuwając dolary w liniach deklaracji otrzymamy zgodność ze skryptami powłoki. Trudno się dziwić, bo szerokie możliwości języka to głównie posklejane kawałki bibliotek standardowych Perla i C, pomieszane z możliwościami powłoki. Faktycznie, jeśliby dodać do siebie procentowy udział języków pomnożony przez ich generację, to PHP okazuje się stać na czele i już tylko krok dzieli go od interpretacji języka naturalnego.

Nie o tym jednak chciałem pisać. Jedną z konsekwencji zachowania zgodności jest wyjątkowość języka, przejawiające się w braku wbudowanych wyjątków. Nie mam tu na myśli klasy Exception, mówię o tym, że żadna z funkcji bibliotecznych wyjątkami nie rzuca. Zwracają magiczne wartości, ustawiają liczniki błędów, ale wyjątków unikają jak ognia. Dlaczego? Może dlatego, że przeciętny konsument API o obiektowości, wyjątkach i wzorcach projektowych ma takie samo pojęcia, jak ja o ornitologii. Dlatego właśnie uważam, że wyjątki w PHP są niemal bezużyteczne.

$f = foo();
if (foo_error())
	return false;
if (!foo_write($f, 'bar'))
	return false;
if (!foo_write($f, 'baz'))
	return false;
foo_flush($f);
if (foo_error())
	return false;
foo_close($f);
if (foo_error())
	return false;

Czy tak powinien wyglądać kod? A może tak:

$result = true;
try
{
	$f = foo();
	$f->write('bar');
	$f->write('baz');
	$f->flush();
}
catch (FooException $e)
{
	$result = false;
}
finally
{
	if ($f)
		$f->close();
}
return $result;

Żeby móc osiągnąć czytelność drugiej wersji kodu, programista musi poświęcić kilka godzin na napisanie wrapperów dla większości bibliotecznych wywołań. W przeciwnym wypadku używanie wyjątków jest bezcelowe, bo i tak na każdym kroku trzeba kontrolować zwracane wartości. Czy jest tu zaszyta jakaś głębsza logika, czy słusznie wydaje mi się, że PHP5 wygląda na zaprojektowany na kolanie?