Dlaczego require_once jest tak zły w użyciu?

143

Wszystko, co czytałem o lepszych praktykach kodowania PHP, ciągle mówi, że nie używaj require_once powodu szybkości.

Dlaczego to?

Jaki jest właściwy / lepszy sposób zrobienia tego samego, co require_once? Jeśli ma to znaczenie, używam PHP 5.

Uberfuzzy
źródło
9
To pytanie jest teraz dość stare, a odpowiedzi są już wątpliwie istotne. Byłoby wspaniale zobaczyć zaktualizowany zestaw odpowiedzi od uczestników :)
Purefan

Odpowiedzi:

108

require_oncei include_onceoba wymagają, aby system prowadził dziennik tego, co już zostało uwzględnione / wymagane. Każde *_oncepołączenie oznacza sprawdzenie tego dziennika. Więc na pewno niektóre dodatkowa praca wykonywana tam, ale na tyle na niekorzyść szybkości całej aplikacji?

... Naprawdę w to wątpię ... Nie, chyba że jesteś na naprawdę starym sprzęcie lub często to robisz .

Jeśli robi tysiące *_once, można zrobić samemu w jaśniejszy sposób. W przypadku prostych aplikacji, po prostu upewniając się wcześniej tylko raz włączone to powinno wystarczyć, ale jeśli nadal się błędy przedefiniować, można było coś takiego:

if (!defined('MyIncludeName')) {
    require('MyIncludeName');
    define('MyIncludeName', 1);
}

Osobiście będę trzymał się *_oncestwierdzeń, ale na głupim benchmarku z milionem przebiegów widać różnicę między nimi:

                php                  hhvm
if defined      0.18587779998779     0.046600103378296
require_once    1.2219581604004      3.2908599376678

10-100 × wolniej z require_oncei ciekawe, że require_oncewydaje się wolniej hhvm. Ponownie, ma to znaczenie tylko dla twojego kodu, jeśli wykonujesz *_oncetysiące razy.


<?php // test.php

$LIMIT = 1000000;

$start = microtime(true);

for ($i=0; $i<$LIMIT; $i++)
    if (!defined('include.php')) {
        require('include.php');
        define('include.php', 1);
    }

$mid = microtime(true);

for ($i=0; $i<$LIMIT; $i++)
    require_once('include.php');

$end = microtime(true);

printf("if defined\t%s\nrequire_once\t%s\n", $mid-$start, $end-$mid);

<?php // include.php

// do nothing.
Oli
źródło
29
Wątpię, czy twoja metoda define () jest szybsza niż wbudowana tabela odnośników, ale zgadzam się z twoim ogólnym punktem - na pewno nie jest to problem ?!
Bobby Jack
1
Jestem całkiem pewien, że masz rację Bobby, ale nie opowiadam się za definiowaniem ponad _ raz. To tylko opcja. Czas potrzebny na zinterpretowanie kodu może nawet spowodować, że będzie on nieco wolniejszy, ale to powiedziawszy, nie wiem, jak dokładna jest metoda wewnętrzna. Może to wymagać dodatkowej pracy, aby uniknąć duplikatów.
Oli
8
Innym minusem jest to, że APC nie buforuje połączeń include_once i require_once w IIRC
dcousineau
3
Właśnie wykonałem bardzo podstawowy test obu metod - wykonałem 1 000 000 iteracji, w tym plik, który po prostu definiował stałą „testinclude” na true. W pierwszym teście użyłem require_once, drugiego użyłem if (! Define ('testinclude')) i wyniki były interesujące: Require: 0.81639003753662 Not Defined: 0.17906713485718 Defined jest o 0,63732290267944 mikrosekund szybciej.
Travis Weston
Sprawa z definicją będzie szybsza, ponieważ nie wykonujesz żadnych dodatkowych kontroli, takich jak użycie realpath. To nie jest porównywanie dwóch rzeczy, które są naprawdę takie same.
jgmjgm
150

