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

Podczas pisania kodu czasami natrafiamy na sytuację, gdzie potrzebne informacje znajdują się w mało wygodnym dla nas kontenerze. O ile tablice w języku PHP są jednym z najprostszych w wykorzystaniu kontenerów, jakie do tej pory widziałem, ciągłe wykorzystywanie konstrukcji $arr[‘sth’] potrafi zmęczyć nawet bardzo wytrwałego programistę. W dzisiejszym wpisie chciałbym przedstawić dwie techniki pozwalające na uniknięcie tego typu utrudnień.

Problem: $arr['index0'], $arr['index1']...

Problem polega na tym, że podczas odwoływania się do informacji zawartych w tablicy... musimy odwołać się do tablicy:
1
2
3
$arr = array('foo' => 1, 'bar' => 'other', 'baz' => 'gif');

echo 'Bar index value: '.$arr['bar'];

Proste, jednak nie zawsze wygodne rozwiązanie. O ile łatwiej byłoby po prostu odwołać się do odpowiednio nazwanej zmiennej?

1
2
3
4
5
6
$arr = array('foo' => 1, 'bar' => 'other', 'baz' => 'gif');

$foo = $arr['foo'];
$bar = $arr['bar'];
$baz = $arr['baz'];
echo 'Bar index value: '.$bar;

Przykład ten pokazuje jednak jasno, że w przypadku, kiedy zechcemy skorzystać z kilku lub więcej zmiennych, ustawianie wszystkiego na pewno będzie bardzo uciążliwe. Czy nie można zrobić tego… łatwiej?

Rozwiązanie: Variable variables / extract().

Pierwszym rozwiązaniem, które zapewne nasunie się Czytelnikom niniejszego blogu, jest wykorzystanie techniki variable variables. W najprostszej postaci polega ono na tym, że na początku funkcji / skryptu umieścimy pętlę, która utworzy nam wszystkie potrzebne zmienne:
1
2
3
4
5
6
7
$arr = array('foo' => 1, 'bar' => 'other', 'baz' => 'gif');

foreach($arr as $key => $val)
    {
    $$key = $val;
    }
echo 'Bar index value: '.$bar;

Wystarczy jeden “nadmiarowy” znak dolara w odpowiednim miejscu i życie staje się prostsze. ;]

Jest jednak jeszcze ciekawsze rozwiązanie, polegające na wykorzystaniu wbudowanej funkcji extract(). Funkcja ta, zgodnie z opisem zawartym w manualu “importuje wartości zawarte w tablicy pod zmienne o nazwach odpowiadających ich indeksom”. Brzmi mało ciekawie - można było wymyślić nieco lepszy opis, ale w końcu jesteśmy programistami, nikt nie mówił, że będzie łatwo. ;] W każdym razie, działanie tej funkcji prezentuje poniższy listing:

1
2
3
4
$arr = array('foo' => 1, 'bar' => 'other', 'baz' => 'gif');

extract($arr);
echo 'Bar index value: '.$bar;

Widać jak na dłoni, że zastąpiła nam ona całą pętlę foreach, a oprócz tego uprościło ten fragment kodu.

Ważne: Zawsze pamiętaj o konsekwencjach.

Ważne jest, aby nie używać ani podanej pętli, ani tej funkcji "na ślepo". W obu przypadkach nie umieściliśmy żadnych zabezpieczeń przed nadpisaniem istniejących zmiennych, co może mieć opłakane skutki, szczególnie, jeśli np. w tablicy znajdzie się indeks "this", a wywołamy kod w kontekście metody klasy.

Jeśli chodzi o pętlę foreach, sprawdzenie istnienia zmiennej sprawdzi prosty if(true == isset($key)), jednakże kopiowanie całego fragmentu z tym i dodatkowymi sprawdzeniami w pewnym momencie przestanie być wygodne. Tutaj po raz kolejny z pomocą przychodzi funkcja extract(), która przyjmuje dwa dodatkowe parametry: flagi dotyczące “ekstrakcji” zmiennych oraz prefiks dodawany do eksportowanych zmiennych. Wykorzystanie flagi EXTR_SKIP pozwoli na “ominięcie” kolidujących identyfikatorów, dzięki czemu ominiemy też problem nadpisywania.

Zachęcam do zapoznania się z resztą opcji, a szczególnie z wprowadzoną już w wersji 4.3.0 EXTR_REFS, dzięki której wyeksportowane z tablicy wartości bez dodatkowego wysiłku mogą pozostać “zsynchronizowane” ze zmianami wprowadzonymi do osobnych zmiennych.