Tại sao allow_once rất tệ để sử dụng?


143

Tất cả mọi thứ tôi đọc về các thực hành mã hóa PHP tốt hơn đều nói rằng đừng sử dụng require_oncevì tốc độ.

Tại sao lại thế này?

Cách thích hợp / tốt hơn để làm điều tương tự là require_oncegì? Nếu có vấn đề, tôi đang sử dụng PHP 5.


9
Câu hỏi này đã khá cũ và các câu trả lời không còn phù hợp nữa. Thật tuyệt vời khi thấy một bộ câu trả lời được cập nhật từ những người tham gia :)
Purefan 27/2/2015

Câu trả lời:


108

require_onceinclude_oncecả hai đều yêu cầu hệ thống giữ một bản ghi của những gì đã được bao gồm / yêu cầu. Mỗi *_oncecuộc gọi có nghĩa là kiểm tra nhật ký đó. Vì vậy, chắc chắn có một số công việc bổ sung đang được thực hiện ở đó nhưng đủ để làm giảm tốc độ của toàn bộ ứng dụng?

... Tôi thực sự nghi ngờ điều đó ... Không trừ khi bạn sử dụng phần cứng thực sự cũ hoặc làm việc đó rất nhiều .

Nếu bạn đang làm hàng ngàn *_once, bạn có thể tự mình thực hiện công việc theo cách nhẹ nhàng hơn. Đối với các ứng dụng đơn giản, chỉ cần đảm bảo rằng bạn đã chỉ bao gồm nó một lần nên là đủ nhưng nếu bạn vẫn nhận được lỗi Định nghĩa lại, bạn có thể một cái gì đó như thế này:

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

Cá nhân tôi sẽ gắn bó với các *_oncetuyên bố nhưng trên điểm chuẩn triệu ngớ ngẩn, bạn có thể thấy sự khác biệt giữa hai báo cáo:

                php                  hhvm
if defined      0.18587779998779     0.046600103378296
require_once    1.2219581604004      3.2908599376678

10-100 × chậm hơn require_oncevà nó tò mò require_oncedường như chậm hơn hhvm. Một lần nữa, điều này chỉ liên quan đến mã của bạn nếu bạn đang chạy *_oncehàng ngàn lần.


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

29
Tôi nghi ngờ phương thức được xác định () của bạn nhanh hơn bảng tra cứu tích hợp, nhưng tôi đồng ý với quan điểm chung của bạn - chắc chắn là không có vấn đề?!
Bobby Jack

1
Tôi khá chắc chắn rằng bạn đúng Bobby nhưng tôi không ủng hộ định nghĩa trên _once. Nó chỉ là một lựa chọn. Thời gian cần thiết để diễn giải mã thậm chí có thể làm cho nó chậm hơn một chút, nhưng, điều đó nói rằng, tôi không biết phương pháp nội bộ kỹ lưỡng đến mức nào. Nó có thể làm thêm để đảm bảo không trùng lặp.
Oli

8
Nhược điểm khác là APC không lưu cache bao
gồm_once và request_once

3
Tôi vừa thực hiện một thử nghiệm rất cơ bản về hai phương pháp - Tôi đã thực hiện 1.000.000 lần lặp bao gồm một tệp chỉ đơn giản xác định một hằng số 'testince' là đúng. Trong thử nghiệm đầu tiên, tôi đã sử dụng allow_once, lần thứ hai tôi đã sử dụng if (! Xác định ('testinclude')) và kết quả rất thú vị: Yêu cầu: 0.81639003753662 Không được xác định: 0.17906713485718 Xác định là nhanh hơn 0.63732290267944.
Travis Weston

Trường hợp với định nghĩa sẽ nhanh hơn vì bạn không thực hiện bất kỳ loại kiểm tra bổ sung nào, chẳng hạn như sử dụng realpath. Nó không so sánh hai thứ thực sự giống nhau.
jgmjgm

150