Wątek ten sprawia, że ​​się wzdrygam, ponieważ zostało już „opublikowane rozwiązanie” i jest ono pod każdym względem błędne. Wymieńmy:

  1. W PHP definicje są naprawdę drogie. Możesz to sprawdzić lub przetestować samodzielnie, ale jedynym skutecznym sposobem zdefiniowania stałej globalnej w PHP jest użycie rozszerzenia. (Stałe klasowe są w rzeczywistości całkiem przyzwoite, jeśli chodzi o wydajność, ale jest to kwestia dyskusyjna, ponieważ 2)

  2. Jeśli używasz require_once()odpowiednio, to znaczy włączasz klasy, nie potrzebujesz nawet definicji; po prostu sprawdź, czy class_exists('Classname'). Jeśli plik, który dołączasz, zawiera kod, tj. Używasz go w sposób proceduralny, nie ma absolutnie żadnego powodu, który require_once()powinien być dla Ciebie potrzebny; za każdym razem, gdy dołączasz plik, zakładasz, że wywołuje podprogram.

Tak więc przez jakiś czas wiele osób używało tej class_exists()metody do swoich inkluzji. Nie podoba mi się to, ponieważ jest zepsuty, ale mieli dobry powód, aby: require_once()był dość nieefektywny przed niektórymi nowszymi wersjami PHP. Ale to zostało naprawione i twierdzę, że dodatkowy kod bajtowy, który musiałbyś skompilować dla warunku, i dodatkowe wywołanie metody, zdecydowanie przeważałyby nad jakimkolwiek wewnętrznym sprawdzaniem z tablicą haszującą.

A teraz przyznaję: to jest trudne do przetestowania, ponieważ zajmuje tak mało czasu wykonania.

Oto pytanie, o którym powinieneś pomyśleć: obejmuje z reguły są drogie w PHP, ponieważ za każdym razem, gdy interpreter trafia w jeden, musi przełączyć się z powrotem w tryb parsowania, wygenerować kody operacyjne, a następnie skoczyć z powrotem. Jeśli masz ponad 100 elementów, z pewnością będzie to miało wpływ na wydajność. Powodem, dla którego używanie lub nieużywanie require_once jest tak ważne pytanie, jest to, że utrudnia życie buforom opcode. Wyjaśnienie tego można znaleźć tutaj, ale to, co sprowadza się do tego, że:

  • Jeśli w czasie parsowania wiesz dokładnie, jakich plików nagłówkowych będziesz potrzebować przez cały czas trwania żądania, require()te na samym początku i pamięć podręczna kodu operacji zajmie się wszystkim innym za Ciebie.

  • Jeśli nie korzystasz z pamięci podręcznej kodu operacyjnego, jesteś w ciężkim miejscu. Umieszczanie wszystkich dołączeń w jednym pliku (nie rób tego podczas programowania, tylko w środowisku produkcyjnym) może z pewnością pomóc przeanalizować czas, ale jest to uciążliwe, a ponadto musisz dokładnie wiedzieć, co będziesz uwzględniać podczas żądanie.

  • Automatyczne ładowanie jest bardzo wygodne, ale powolne, ponieważ logika automatycznego ładowania musi być uruchamiana za każdym razem, gdy jest wykonywane dołączanie. W praktyce odkryłem, że automatyczne ładowanie kilku wyspecjalizowanych plików dla jednego żądania nie powoduje zbyt dużego problemu, ale nie powinno się automatycznie ładować wszystkich potrzebnych plików.

  • Jeśli masz może 10 włączeń (to bardzo koniec kalkulacji obwiedni), całe to wankowanie nie jest tego warte: po prostu zoptymalizuj zapytania do bazy danych lub coś takiego.

