1. 程式人生 > 實用技巧 >掌握提高 Web 應用的效能的方法 之 優化 PHP 和 Laravel

掌握提高 Web 應用的效能的方法 之 優化 PHP 和 Laravel

Laravel 有很多東西。但是快不是其中之一。讓我們學習一些優化技巧,以加快執行速度!

自從 Laravel 誕生以來,沒有一個 PHP 開發人員不受她的影響。他們是喜歡 Laravel 提供的快速開發的初級或中級開發人員,或者是由於市場壓力而被迫學習 Laravel 的高階開發人員。

不管怎樣,不可否認的是,Laravel 已經振興了 PHP 生態系統。

對 Laravel 的評價節選

但是,由於 Laravel 竭盡全力讓您的事情變得簡單,這意味著它在底層做了大量工作,以確保您作為開發人員能有一個舒適的程式設計體驗。 Laravel 所有看似「神奇」的功能都有一層又一層的程式碼,每當執行一個功能時都需要啟動這些程式碼層。甚至是一個簡單的異常都會深究到底層 (從錯誤那裡開始,一直到核心):

對於一個檢視中似乎是編譯錯誤的情況,有 18 個函式呼叫要跟蹤。我個人遇到過 40 個的,如果您使用其他庫和外掛,則可能會更多。

重點是,預設情況下,這樣層層巢狀的程式碼,使得 Laravel 速度很慢。

Laravel 有多慢?

說實話,這個問題根本無法回答,原因有幾個。

首先,目前還沒有公認的、客觀的、合理的標準來衡量網路應用的速度。與什麼相比更快或更慢?在什麼條件下?

其次,一個 Web 應用取決於很多東西(資料庫、檔案系統、網路、快取等),所以談論速度是很愚蠢的。一個非常快的 Web 應用,如果有一個非常慢的資料庫,那麼它就是一個非常慢的 Web 應用。

但這種不確定性正是基準測試受歡迎的原因。儘管它們毫無意義,但它們提供了一些 參考框架,幫助我們避免生氣。因此,最好有所保留,讓我們對 PHP 框架之間的速度有一個錯誤的、粗略的認識。

根據這個相當值得尊敬的 GitHub原始碼,以下是 PHP 框架的對比情況。

你可能根本不會注意到 Laravel 在這裡 (即使你真的很努力地眯著眼睛), 除非你把你的目光投到最尾部。是的,親愛的朋友們,Laravel 排在最後! 現在,理所當然的,這些「框架」中的大多數都不是很實用,甚至沒有什麼用處,但它確實告訴我們,與其他更流行的框架相比,Laravel 是多麼的慢。

通常情況下,這種「慢」在應用中不會出現, 因為我們日常的 Web 應用很少達到很高的資料量。但是一旦達到了(比如高達 200-500 以上的併發量),伺服器就會開始阻塞而死。這時候即使扔再多的硬體也解決不了問題,基礎架構費用迅速攀升,你對雲端計算的崇高理想轟然倒塌。

不過,嘿嘿,振作起來吧! 這篇文章並不是講什麼不能做, 而是講什麼可以做。

好訊息是, 你可以做很多事情來讓你的 Laravel 應用更快。幾倍的速度。 是的,不是開玩笑。你可以讓同樣的程式碼庫變得快速,每個月節省幾百美元的基礎設施 / 託管費用。 怎麼做?讓我們開始吧。

四種類型的優化

在我看來,優化可以在四個不同的層面上進行(當涉及到 PHP 應用時,就是):

  1. 語言層面:這意味著你使用更快的語言版本,並避免語言中特定的功能 / 編碼風格,使你的程式碼速度變慢。
  2. 框架層面:這些是我們在本文中要涉及的內容。
  3. 基礎設施層面:調整你的 PHP 程序管理器、Web 伺服器、資料庫等。
  4. 硬體層面:轉向更好、更快、更強大的硬體主機提供商。

所有這些型別的優化都有其存在的意義(例如,php-fpm 的優化是非常關鍵和強大的)。但本文的重點是純粹的第 2 類優化:那些與框架相關的優化。

順便說一下,這些編號背後沒有任何理由,也不是一個公認的標準。我只是編了這些。請千萬不要引用我的話說:「我們的伺服器需要 type-3 優化」,否則你的團隊負責人會殺了你,找到我,然後把我也殺了。

現在,我們終於到了應許之地。

要注意 n+1 資料庫查詢

n+1 查詢問題是使用 ORM 時常見的問題。Laravel 有其強大的 ORM,叫 Eloquent,它是如此的漂亮,如此的方便,以至於我們常常忘記了看是怎麼回事。

考慮一個非常常見的場景:顯示指定客戶列表下的所有訂單。這在電子商務系統和任何需要顯示與某些實體相關的所有實體的列表中非常常見,

我們可以想象有這樣一個控制器:

class OrdersController extends Controller
{
    // ...

    public function getAllByCustomers(Request $request, array $ids) {
        $customers = Customer::findMany($ids);
        $orders = collect(); // new collection

        foreach ($customers as $customer) {
            $orders = $orders->merge($customer->orders);
        }

        return view('admin.reports.orders', ['orders' => $orders]);
    }
}

太好了!更重要的是,優雅,美麗。