Chủ đề này làm cho tôi co rúm lại, bởi vì đã có một "giải pháp được đăng", và nó, cho tất cả các ý định và mục đích, sai. Hãy liệt kê:

  1. Định nghĩa là thực sự tốn kém trong PHP. Bạn có thể tự tìm kiếm hoặc kiểm tra nó, nhưng cách hiệu quả duy nhất để xác định hằng số toàn cầu trong PHP là thông qua một phần mở rộng. (Các hằng số lớp thực sự là hiệu năng khá tốt khôn ngoan, nhưng đây là điểm moot, vì 2)

  2. Nếu bạn đang sử dụng một cách require_once()thích hợp, nghĩa là, để bao gồm các lớp, bạn thậm chí không cần một định nghĩa; Chỉ cần kiểm tra nếu class_exists('Classname'). Nếu tệp bạn đang chứa có chứa mã, tức là bạn đang sử dụng nó theo kiểu thủ tục, hoàn toàn không có lý do nào require_once()cần thiết cho bạn; mỗi lần bạn bao gồm tệp bạn cho là đang thực hiện cuộc gọi chương trình con.

Vì vậy, trong một thời gian, rất nhiều người đã sử dụng class_exists()phương pháp này cho các vùi của họ. Tôi không thích nó bởi vì nó chạy trốn, nhưng họ có lý do chính đáng: require_once()khá kém hiệu quả trước một số phiên bản gần đây của PHP. Nhưng điều đó đã được sửa, và tôi tranh cãi rằng mã byte phụ mà bạn phải biên dịch cho lệnh gọi có điều kiện và phương thức bổ sung, sẽ vượt xa bất kỳ kiểm tra hashtable nội bộ nào.

Bây giờ, một sự thừa nhận: công cụ này rất khó để kiểm tra, vì nó chiếm quá ít thời gian thực hiện.

Đây là câu hỏi bạn nên suy nghĩ: bao gồm, như một quy tắc chung, rất tốn kém trong PHP, bởi vì mỗi khi trình thông dịch chạm vào nó, nó phải chuyển trở lại chế độ phân tích cú pháp, tạo ra các opcode và sau đó nhảy trở lại. Nếu bạn có hơn 100 bao gồm, điều này chắc chắn sẽ có tác động hiệu suất. Lý do tại sao sử dụng hay không sử dụng allow_once là một câu hỏi quan trọng như vậy là vì nó gây khó khăn cho bộ nhớ opcode. Một lời giải thích cho điều này có thể được tìm thấy ở đây, nhưng điều này sôi nổi là:

  • Nếu trong thời gian phân tích cú pháp, bạn biết chính xác những gì bạn sẽ cần trong toàn bộ vòng đời của yêu cầu, require()những tệp ngay từ đầu và bộ đệm opcode sẽ xử lý mọi thứ khác cho bạn.

  • Nếu bạn không chạy bộ đệm opcode, bạn đang ở một nơi khó khăn. Nội tuyến tất cả bao gồm của bạn vào một tệp (không làm điều này trong quá trình phát triển, chỉ trong sản xuất) chắc chắn có thể giúp phân tích thời gian, nhưng đó là một điều khó khăn, và, bạn cũng cần biết chính xác những gì bạn sẽ bao gồm trong quá trình yêu cầu.

  • Tự động tải rất thuận tiện, nhưng chậm, vì lý do logic tự động tải phải được chạy mỗi khi bao gồm xong. Trong thực tế, tôi đã thấy rằng tự động tải một số tệp chuyên dụng cho một yêu cầu không gây ra quá nhiều vấn đề, nhưng bạn không nên tự động tải tất cả các tệp bạn cần.

  • Nếu bạn có thể bao gồm 10 (đây là một rất sau của việc tính toán phong bì), tất cả wanking đây không phải là giá trị của nó: chỉ cần tối ưu hóa truy vấn cơ sở dữ liệu của bạn hoặc một cái gì đó.


14
Đây là 4 năm và phần lớn không còn áp dụng nữa define(), require_once()defined()tất cả chỉ mất khoảng 1-2 micro giây trên máy của tôi.
Daniel Beardsley

72
Nhưng đó là 2 micro giây sớm hơn người dùng sẽ có trang. Trong một năm lượt xem trang, điều đó có thể giúp người dùng tiết kiệm được toàn bộ 3 giây! Họ có thể xem một phần mười quảng cáo trong thời gian đó! Hãy nghĩ về người dùng. Đừng lãng phí micro giây.
Andrew Oblley

15
Để mọi người nhận thức được sự châm biếm, một phần triệu giây là 1/1000000 của một giây.
Andy Chase