Edward Z. Yang
źródło
14
To ma 4 lata i przeważnie już nie ma zastosowania define(), require_once()a defined()każde z nich zajmuje około 1-2 mikrosekund na moim komputerze.
Daniel Beardsley
72
Ale to 2 mikrosekundy szybciej użytkownik będzie miał stronę. Ponad rok odsłon, co może zaoszczędzić użytkownikowi całe 3 sekundy! Mogli w tym czasie obejrzeć jedną dziesiątą reklamy! Pomyśl o użytkowniku. Nie trać mikrosekund.
Andrew Ensley
15
Aby wszyscy byli świadomi sarkazmu, mikrosekunda to 1/1000000 sekundy.
Andy Chase
1
@AndrewEnsley Po prostu mylisz się ze swoim sarkazmem. Nie masz pojęcia, że ​​PHP działa również na mikroprocesorach, 1 mikrosekunda na twoim komputerze to kilka milisekund na mikroprocesorze. A co z posiadaniem 20 plików dołączanych, czyli większego projektu? Wprowadzono 20-krotne kilkumilisekundowe opóźnienie, więc już osiągamy punkt, który jest zauważalny dla człowieka. Jeśli ten skrypt jest wywoływany często, spowoduje to problemy z wydajnością w systemie. Optymalizacja to nie żart, a cały świat nie kręci się wokół twojego komputera. W użyciu jest dziesięć tysięcy procesorów.
John
2
@Jan. To był żart zrobiony w dobrym nastroju. Bez złośliwości. Jeśli warto zoptymalizować dołączone elementy, śmiało.
Andrew Ensley,
66

Zaciekawiło mnie to i sprawdziłem link Adama Backstroma do Tech Your Universe . W tym artykule opisano jeden z powodów, dla których należy użyć wymagania zamiast require_once. Jednak ich twierdzenia nie potwierdziły mojej analizy. Chciałbym zobaczyć, gdzie mogłem źle przeanalizować rozwiązanie. Do porównań użyłem PHP 5.2.0.

Zacząłem od stworzenia 100 plików nagłówkowych, które wykorzystywały require_once do dołączenia innego pliku nagłówkowego. Każdy z tych plików wyglądał mniej więcej tak:

<?php
    // /home/fbarnes/phpperf/hdr0.php
    require_once "../phpperf/common_hdr.php";

?>

Stworzyłem je za pomocą szybkiego hacka Bash:

for i in /home/fbarnes/phpperf/hdr{00..99}.php; do
    echo "<?php
    // $i" > $i
    cat helper.php >> $i;
done

W ten sposób mogłem łatwo przełączać się między użyciem require_once i wymaganiem przy dołączaniu plików nagłówkowych. Następnie utworzyłem plik app.php, aby załadować sto plików. Wyglądało to tak:

<?php
    // Load all of the php hdrs that were created previously
    for($i=0; $i < 100; $i++)
    {
        require_once "/home/fbarnes/phpperf/hdr$i.php";
    }

    // Read the /proc file system to get some simple stats
    $pid = getmypid();
    $fp = fopen("/proc/$pid/stat", "r");
    $line = fread($fp, 2048);
    $array = split(" ", $line);

    // Write out the statistics; on RedHat 4.5 with kernel 2.6.9
    // 14 is user jiffies; 15 is system jiffies
    $cntr = 0;
    foreach($array as $elem)
    {
        $cntr++;
        echo "stat[$cntr]: $elem\n";
    }
    fclose($fp);
?>

Kontrastowałem nagłówki require_once z nagłówkami wymagającymi, które używały pliku nagłówkowego wyglądającego tak:

<?php
    // /home/fbarnes/phpperf/h/hdr0.php
    if(!defined('CommonHdr'))
    {
        require "../phpperf/common_hdr.php";
        define('CommonHdr', 1);
    }
?>

Nie znalazłem dużej różnicy podczas uruchamiania tego z wymaganiem a require_once. W rzeczywistości moje wstępne testy wydawały się sugerować, że require_once była nieco szybsza, ale niekoniecznie w to wierzę. Powtórzyłem eksperyment z 10000 plików wejściowych. Tutaj widziałem stałą różnicę. Przeprowadziłem test wiele razy, wyniki są bliskie, ale użycie require_once używa średnio 30,8 jiffies użytkownika i 72,6 systemowych jiffies; używanie require używa średnio 39,4 jiffies użytkownika i 72,0 systemowych jiffies. Dlatego wydaje się, że obciążenie jest nieco mniejsze przy użyciu require_once. Jednak zegar ścienny nieco się wydłuża. 10 000 połączeń require_once zajmuje średnio 10,15 sekundy, a 10 000 połączeń wymaga średnio 9,84 sekundy.

