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:

$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?

$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:

$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:

$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.