1
@AndrewEnsley Bạn chỉ đơn giản là nhầm lẫn với tất cả sự mỉa mai của bạn. Bạn không biết gì về thực tế là PHP cũng chạy trên bộ vi xử lý, 1 micro giây trên PC của bạn là vài mili giây trên bộ vi xử lý. Bây giờ những gì về việc có 20 bao gồm các tập tin, một dự án lớn hơn? Đó là độ trễ 20 lần vài mili giây được giới thiệu, vì vậy chúng tôi đã đạt đến một điểm đáng chú ý đối với con người. Nếu tập lệnh đó được gọi thường xuyên, nó sẽ gây ra các vấn đề về hiệu năng trên hệ thống. Tối ưu hóa không phải là một trò đùa và cả thế giới không xoay quanh PC của bạn. Có mười ngàn CPU đang được sử dụng.
Giăng

2
@John. Đó là một trò đùa được thực hiện trong tinh thần tốt. Không có ý định ác ý. Nếu nó đáng để bạn tối ưu hóa bao gồm, hãy tiếp tục.
Andrew Oblley

66

Tôi đã tò mò và kiểm tra liên kết của Adam Backstrom với Tech Your Universe . Bài viết này mô tả một trong những lý do cần phải được sử dụng thay vì allow_once. Tuy nhiên, tuyên bố của họ đã không theo kịp phân tích của tôi. Tôi muốn biết nơi tôi có thể đánh giá sai giải pháp. Tôi đã sử dụng PHP 5.2.0 để so sánh.

Tôi đã bắt đầu bằng cách tạo 100 tệp tiêu đề đã sử dụng allow_once để bao gồm một tệp tiêu đề khác. Mỗi tệp này trông giống như:

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

?>

Tôi đã tạo những thứ này bằng cách sử dụng hack Bash nhanh chóng:

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

Bằng cách này, tôi có thể dễ dàng trao đổi giữa việc sử dụng allow_once và yêu cầu khi bao gồm các tệp tiêu đề. Sau đó tôi đã tạo một app.php để tải một trăm tệp. Điều này trông giống như:

<?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);
?>

Tôi đã đối chiếu các tiêu đề allow_once với các tiêu đề yêu cầu sử dụng tệp tiêu đề trông giống như:

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

Tôi không tìm thấy nhiều sự khác biệt khi chạy cái này với request so với allow_once. Trên thực tế, các thử nghiệm ban đầu của tôi dường như ngụ ý rằng request_once nhanh hơn một chút, nhưng tôi không nhất thiết phải tin vào điều đó. Tôi lặp lại thí nghiệm với 10000 tệp đầu vào. Ở đây tôi đã thấy một sự khác biệt nhất quán. Tôi đã chạy thử nghiệm nhiều lần, kết quả rất gần nhưng sử dụng allow_once sử dụng trung bình 30,8 jiffies người dùng và 72,6 jiffies hệ thống; sử dụng yêu cầu sử dụng trung bình 39,4 jiffies người dùng và 72.0 jiffies hệ thống. Do đó, có vẻ như tải thấp hơn một chút bằng cách sử dụng allow_once. Tuy nhiên, thời gian đồng hồ treo tường hơi tăng. Trung bình 10.000 cuộc gọi request_once sử dụng trung bình 10,15 giây để hoàn thành trung bình và 10.000 cuộc gọi yêu cầu sử dụng trung bình 9,84 giây.

Bước tiếp theo là xem xét những khác biệt này. Tôi đã sử dụng strace để phân tích các cuộc gọi hệ thống đang được thực hiện.

Trước khi mở tệp từ request_once, các cuộc gọi hệ thống sau đây được thực hiện:

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

Điều này trái ngược với yêu cầu:

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

Công nghệ Vũ trụ của bạn ngụ ý rằng request_once sẽ thực hiện nhiều cuộc gọi lstat64 hơn. Tuy nhiên, cả hai đều thực hiện cùng một số cuộc gọi lstat64. Có thể, sự khác biệt là tôi không chạy APC để tối ưu hóa mã ở trên. Tuy nhiên, tiếp theo tôi đã so sánh đầu ra của strace cho toàn bộ các lần chạy:

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

Thực tế, có khoảng hai cuộc gọi hệ thống khác trên mỗi tệp tiêu đề khi sử dụng allow_once. Một điểm khác biệt là allow_once có thêm lệnh gọi hàm time ():

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

Cuộc gọi hệ thống khác là getcwd ():

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

Điều này được gọi bởi vì tôi đã quyết định đường dẫn tương đối được tham chiếu trong các tệp hdrXXX. Nếu tôi thực hiện điều này một tham chiếu tuyệt đối, thì sự khác biệt duy nhất là cuộc gọi thời gian bổ sung (NULL) được thực hiện trong mã:

