This post comes from the first version of this blog.
Please send me an email if anything needs an update. Thanks!
Języki skryptowe mają to do siebie, że dzięki wprowadzonej abstrakcji interpretera możliwa jest o wiele szersza ingerencja w sposób działania już uruchomionego skryptu. PHP jest jednym z takich języków, stąd czasem potrafi zadziwić swoimi możliwościami, dając nam narzędzia zarówno bardzo pomocne jak i proste w użyciu. W niniejszym wpisie chciałbym Wam przedstawić jedno takie narzędzie - funkcje o zmiennej liczbie parametrów.
Wstęp. Jeśli mieliście kiedykolwiek do czynienia z językiem C lub C++ pewnie zastanawialiście się jak działa np. funkcja printf(). Jeśli nie, to musicie jedynie wiedzieć, że funkcja ta po prostu wypisywała na standardowe wyjście żądany ciąg znaków. Nie ma w tym żadnej magii, poza tym, że mogliśmy podać dowolną ilość parametrów dowolnych typów [oczywiście musieliśmy też uwzględnić je w łańcuchu formatującym], a funkcja cały czas działała poprawnie.
Każdemu programiście, który napisał w życiu co najmniej jedną funkcję a nie słyszał o mechanizmach variadic functions [funkcje wariadyczne? chyba lepiej brzmi po angielsku ;]] wyda się to zapewne niemożliwe. Zresztą, zobaczcie sami:
|
|
Pamiętam, jak na samym początku przygody z programowaniem próbowałem “imitować” jej działanie poprzez przeciążanie wielu funkcji o tej samej nazwie, różniących się jedynie ilością parametrów. Powstawały wtedy “potworki” w stylu:
|
|
Oczywiście te funkcje miały jakieś zastosowanie, więc nie myślcie, że wyważałem otwarte drzwi. Po prostu na początku nie miałem świadomości istnienia pewnych mechanizmów i sztuczek, stąd trzeba było sobie radzić z tym, co się umiało. Ze względu na to, że rzadko podawałem więcej niż 5 argumentów działało to całkiem nieźle. ;] Wracając do tematu - pewnie domyślacie się teraz, że pokażę Wam jak osiągnąć tego typu efekt w języku PHP. Nie wiem jakim cudem, ale zgadliście. ;]
func_*
Aby kontrolować liczbę i wartości podanych argumentów potrzebne będą odpowiednie narzędzia. Programiści biblioteki standardowej PHP oddali do naszego użytku aż trzy specjalnie przygotowane funkcje, są to:- func_num_args() - zwraca liczbę podanych argumentów
- func_get_arg($id) - zwraca wartość argumentu o numerze porządkowym $id
- func_get_args() - zwraca tablicę argumentów i ich wartości
|
|
Wynik wykonania powyższego skryptu jest następujący:
Hello, my name is Foo.
You were mean and passed no arguments.
Hello, my name is Foo again.
You were quite generous and passed 2 arguments.
These arguments were:
print_r(), for sure:
Array
(
[0] => 12
[1] => 24
)
foreach():
Argument 0 has value: "12"
Argument 1 has value: "24"
Hello, my name is Foo again.
You were quite generous and passed 5 arguments.
These arguments were:
print_r(), for sure:
Array
(
[0] => string
[1] => 4.56
[2] => 52
[3] => 1
[4] =>
)
foreach():
Argument 0 has value: "string"
Argument 1 has value: "4.56"
Argument 2 has value: "52"
Argument 3 has value: "1"
Argument 4 has value: ""
Zwróćcie uwagę na jedną rzecz - w nagłówku funkcji foo() nie został podany ani jeden argument formalny! Za pomocą powyższych trzech funkcji jesteśmy więc w stanie dowolnie operować na tym, co zostało faktycznie przekazane, widać to dokładnie w sposobie wywołania:
|
|
Zarówno “puste” wywołanie, jak i te bardziej “hojne” zostały poprawnie obsłużone - w naszych skryptach możemy oczywiście zareagować w całkowicie dowolny sposób. Jednym ze sposobów jakie przyszły mi do głowy podczas tego wpisu może być np. stworzenie funkcji, która będzie w różny sposób reagowała na ilość podanych parametrów:
|
|
Ogranicza nas jedynie wyobraźnia. ;]
Zalety i wady.
Zaletą takiego rozwiązania jest oczywiście możliwość większej kontroli nad kodem. W pewnych sytuacjach możemy chcieć np. "skompresować" kilka funkcji w jednej bazując na ilości / typach podanych parametrów - mając wiedzę zdobytą w tym wpisie możemy zrobić to w miarę prosto i bezboleśnie.Największą wadą zastosowania tych funkcji będzie ograniczenie czytelności kodu. Mówiąc o czytelności mam w tym wypadku nie samą nieznajomość działania, ale to, że “nie widać” [wymagane jest napisanie oddzielnej dokumentacji jakie wywołania odpowiadają poszczególnym akcjom] jakie parametry są wymagane do jej wykonania. Można to częściowo ominąć nazywając część parametrów i podając w nagłówku ich wartości domyślne:
|
|
Oczywiście wartości domyślne są opcjonalne, ale jeśli ich nie podamy to “zepsujemy” puste wywołanie funkcji. W każdym razie umieszczając pewne parametry jawnie w deklaracji możemy się do nich odwołać na dwa sposoby.
W mojej opinii o wiele mniejszym, ale jednak problemem może być zaprzestanie wspierania tych funkcji przez przyszłe wersje PHP. Język ten od początku rozwija się w bardzo burzliwy sposób, to dodając, to usuwając pewne funkcjonalności, stąd zawsze trzeba mieć na uwadze fakt, że kiedyś komuś może się przestać podobać takie rozwiązanie i po prostu “wyrzuci” je z kodu. Jest to bardzo mało prawdopodobne, ale w programowaniu jest jedna prosta zasada: “nigdy nie mów nigdy”. ;]