Następnym krokiem jest przyjrzenie się tym różnicom. Użyłem strace do analizy wywołań systemowych, które są wykonywane.

Przed otwarciem pliku z require_once wykonywane są następujące wywołania systemowe:

time(NULL)                              = 1223772434
lstat64("/home", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes/phpperf", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes/phpperf/h", {st_mode=S_IFDIR|0755, st_size=270336, ...}) = 0
lstat64("/home/fbarnes/phpperf/h/hdr0.php", {st_mode=S_IFREG|0644, st_size=88, ...}) = 0
time(NULL)                              = 1223772434
open("/home/fbarnes/phpperf/h/hdr0.php", O_RDONLY) = 3

Kontrastuje to z wymaganiami:

time(NULL)                              = 1223772905
lstat64("/home", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes/phpperf", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes/phpperf/h", {st_mode=S_IFDIR|0755, st_size=270336, ...}) = 0
lstat64("/home/fbarnes/phpperf/h/hdr0.php", {st_mode=S_IFREG|0644, st_size=146, ...}) = 0
time(NULL)                              = 1223772905
open("/home/fbarnes/phpperf/h/hdr0.php", O_RDONLY) = 3

Tech Your Universe sugeruje, że require_once powinno wykonywać więcej wywołań lstat64. Jednak oba wykonują taką samą liczbę wywołań lstat64. Być może różnica polega na tym, że nie używam APC do optymalizacji powyższego kodu. Jednak następnie porównałem wyniki strace dla całych biegów:

[fbarnes@myhost phpperf]$ wc -l strace_1000r.out strace_1000ro.out
  190709 strace_1000r.out
  210707 strace_1000ro.out
  401416 total

W efekcie w przypadku korzystania z require_once istnieje około dwóch dodatkowych wywołań systemowych na plik nagłówkowy. Jedna różnica polega na tym, że require_once ma dodatkowe wywołanie funkcji time ():

[fbarnes@myhost phpperf]$ grep -c time strace_1000r.out strace_1000ro.out
strace_1000r.out:20009
strace_1000ro.out:30008

Drugie wywołanie systemowe to getcwd ():

[fbarnes@myhost phpperf]$ grep -c getcwd strace_1000r.out strace_1000ro.out
strace_1000r.out:5
strace_1000ro.out:10004

Nazywa się to, ponieważ zdecydowałem się na ścieżkę względną, do której odwołują się pliki hdrXXX. Jeśli uczynię to odniesieniem bezwzględnym, jedyną różnicą jest wywołanie dodatkowego czasu (NULL) wykonane w kodzie:

[fbarnes@myhost phpperf]$ wc -l strace_1000r.out strace_1000ro.out
  190705 strace_1000r.out
  200705 strace_1000ro.out
  391410 total
[fbarnes@myhost phpperf]$ grep -c time strace_1000r.out strace_1000ro.out
strace_1000r.out:20008
strace_1000ro.out:30008

Wydaje się to sugerować, że można zmniejszyć liczbę wywołań systemowych, używając ścieżek bezwzględnych zamiast ścieżek względnych. Jedyną różnicą poza tym jest wywołania time (NULL), które wydają się być używane do instrumentowania kodu w celu porównania tego, co jest szybsze.

Inną uwagą jest to, że pakiet optymalizacyjny APC ma opcję o nazwie „apc.include_once_override”, która twierdzi, że zmniejsza liczbę wywołań systemowych wykonywanych przez wywołania require_once i include_once (zobacz dokumentację PHP ).

