This post comes from the first version of this blog.
Please send me an email if anything needs an update. Thanks!

Pisząc framework będący tematem pracy inżynierskiej w pewnym momencie musiałem zmierzyć się z problemem wyświetlania i formatowania przyjaznych komunikatów o błędach wykonania. Przyjaznych nie dla użytkownika, lecz dla programisty tworzącego stronę internetową, co trochę utrudniło problem, ponieważ wiadomości w stylu “strona jest chwilowo niedostępna” nie są zbyt informatywne. W dzisiejszym wpisie chciałbym się z Wami podzielić sposobem, w jaki udało mi się ten problem rozwiązać.

Wstęp: Przekazywanie danych i formatowanie komunikatów.

Praktycznie każdy programista na pewnym [raczej początkowym] etapie kariery zetknął się z funkcją printf() i jej wariacjami. Jest to jedna z funkcji pochodzących z biblioteki standardowej języka C, bardzo przydatna w przypadku, kiedy chcemy wypisać na ekran ciąg znaków zawierający zmienne fragmenty. Ze względu na to, że biblioteka standardowa PHP zawiera w sobie bardzo dużo funkcji pochodzących z C [interpreter PHP jest napisany w C], jest też w niej obecna funkcja printf().

Pomimo swojej prostoty i użyteczności niestety ma swoje ograniczenia. Jednym z problemów, na jakie natrafiłem podczas rozwiązywania kwestii wyświetlania ładnie sformatowanych komunikatów było to, że printf() przyjmuje z góry określoną liczbę parametrów. Jako “z góry określoną” rozumiem taką, która została wpisana podczas programowania do kodu, czyli “zakodowana na sztywno”.

Ze względu na to, że potrzebowałem dynamicznej zmienności liczby tych parametrów, miałem do wyboru jedynie samodzielnie przetwarzać wprowadzony string formatujący i wstawiać do niego kolejno przekazane parametry. Miałem do wyboru, dopóki nie zacząłem wertować manuala PHP w poszukiwaniu rozwiązania.

PHP: Funkcja vsprintf() przyjmująca tablicę jako argument.

Po przejrzeniu dokumentacji PHP dla funkcji printf() znalazłem w akapicie "See also" kilka pozycji, które niejako z przyzwyczajenia otworzyłem rolką myszy w kolejnych zakładkach. Jedną z "powiązanych" funkcji była funkcja sprintf() - zmieniło to nieco mój pogląd na sprawę, ponieważ zauważyłem, że zwrócenie stringa ze sformatowanym komunikatem będzie lepszym rozwiązaniem, pozwalającym przenieść decyzję o wyświetleniu w nieco lepsze miejsce. Spojrzałem też ponownie w akapit "See also". Moim oczom ukazała się podobnie brzmiąca nazwa... vsprintf(). Szybko otworzyłem dokumentację dla także i tej funkcji... i się ucieszyłem. ;]

Można powiedzieć wiele złych słów na temat PHP, jego własności, braków i wydajności, ale nie można mu odmówić jednego - potrafi nie raz zaskoczyć programistę. Jak się okazuje nie tylko negatywnie, ale także bardzo pozytywnie. W tym przypadku okazuje się, że ktoś zwyczajnie “pomyślał” i skorzystał z dynamiki języka, umieszczając odpowiedni dla niego wariant funkcji sprintf(). Funkcja vsprintf(), w odróżnieniu od jej odpowiednika bez “v” w nazwie przyjmuje zamiast listy parametrów tablicę, pozwalającą na umieszczenie zmiennej liczby parametrów. Jej sygnatura wygląda następująco:

1
string vsprintf(string $format, array $args)

W momencie, kiedy chciałem uzyskać string będący sformatowanym komunikatem o błędzie, wystarczyło wykonać jedną prostą linijkę, np.:

1
Log::Message('Failed to execute route %s using %s.', array($routeIdentifier, __METHOD__));

Parametry wywołania były przekazywane do funkcji vsprintf(), przy czym do każdego elementu tablicy dopisywałem jeszcze kawałek HTMLa, aby wyróżnić nieco najbardziej istotne elementy. Powodowało to w tym przypadku dopisanie komunikatu do listy, która mogła potem zostać wyświetlona w przypadku błędu. I po wszystkim! Mam nadzieję, że poznana dzisiaj funkcja przyniesie Wam wymierne korzyści, ponieważ naprawdę upraszcza dosyć spory problem formatowania stringów. Jeśli już ją znacie, podzielcie się w komentarzach ciekawymi zastosowaniami, jakie mieliście okazję implementować. Z góry dziękuję!