[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

Điều này dường như ngụ ý rằng bạn có thể giảm số lượng cuộc gọi hệ thống bằng cách sử dụng các đường dẫn tuyệt đối thay vì các đường dẫn tương đối. Sự khác biệt duy nhất bên ngoài đó là các cuộc gọi thời gian (NULL) dường như được sử dụng để ghi mã để so sánh cái nào nhanh hơn.

Một lưu ý khác là gói tối ưu hóa APC có một tùy chọn gọi là "apc.include_once_override" tuyên bố rằng nó giảm số lượng cuộc gọi hệ thống được thực hiện bởi các cuộc gọi allow_once và include_once (xem tài liệu PHP ).


6
Và bất kỳ "tối ưu hóa" nào mà bạn phải chạy 10.000 lần để thấy sự khác biệt rất nhỏ như vậy thậm chí không đáng lo ngại. Sử dụng một hồ sơ và tìm ra nơi tắc nghẽn thực sự trong ứng dụng của bạn. Tôi nghi ngờ câu hỏi này là nút cổ chai.
DGM

1
Tất cả điều này có nghĩa là nó hoàn toàn không thành vấn đề. Sử dụng bất cứ điều gì làm việc tốt hơn cho bạn một cách hợp lý.
Butussy Butkus

wat là jiffies
OverCoder

21

Bạn có thể cung cấp cho chúng tôi bất kỳ liên kết đến các thực hành mã hóa mà nói để tránh nó? Theo tôi nghĩ, đó là một vấn đề hoàn toàn . Tôi đã không nhìn vào mã nguồn, nhưng tôi tưởng tượng rằng sự khác biệt duy nhất giữa includeinclude_onceđó là include_oncethêm tên tệp đó vào một mảng và kiểm tra mảng mỗi lần. Thật dễ dàng để giữ cho mảng đó được sắp xếp, vì vậy tìm kiếm trên đó phải là O (log n) và ngay cả một ứng dụng cỡ trung bình cũng chỉ có vài chục bao gồm.


một là, chazzuka.com/blog/?p=163 họ thực sự không "không", nhưng quá nhiều thứ 'đắt tiền' cộng lại. và trên thực tế, tất cả các tệp được bao gồm / yêu cầu được thêm vào một mảng bên trong (có chức năng trả về nó), tôi đoán rằng _once phải lặp lại mảng đó và thực hiện strcmp, sẽ bổ sung
Uberfuzzy

7

Cách tốt hơn để làm mọi việc là sử dụng cách tiếp cận hướng đối tượng và sử dụng __autoload () .


3
nhưng ví dụ đầu tiên trong trang đối tượng tự động tải mà bạn đã liên kết để sử dụng allow_once
Shabbycoat

Tôi không mua cái này. Có NHIỀU tình huống trong đó OO không phù hợp như các mô hình khác, vì vậy bạn không nên ép buộc để đạt được bất kỳ lợi thế nhỏ nào có thể có với __autoload ().
Bobby Jack

1
bạn nghĩ rằng tự động tải sẽ thực sự mất nhiều thời gian hơn * _once (giả sử rằng bạn chỉ yêu cầu những gì bạn cần).
nickf

Không, không phải vậy, ít nhất là không chắc chắn, Autoload vẫn cần được đưa vào bằng cách nào đó và đó là giải pháp cuối cùng cho PHP trước khi lỗi không thành công - vì vậy trong thực tế PHP thực sự thực hiện kiểm tra không cần thiết thông qua tất cả các nơi sẽ áp dụng để bao gồm / yêu cầu và SAU RATNG nó sẽ gọi tự động tải (nếu có xác định) ... PS: __autoload()không được khuyến khích và nó có thể bị phản đối trong tương lai, bạn nên sử dụng spl_autoload_register(...)những ngày này ... PS2: đôi khi tôi không sử dụng chức năng tự động tải; )
jave.web

6

Nó không sử dụng chức năng xấu. Đó là một sự hiểu biết không chính xác về cách thức và thời điểm sử dụng nó, trong một cơ sở mã tổng thể. Tôi sẽ chỉ thêm một chút bối cảnh cho khái niệm có thể bị hiểu lầm:

Mọi người không nên nghĩ rằng request_once là một chức năng chậm. Bạn phải bao gồm mã của bạn bằng cách này hay cách khác. require_once()so với require()tốc độ không phải là vấn đề. Đó là về hiệu suất cản trở hiệu suất có thể dẫn đến việc sử dụng nó một cách mù quáng. Nếu được sử dụng rộng rãi mà không xem xét cho ngữ cảnh, nó có thể dẫn đến lãng phí bộ nhớ lớn hoặc mã lãng phí.