terson
źródło
6
A każda „optymalizacja”, którą trzeba uruchomić 10 000 razy, aby zobaczyć tak niewielką różnicę, nie jest nawet warta zmartwień. Użyj programu profilującego i dowiedz się, gdzie są prawdziwe wąskie gardła w Twojej aplikacji. Wątpię, czy to pytanie jest wąskim gardłem.
DGM
1
To wszystko oznacza, że ​​nie ma to żadnego znaczenia. Używaj tego, co działa lepiej dla Ciebie.
Buttle Butkus,
wat are jiffies
OverCoder
21

Czy możesz podać nam linki do tych praktyk kodowania, które mówią, że należy tego unikać? Jeśli o mnie chodzi, to kompletny nie problem . Sam nie przeglądałem kodu źródłowego, ale wyobrażam sobie, że jedyną różnicą między includei include_oncejest to, że include_oncedodaje tę nazwę pliku do tablicy i sprawdza tablicę za każdym razem. Łatwo byłoby posortować tę tablicę, więc przeszukiwanie jej powinno mieć wartość O (log n), a nawet średnio-duża aplikacja miałaby tylko kilka tuzinów dołączeń.

nickf
źródło
po pierwsze, chazzuka.com/blog/?p=163 tak naprawdę nie „nie chcieli ”, ale zbyt wiele „drogich” rzeczy się sumuje. i faktycznie, wszystkie dołączone / wymagane pliki są dodawane do wewnętrznej tablicy (jest funkcja, aby ją zwrócić), myślę, że _once musi zapętlić tę tablicę i zrobić strcmp, co by się dodało
Uberfuzzy
7

Lepszym sposobem na robienie rzeczy jest użycie podejścia obiektowego i użycie __autoload () .

Greg
źródło
3
ale pierwszy przykład na stronie automatycznego ładowania obiektów, do której prowadziło
łącze,
Ja tego nie kupuję. Jest WIELE sytuacji, w których OO nie pasuje tak dobrze, jak inne paradygmaty, więc nie powinieneś zmuszać go tylko do uzyskania jakichkolwiek drobnych korzyści, jakie może przynieść __autoload ().
Bobby Jack
1
można by pomyśleć, że automatyczne ładowanie faktycznie potrwa dłużej niż * _ raz (zakładając, że potrzebujesz tylko tego, czego potrzebujesz).
nickf
Nie, nie jest, przynajmniej nie zdecydowanie, automatyczne ładowanie nadal musi być w jakiś sposób uwzględnione i jest to ostatnia deska ratunku dla PHP, zanim błąd się nie powiedzie - więc w rzeczywistości PHP faktycznie przeprowadza potencjalnie niepotrzebne sprawdzenia we wszystkich miejscach, które miałyby zastosowanie do uwzględnienia / wymagania i PO ŻE nazwałoby to automatyczne ładowanie (jeśli zostało zdefiniowane) ... PS: __autoload()jest odradzane i może być przestarzałe w przyszłości, powinieneś używać spl_autoload_register(...)tych dni ... PS2: nie zrozum mnie źle, czasami używam funkcji automatycznego ładowania; )
jave.web
6

Nie używa złej funkcji. Jest to niepoprawne zrozumienie, jak i kiedy go używać w ogólnej bazie kodu. Dodam tylko trochę więcej kontekstu do tego prawdopodobnie niezrozumianego pojęcia:

Ludzie nie powinni myśleć, że require_once to powolna funkcja. Musisz dołączyć swój kod w ten czy inny sposób. require_once()vs. require()prędkość nie jest problemem. Chodzi o wydajność utrudniającą zastrzeżenia, które mogą skutkować używaniem go na ślepo. Jeśli jest używany szeroko bez uwzględnienia kontekstu, może prowadzić do ogromnych strat pamięci lub marnotrawstwa kodu.

To, co widziałem, jest naprawdę złe, gdy ogromne monolityczne frameworki używają require_once()na wszystkie niewłaściwe sposoby, szczególnie w złożonym środowisku obiektowym (OO).

Weź przykład użycia require_once()na początku każdej klasy, jak widać w wielu bibliotekach:

require_once("includes/usergroups.php");
require_once("includes/permissions.php");
require_once("includes/revisions.php");
class User{
  // User functions
}

