function foo () {
global $var;
// rest of code
}
W moich małych projektach PHP zwykle podążam drogą proceduralną. Generalnie mam zmienną, która zawiera konfigurację systemu, a kiedy chcę uzyskać dostęp do tej zmiennej w funkcji, robię to global $var;
.
Czy to zła praktyka?
php
global-variables
global
KRTac
źródło
źródło
Odpowiedzi:
Kiedy ludzie mówią o zmiennych globalnych w innych językach, oznacza to coś innego niż to, co robi się w PHP. Dzieje się tak, ponieważ zmienne nie są tak naprawdę globalne w PHP. Zakres typowego programu PHP to jedno żądanie HTTP. Zmienne sesji mają w rzeczywistości szerszy zakres niż zmienne „globalne” PHP, ponieważ zazwyczaj obejmują wiele żądań HTTP.
Często (zawsze?) Możesz wywołać funkcje składowe w metodach takich
preg_replace_callback()
jak ta:preg_replace_callback('!pattern!', array($obj, 'method'), $str);
Zobacz oddzwonienia, aby uzyskać więcej informacji.
Chodzi o to, że obiekty zostały przykręcone do PHP i pod pewnymi względami prowadzą do pewnej niezręczności.
Nie przejmuj się zbytnio stosowaniem standardów lub konstrukcji z różnych języków do PHP. Inną częstą pułapką jest próba przekształcenia PHP w czysty język OOP poprzez umieszczanie modeli obiektowych na wszystkim.
Jak wszystko inne, używaj zmiennych „globalnych”, kodu proceduralnego, określonego frameworka i OOP, ponieważ ma to sens, rozwiązuje problem, zmniejsza ilość kodu, który musisz napisać lub sprawia, że jest łatwiejszy do utrzymania i łatwiejszy do zrozumienia, nie dlatego, że myślisz powinieneś.
źródło
array ($obj, 'callbackMethod')
w wywołaniachpreg_replace_callback()
? (Wiem,Zmienne globalne, jeśli nie są używane ostrożnie, mogą utrudnić znalezienie problemów. Powiedzmy, że żądasz skryptu php i otrzymujesz ostrzeżenie, że próbujesz uzyskać dostęp do indeksu tablicy, która nie istnieje w jakiejś funkcji.
Jeśli tablica, do której próbujesz uzyskać dostęp, jest lokalna dla funkcji, sprawdzasz funkcję, aby zobaczyć, czy nie popełniłeś tam błędu. Może to być problem z danymi wejściowymi do funkcji, więc sprawdzasz miejsca, w których funkcja jest wywoływana.
Ale jeśli ta tablica jest globalna, musisz sprawdzić wszystkie miejsca, w których używasz tej zmiennej globalnej, i nie tylko, musisz dowiedzieć się, w jakiej kolejności uzyskuje się dostęp do tych odwołań do zmiennej globalnej.
Jeśli masz zmienną globalną w fragmencie kodu, trudno jest wyodrębnić funkcjonalność tego kodu. Dlaczego chcesz wyodrębnić funkcjonalność? Możesz więc go przetestować i użyć ponownie w innym miejscu. Jeśli masz kod, którego nie musisz testować i nie musisz go ponownie używać, użycie zmiennych globalnych jest w porządku.
źródło
zgadzam się z cletusem. dodałbym dwie rzeczy:
pozdrawiam, don
źródło
$DB = 'foo';
Kto może spierać się z doświadczeniem, stopniami wyższymi i inżynierią oprogramowania? Nie ja. Powiedziałbym tylko, że przy tworzeniu aplikacji PHP zorientowanych obiektowo na pojedynczą stronę, bawię się lepiej, gdy wiem, że mogę zbudować całość od zera, nie martwiąc się o kolizje przestrzeni nazw. Budowanie od podstaw to coś, czego wiele osób już nie robi. Mają pracę, termin, premię lub reputację, o którą muszą się troszczyć. Te typy mają tendencję do używania tak dużo gotowego kodu z wysokimi stawkami, że nie mogą w ogóle ryzykować używania zmiennych globalnych.
Używanie zmiennych globalnych może być złe, nawet jeśli są one używane tylko w globalnym obszarze programu, ale nie zapominajmy o tych, którzy po prostu chcą się bawić i sprawić, by coś działało .
Jeśli to oznacza użycie kilku zmiennych (<10) w globalnej przestrzeni nazw, które są używane tylko w globalnym obszarze programu, niech tak będzie. Tak, tak, MVC, wstrzykiwanie zależności, kod zewnętrzny, bla, bla, bla, bla. Ale jeśli zawarłeś 99,99% swojego kodu w przestrzeni nazw i klas, a kod zewnętrzny jest w piaskownicy, świat się nie skończy (powtarzam, świat się nie skończy), jeśli użyjesz zmiennej globalnej.
Generalnie nie powiedziałbym, że używanie zmiennych globalnych jest złą praktyką . Powiedziałbym, że używanie zmiennych globalnych (flag itp.) Poza globalnym obszarem programu jest problemem i (na dłuższą metę) nierozsądne, ponieważ można dość łatwo stracić orientację w ich stanach. Powiedziałbym również, że im więcej się nauczysz, tym mniej będziesz zależny od zmiennych globalnych, ponieważ doświadczysz „radości” ze śledzenia błędów związanych z ich użyciem. Już samo to zachęci Cię do znalezienia innego sposobu rozwiązania tego samego problemu. Przypadkowo popycha to ludzi PHP w kierunku uczenia się, jak używać przestrzeni nazw i klas (statyczne elementy członkowskie itp.).
Dziedzina informatyki jest rozległa. Jeśli odstraszamy wszystkich od zrobienia czegoś, ponieważ określamy to jako złe , wtedy tracą radość z prawdziwego zrozumienia argumentów stojących za etykietą.
Jeśli musisz, użyj zmiennych globalnych, ale zobacz, czy możesz rozwiązać problem bez nich. Kolizje, testowanie i debugowanie mają większe znaczenie, gdy dokładnie zrozumiesz prawdziwą naturę problemu, a nie tylko opis problemu.
źródło
Możemy zilustrować ten problem następującym pseudokodem
function foo() { global $bob; $bob->doSomething(); }
Twoje pierwsze pytanie jest oczywiste
Jesteś zmieszany? Dobry. Właśnie dowiedziałeś się, dlaczego globale są mylące i uważane za złą praktykę. Gdyby to był prawdziwy program, następną zabawą będzie wytropienie wszystkich jego wystąpień
$bob
i miejmy nadzieję, że znajdziesz właściwy (to się pogarsza, jeśli$bob
jest używany wszędzie). Gorzej, jeśli ktoś inny podejdzie i zdefiniuje$bob
(lub zapomnisz i ponownie użyjesz tej zmiennej), twój kod może się zepsuć (w powyższym przykładzie kodu, posiadanie niewłaściwego obiektu lub jego brak spowodowałby błąd krytyczny). Ponieważ praktycznie wszystkie programy PHP wykorzystują kod, tak jakinclude('file.php');
twoja praca, utrzymanie takiego kodu staje się wykładniczo trudniejsze, im więcej plików dodajesz.Jak unikamy Globals?
Najlepszym sposobem na uniknięcie zjawisk globalnych jest filozofia zwana Dependency Injection . W tym miejscu przekazujemy potrzebne nam narzędzia do funkcji lub klasy.
function foo(\Bar $bob) { $bob->doSomething(); }
Jest to znacznie łatwiejsze do zrozumienia i utrzymania. Nie ma zgadywania, gdzie
$bob
zostało ustawione, ponieważ dzwoniący jest odpowiedzialny za to, aby to wiedzieć (przekazuje nam to, co musimy wiedzieć). Co więcej, możemy użyć deklaracji typu, aby ograniczyć to, co jest przekazywane. Więc wiemy, że$bob
jest to instancjaBar
klasy lub instancja dzieckaBar
, co oznacza, że wiemy, że możemy użyć metod tej klasy. W połączeniu ze standardowym autoloaderem (dostępnym od PHP 5.3), możemy teraz sprawdzić, gdzieBar
zostało zdefiniowane. PHP 7.0 lub nowszy zawiera rozszerzone deklaracje typów, w których można również używać typów skalarnych (takich jakint
lubstring
).źródło
$bob = Bar::instance();
zawsze, kiedy tego potrzebujesz.Tak jak:
global $my_global; $my_global = 'Transport me between functions'; Equals $GLOBALS['my_global']
to zła praktyka (jak Wordpress
$pagenow
) ... hmmmRozważ to:
$my-global = 'Transport me between functions';
to błąd PHP Ale:
$GLOBALS['my-global'] = 'Transport me between functions';
NIE jest błędem, myślniki nie będą kolidować z "typowymi" zmiennymi zadeklarowanymi przez użytkownika, takimi jak
$pagenow
. A użycie WIELKICH LITER oznacza superglobalny w użyciu, łatwy do wykrycia w kodzie lub śledzenia za pomocą funkcji znajdowania w plikachUżywam łączników, jeśli jestem leniwy, aby zbudować klasy wszystkiego dla jednego rozwiązania, na przykład:
$GLOBALS['PREFIX-MY-GLOBAL'] = 'Transport me ... ';
Ale w przypadku szerszego zastosowania używam JEDNEGO globalnego jako tablicy:
$GLOBALS['PREFIX-MY-GLOBAL']['context-something'] = 'Transport me ... '; $GLOBALS['PREFIX-MY-GLOBAL']['context-something-else']['numbers'][] = 'Transport me ... ';
Ta ostatnia jest dla mnie dobrą praktyką na obiektywach typu „cola light” lub używaniu, zamiast zaśmiecania za każdym razem pojedynczymi klasami, aby „buforować” jakieś dane. Proszę o komentarz, jeśli się mylę lub brakuje mi czegoś głupiego ...
źródło