Những gì tôi đã thấy thực sự tồi tệ, là khi các khung nguyên khối khổng lồ sử dụng require_once()sai tất cả các cách, đặc biệt là trong một môi trường hướng đối tượng (OO) phức tạp.

Lấy ví dụ về việc sử dụng require_once()ở đầu mỗi lớp như đã thấy trong nhiều thư viện:

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

Vì vậy, Userlớp được thiết kế để sử dụng cả ba lớp khác. Đủ công bằng!

Nhưng bây giờ sẽ ra sao nếu khách truy cập đang duyệt trang web và thậm chí không đăng nhập và khung tải: require_once("includes/user.php");cho mỗi yêu cầu.

Nó bao gồm 1 + 3 lớp không cần thiết mà nó sẽ không bao giờ sử dụng trong yêu cầu cụ thể đó. Đây là cách các khung cồng kềnh kết thúc bằng cách sử dụng 40 MB cho mỗi yêu cầu thay vì 5 MB hoặc ít hơn.


Các cách khác nó có thể bị sử dụng sai, là khi một lớp được sử dụng lại bởi nhiều người khác! Giả sử bạn có khoảng 50 lớp sử dụng helperhàm. Để đảm bảo helperscó sẵn cho các lớp đó khi chúng được tải, bạn nhận được:

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

Không có gì sai ở đây mỗi se. Tuy nhiên nếu một yêu cầu trang xảy ra bao gồm 15 lớp tương tự. Bạn đang chạy require_once15 lần hoặc cho một hình ảnh đẹp:

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");

Việc sử dụng allow_once () về mặt kỹ thuật ảnh hưởng đến hiệu năng để chạy chức năng đó 14 lần, trên hết là phải phân tích các dòng không cần thiết đó. Chỉ với 10 lớp được sử dụng nhiều khác với vấn đề tương tự, nó có thể chiếm hơn 100 dòng mã lặp đi lặp lại khá vô nghĩa như vậy.

require("includes/helpers.php");Thay vào đó, có lẽ đáng để sử dụng tại bootstrap của ứng dụng hoặc khung của bạn, thay vào đó. Nhưng vì mọi thứ đều tương đối, tất cả phụ thuộc vào việc trọng số so với tần suất sử dụng của helperslớp có đáng để tiết kiệm 15 - 100 dòng hay không require_once(). Nhưng nếu xác suất không sử dụng helperstệp trên bất kỳ yêu cầu cụ thể nào là không có, thì requirechắc chắn nên ở trong lớp chính của bạn. Có require_oncetrong mỗi lớp riêng biệt trở thành một sự lãng phí tài nguyên.


Các require_oncechức năng rất hữu ích khi cần thiết, nhưng nó không nên được coi là một giải pháp nguyên khối để sử dụng ở khắp mọi nơi để tải tất cả các lớp học.


5

Wiki PEAR2 (khi nó tồn tại) được sử dụng để liệt kê các lý do chính đáng để từ bỏ tất cả các chỉ thị yêu cầu / bao gồm có lợi cho việc tự động tải, ít nhất là cho mã thư viện. Những thứ này buộc bạn xuống các cấu trúc thư mục cứng nhắc khi các mô hình đóng gói thay thế như phar xuất hiện.

Cập nhật: Vì phiên bản lưu trữ web của wiki rất xấu, tôi đã sao chép những lý do hấp dẫn nhất dưới đây:

  • include_path là bắt buộc để sử dụng gói (PEAR). Điều này gây khó khăn cho việc gói một gói PEAR trong một ứng dụng khác với bao gồm chính nó, để tạo một tệp duy nhất chứa các lớp cần thiết, để chuyển gói PEAR sang kho lưu trữ phar mà không cần sửa đổi mã nguồn mở rộng.
  • khi request_once cấp cao nhất được trộn lẫn với request_once có điều kiện, điều này có thể dẫn đến mã không thể truy cập được bởi các bộ đệm opcode như APC, sẽ được gói cùng với PHP 6.
  • Yêu cầu tương đối yêu cầu bao gồm bao gồm_path đã được thiết lập đúng giá trị, khiến cho không thể sử dụng gói mà không có bao gồm đúng_path

5