Tak więc Userklasa została zaprojektowana do używania wszystkich trzech innych klas. Słusznie!

Ale co teraz, jeśli użytkownik przegląda witrynę i nawet nie jest zalogowany, a struktura się ładuje: require_once("includes/user.php"); dla każdego żądania.

Zawiera 1 + 3 niepotrzebnych klas, których nigdy nie użyje podczas tego konkretnego żądania. W ten sposób rozdęte platformy zużywają 40 MB na żądanie, zamiast 5 MB lub mniej.


Innym sposobem, w jaki może być nadużywany, jest sytuacja, gdy klasa jest ponownie używana przez wielu innych! Załóżmy, że masz około 50 klas korzystających z helperfunkcji. Aby upewnić się, że helperssą dostępne dla tych klas po ich załadowaniu, otrzymujesz:

require_once("includes/helpers.php");
class MyClass{
  // Helper::functions(); // etc..
}

Nie ma tu nic złego per se. Jeśli jednak jedno żądanie strony zawiera 15 podobnych klas. Biegasz require_once15 razy lub dla ładnego obrazu:

require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");
require_once("includes/helpers.php");

Użycie require_once () technicznie wpływa na wydajność działania tej funkcji 14 razy, oprócz konieczności analizowania tych niepotrzebnych wierszy. Mając zaledwie 10 innych, często używanych klas, które mają podobny problem, może to stanowić ponad 100 wierszy takiego raczej bezcelowego, powtarzalnego kodu.

W związku z tym prawdopodobnie warto użyć require("includes/helpers.php");zamiast tego na ładowaniu aplikacji lub frameworku. Ale ponieważ wszystko jest względne, wszystko zależy od tego, czy waga w porównaniu z częstotliwością użytkowania helpersklasy jest warta zaoszczędzenia 15-100 linii require_once(). Ale jeśli prawdopodobieństwo nieużywania helperspliku w jakimkolwiek żądaniu jest zerowe, to requirezdecydowanie powinno być zamiast tego w twojej głównej klasie. Posiadanie require_onceosobno w każdej klasie staje się marnotrawstwem zasobów.


require_onceFunkcja jest przydatna, gdy jest to konieczne, ale nie powinny być traktowane jako monolityczny rozwiązanie wszędzie używać do ładowania wszystkich klas.

hexalys
źródło
5

Wiki PEAR2 (o ile istniało) podawało dobre powody do porzucenia wszystkich dyrektyw require / include na rzecz automatycznego ładowania , przynajmniej dla kodu biblioteki. To przywiązuje Cię do sztywnych struktur katalogów, gdy na horyzoncie pojawiają się alternatywne modele pakowania, takie jak phar .

Aktualizacja: ponieważ wersja wiki zarchiwizowana w Internecie jest niesamowicie brzydka, skopiowałem poniżej najważniejsze powody:

  • include_path jest wymagana, aby użyć pakietu (PEAR). Utrudnia to pakowanie pakietu PEAR do innej aplikacji z własną ścieżką include_path, tworzenie pojedynczego pliku zawierającego potrzebne klasy, przenoszenie pakietu PEAR do archiwum phar bez rozległej modyfikacji kodu źródłowego.
  • Gdy wymieszanie require_once najwyższego poziomu z warunkowym require_once może spowodować, że kod nie będzie można zapisać w pamięci podręcznej kodu operacji, takiej jak APC, która będzie dołączona do PHP 6.
  • względne require_once wymaga, aby parametr include_path był już ustawiony na poprawną wartość, co uniemożliwia użycie pakietu bez odpowiedniej ścieżki include_path
Steve Clay
źródło
5

*_once()Funkcje stat każdym katalogu nadrzędnego, aby upewnić się, że plik jesteś tym nie jest taki sam jak ten, który jest już zawarty. To jest jeden z powodów spowolnienia.

Zalecam użycie narzędzia takiego jak Siege do testów porównawczych. Możesz wypróbować wszystkie sugerowane metodologie i porównać czasy odpowiedzi.

Więcej na require_once()jest w Tech waszego wszechświata .

Annika Backstrom
źródło
Dzięki za wskazanie artykułu. require_once () jest dobrym pasem bezpieczeństwa w stosunku do plików z podwójnym włączaniem i będziemy go nadal używać, ale możliwość wyczyszczenia go jest fajna.
Andy Lester
2

Nawet jeśli require_oncei include_once wolniejsze niż requirei include(lub jakiekolwiek alternatywy mogą istnieć), mówimy tutaj o najmniejszym poziomie mikro-optymalizacji. Znacznie lepiej poświęcić czas na optymalizację tej źle napisanej pętli lub zapytania do bazy danych niż martwienie się o coś takiego require_once.

Teraz można by argumentować, mówiąc, że require_oncedopuszcza to złe praktyki kodowania, ponieważ nie musisz zwracać uwagi na utrzymanie czystości i porządku w dołączeniach, ale nie ma to nic wspólnego z samą funkcją , a zwłaszcza z jej szybkością.

Oczywiście automatyczne ładowanie jest lepsze ze względu na czystość kodu i łatwość konserwacji, ale chcę wyjaśnić, że nie ma to nic wspólnego z szybkością .

NeuroXc
źródło
0

Testujesz, używając funkcji include, alternatywy oli i __autoload (); i przetestuj go z zainstalowanym czymś takim jak APC .

Wątpię, by używanie stałej przyspieszyło sprawę.

Dinoboff
źródło
0

Tak, jest to nieco droższe niż zwykłe wymagania (). Myślę, że jeśli możesz utrzymać swój kod na tyle zorganizowany, aby nie powielać dołączeń, nie używaj funkcji * _once (), ponieważ pozwoli to zaoszczędzić kilka cykli.

Ale użycie funkcji _once () nie zabije twojej aplikacji. Zasadniczo nie używaj tego jako wymówki, aby nie organizować swoich dołączeń . W niektórych przypadkach używanie go jest nadal nieuniknione i nie jest to wielka sprawa.

Lucas Oman
źródło
-2

Myślę, że w dokumentacji PEAR jest zalecenie dla require, require_once, include i include_once. Przestrzegam tych wytycznych. Twoja aplikacja byłaby bardziej przejrzysta.

Ekkmanz
źródło
Niektóre odniesienia byłyby w porządku.
Peter Mortensen
-3

Nie ma to nic wspólnego z szybkością. Chodzi o to, żeby wdzięcznie zawieść.

Jeśli require_once () zawiedzie, Twój skrypt jest gotowy. Nic więcej nie jest przetwarzane. Jeśli użyjesz funkcji include_once (), reszta twojego skryptu będzie próbowała kontynuować renderowanie, więc Twoi użytkownicy potencjalnie nie byliby mądrzejsi w przypadku czegoś, co zawiodło w twoim skrypcie.

ashchristopher
źródło
1
Niekoniecznie. W rzeczywistości możesz podłączyć moduł obsługi błędów lub moduł obsługi zamykania systemu, aby dać użytkownikowi ładną stronę błędu (chociaż ludzie rzadko to robią). Jako programista o wiele wolałbym od razu wprowadzić błędy.
Edward Z. Yang,
1
Lub, w zależności od przypadku, nie zawiedzie z wdziękiem - jeśli jakiś ważny plik nie jest poprawnie wymagany (), dobrym pomysłem jest poddanie się i zatrzymanie. Ale to jest wymaganie vs uwzględnienie, podczas gdy myślę, że pytanie jest bardziej skoncentrowane na wymaganiu vs wymaganiu_once.
HoboBen
-4

Osobiście uważam, że użycie require_once (lub include_once) jest złą praktyką, ponieważ require_once sprawdza za ciebie, czy już dołączyłeś ten plik i pomija błędy podwójnie dołączonych plików, które powodują błędy krytyczne (takie jak zduplikowana deklaracja funkcji / klas / itp.) .

Powinieneś wiedzieć, czy musisz dołączyć plik.

Joe Scylla
źródło