Các *_once()chức năng stat mọi thư mục mẹ để đảm bảo tệp bạn bao gồm không giống với tệp đã được đưa vào. Đó là một phần lý do cho sự chậm lại.

Tôi khuyên bạn nên sử dụng một công cụ như Siege để đo điểm chuẩn. Bạn có thể thử tất cả các phương pháp được đề xuất và so sánh thời gian phản hồi.

Thêm vào require_once()là tại Tech Your Universe .


Cảm ơn con trỏ đến bài viết. Yêu cầu_once () là một vành đai an toàn tốt so với các tệp bao gồm gấp đôi và chúng tôi sẽ tiếp tục sử dụng nó, nhưng có thể làm cho nó sạch sẽ là tốt.
Andy Lester

2

Thậm chí nếu require_onceinclude_once chậm hơn so với requireinclude(hoặc bất kỳ lựa chọn thay thế có thể tồn tại), chúng ta đang nói về mức độ nhỏ nhất của vi-tối ưu hóa ở đây. Thời gian của bạn tốt hơn dành cho việc tối ưu hóa vòng lặp hoặc truy vấn cơ sở dữ liệu được viết kém hơn là lo lắng về một cái gì đó như thế nào require_once.

Bây giờ, người ta có thể đưa ra một lập luận nói rằng require_oncecho phép thực hành mã hóa kém bởi vì bạn không cần phải chú ý đến việc giữ cho bao gồm sạch sẽ và có tổ chức, nhưng điều đó không liên quan gì đến chính chức năng và đặc biệt là tốc độ của nó.

Rõ ràng, tự động tải tốt hơn vì mục đích sạch mã và dễ bảo trì, nhưng tôi muốn làm rõ rằng điều này không liên quan gì đến tốc độ .



0

Có, nó đắt hơn một chút so với yêu cầu (). Tôi nghĩ vấn đề là nếu bạn có thể giữ cho mã của mình được tổ chức đủ để không trùng lặp bao gồm, đừng sử dụng các hàm * _once (), vì nó sẽ giúp bạn tiết kiệm một số chu kỳ.

Nhưng sử dụng các hàm _once () sẽ không giết ứng dụng của bạn. Về cơ bản, chỉ cần không sử dụng nó như một cái cớ để không phải tổ chức bao gồm của bạn . Trong một số trường hợp, sử dụng nó vẫn không thể tránh khỏi, và nó không phải là vấn đề lớn.


-2

Tôi nghĩ trong tài liệu PEAR, có một khuyến nghị cho các yêu cầu, allow_once, bao gồm và include_once. Tôi làm theo hướng dẫn đó. Ứng dụng của bạn sẽ rõ ràng hơn.


Một số tài liệu tham khảo sẽ theo thứ tự.
Peter Mortensen

-3

Nó không có gì để làm với tốc độ. Đó là về thất bại duyên dáng.

Nếu request_once () thất bại, tập lệnh của bạn đã hoàn thành. Không có gì khác được xử lý. Nếu bạn sử dụng include_once () phần còn lại của tập lệnh sẽ cố gắng tiếp tục hiển thị, do đó người dùng của bạn có khả năng sẽ không khôn ngoan hơn với điều gì đó đã thất bại trong tập lệnh của bạn.


1
Không cần thiết. Bạn thực sự có thể móc vào một trình xử lý lỗi hoặc trên trình xử lý tắt máy để cung cấp cho người dùng một trang lỗi đẹp (mặc dù mọi người hiếm khi làm như vậy). Là một nhà phát triển, tôi muốn thay đổi mọi thứ ngay lập tức.
Edward Z. Yang

1
Hoặc, như trường hợp có thể, không thất bại một cách duyên dáng - nếu một số tệp quan trọng không yêu cầu () đúng cách, thì nên từ bỏ và tạm dừng. Nhưng đó là yêu cầu so với bao gồm, trong khi tôi nghĩ rằng câu hỏi tập trung hơn vào yêu cầu so với request_once.
HoboBen

-4

Ý kiến ​​cá nhân của tôi là việc sử dụng allow_once (hoặc include_once) là một cách làm không tốt bởi vì notify_once kiểm tra cho bạn nếu bạn đã bao gồm tệp đó và loại bỏ lỗi của các tệp được bao gồm gấp đôi dẫn đến lỗi nghiêm trọng (như khai báo trùng lặp các hàm / lớp / v.v.) .

Bạn nên biết nếu bạn cần bao gồm một tập tin.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.