尤其適合傳統 PHP 開發者學習 Laravel 的建議

假如你對 PHP 的印象還停留在 PHP 與 HTML 夾雜、沒有 OOP、沒有 package、沒有 MVC、沒有 framework、沒有測試的寫法,那你應該來學學 Laravel,它是一個使用 PHP 最新 OOP 語法、以 Composer 管理套件、MVC 架構、融合 RoR 與 ASP.NET MVC 風格、支援單元測試的 framework,可以說與傳統 PHP 的寫法完全不同,是一個更優雅且生產力更高的全新 PHP。

我真的需要 Framework 嗎?


傳統 PHP 算是 HTML 的 preprocessor,類似 C 語言的 # 開頭關鍵字,如 #if夾雜在 C 語言裡,主要是在產生 C 語言,而不是產生執行檔;而傳統 PHP 的目的就是為了產生 HTML,所以自然也就夾雜在 HTML 裡。

假如只是簡單的顯示邏輯,夾雜在 HTML 就還可以接受,但問題是傳統 PHP,是同時將顯示邏輯、商業邏輯與資料庫邏輯全部與 HTML 夾雜在一起,別忘了網頁前端還有 JavaScript,這就造成了傳統 PHP 是一個 .php 檔內,同時有 HTML、JavaScript、PHP 與 SQL 4 種語言並存,複雜度之高可以想像,所以傳統 PHP 一直被戲稱是義大利麵程式碼。

之後PHP也曾做一些改革,避免 HTML 與 PHP 並存,如 Smarty 這些樣版引擎的出現,專門負責顯示邏輯,而將商業邏輯與資料庫邏輯另外獨立出來,這種寫法已經比之前進步許多,也比較容易維護。

但傳統 PHP 仍然有許多問題,如 :

  1. 一個網頁一個 php : 駭客很容易根據你的副檔名就得知你用什麼後端技術,而輕易使用PHP的漏洞攻擊你。
  2. PHP 缺乏統一的寫法 : 所以只要接手前人的程式,就必須去熟悉他的寫法,維護成本很高。
  3. 每個 PHP 網頁都要從頭開始打造 : 無法使用前人驗證過的套件,開發效率很低。

相對於同期其他網頁技術,如 RoR,ASP.NET,JSP 等,均開始以 framework 的方式呈現 :

  1. MVC 架構 : 不再一個網頁一個檔,而改以 MVC 的方式呈獻,駭客無法再以網頁副檔名得知我後端用什麼技術。
  2. Framework 規定統一寫法 : 以 framework 方式強制規定統一的寫法,如需要哪些目錄,需要哪些檔案,這樣使得大家的寫法都差不多,很容易接手前人的程式,可大幅降低維護成本。
  3. 不必再重新製造輪子 : 不再每個網頁都需要從頭開始打造,取而代之的是很多程式產生器與套件,只要透過一些指令就能幫我們產生程式的框架或下載套件,再加以客製化修改即可,可大幅增加開發效率。

Framework 與 Library 的差異


Framework 與 Library 有以下重要的差異 :

  • Library : 定義很多方便好用的函式供我們使用,而專案整體架構 (目錄、檔案) 則由開發者自行決定,開發者會去呼叫 library 所提供的函式。
  • Framework : 強勢定義整個架構的寫法,我們必須遵守它所定義的架構,去將程式碼進去,因此大家寫出來的程式碼都差不多,將來更容易維護。

使用 Framework 的缺點


Framework 聽起來很棒,但天底下的事有優點就一定有缺點,常常就是一種 trade off。

  1. 執行速度較慢 : Framework 的執行速度一定比傳統 PHP 慢,這也是為什麼當有人問 PHP 爸爸 Rasmus Lerdorf 對於 PHP 使用 framework 的看法時,他的回答是 :「 若你不在乎速度就用吧! 」,但目前半導體進步的速度很快,根據莫爾定律,半導體速度每兩年會增加一倍,且現在雲端技術進步,速度問題已經不如以往那麼重要。
  2. 需要重新學習 : Framework 需要付出學習代價,因為它帶出很多傳統 PHP 沒有的觀念,如物件導向、MVC、Composer、套件、ORM、Migration….等,但只要能通過這些新的觀念的門檻,之後的維護成本會降低,開發效率會提高。

我該怎麼挑選 Framework?


PHP 與 JavaScript一樣,有眾多的 framework 可以挑選,大致上可分為 4 類 :

  1. 強調支援PHP版本最廣 : CodeIgniter。
  2. 強調全功能 : Symfony 與 Laravel。
  3. 強調簡約 : Slim 與 Lumen。
  4. 強調速度 : Falcon。

簡單的介紹這些 framework 的特色 :

  • CodeIgniter : 最新的 CodeIgniter 3.x 版只需要 PHP 5.2.4 以上即可執行,很適合接案,且無法控制代管主機的 PHP 版本者使用。
  • Symfony : 優異的全功能 framework,學習門檻較高,Laravel 底層使用很多 Symfony 的套件。
  • Laravel : 簡單易學的全功能 framework,架構優美,社群活躍。
  • Slim : 適合前後端分家,後端只用來寫 RESTful API 的 framework。
  • Lumen : Laravel 的精簡版本,適合前後端分家,後端只用來寫 RESTful API 的 framework。
  • Falcon :整個 framework 不是以 PHP 寫的,而是以 C 開發,因此速度非常快。

對於 framework 的挑選,我有幾個建議 :

  1. 挑自己喜歡的架構 : 每個 framework 都有它自己的特色,但它的架構可能不是自己喜歡的,畢竟要 Code Happy ,所以首先必須要挑一個自己喜歡的 framework,這樣才能快快樂樂的一直用下去。

  2. 社群活躍 : 一個技術要普及,除了技術本身的優越外,還要靠眾多的傳教士傳遞福音,辦讀書會、辦 seminar、寫 tutorial、Facebook 與 Slack 討論問題…等,這樣才會讓更多的初學者有管道可以學習討論,而 Laravel台灣是目前台灣 PHP 最活躍的社團,而且活動都是免費,連場地費都不用,這也是當初我選擇學習 Laravel 最大的原因。

  3. 用的人多 : 假如你是初學者,根本不知道自己喜歡什麼,那另外一個指標就是看佔有率,根據 2015 年三月 Sitepoint 所做的調查,在 PHP 眾多 framework 當中,Laravel 的佔有率第一。用的人越用,表示有問題越容易google,因為相同的問題全世界不會只有你遇到,因而越容易找得到解決的方法。

Laravel 環境難安裝?


Laravel 的環境是有名的難安裝,主要有兩個原因 :

  1. Laravel 對於 PHP 版本要求較高 : 以 Laravel 5.1 而言,要求 PHP 5.5.9 以上,因為 Laravel 用到了 PHP 最新的物件導向語法開發,也就是說,只要 PHP 一提供新的功能,Laravel 就會想盡辦法用上,所以 Laravel 對 PHP 版本要求很高。
  2. Laravel 使用了較罕用的 PHP extension : 在 Windows 平台,一般人都會使用類似 Wampserver 之類的懶人包開發 PHP,不過這些懶人包預設並沒有安裝 Laravel 所需要的 PHP extension,而這些 extension 又是 C 語言所開發,要求 PHP 開發者自己使用 Visual C++ 去編譯這些 PHP extension 又有難度,這導致要 Laravel 要跑在 Windows 平台比較困難,不過這些 PHP extension 對於 OS X 或 Ubuntu 都不是問題,而且正式上線主機多半也都是 Linux,所以不用擔心正式上線主機難安裝 Laravel。

什麼是 MVC 架構?


傳統 PHP 是將顯示邏輯、商業邏輯與資料庫邏輯全部寫在單一的 *.php 檔案中,因為同時包含 HTML、JavaScript、PHP 與 SQL 4 種語言並存,所以很難維護。

而 MVC 架構是將整個專案分成 model、view、controller 三層,對於專案,大體上可以將 model 放資料庫邏輯,view 放顯示邏輯,而 controller放商業邏輯。

怎麼多了這麼多資料夾?


傳統 PHP 開發,檔案與資料夾都是由開發者自行定義,所以當你接手別人留下來的專案時,假如有文件最好,首先必須先閱讀文件才知道每個檔案與資料夾的功用為何,否則就得慢慢的 trace code;而 Laravel 一安裝完後,就會發現有預設有很多資料夾與檔案,初學者當然也是要看 Laravel 文件,但一旦學過一次之後,之後再接手其他人使用 Laravel 開發的專案時,你會發現因為 Laravel 已經將資料夾與檔案架構定好,所以每個人寫出來的架構都一樣,所以上手很快,降低了維護成本。

怎麼這麼多指令?


Laravel之所以會多了這麼多指令,主要來自於兩項 :

  1. Composer : 負責安裝套件。
  2. Artisan : Laravel 的 CLI 工具,如負責產生 model 與 controller …等程式框架,讓我們只需繼續客製化即可,不用從頭開始打造。

這些都是 Laravel 提高生產力的關鍵,當然天下沒有白吃的午餐,你必須要熟悉 Composer 與 Artisan 兩個工具怎麼使用,他沒有 GUI 介面,只是個 CLI 的程式,因此有很多參數要記。

什麼是物件導向?


OOP 全名為 Object Oriented Programming,中文稱為物件導向程式設計,物件導向主要是一種對大型程式解耦合的技術,讓我們更容易去維護大型專案,從 PHP 5 之後陸續開始支援 物件導向,而 Laravel 更是依照物件導向 SOLID 精神所設計的 framework,所以在寫 Laravel 時,會深深感受到濃濃的物件導向風格,這是寫傳統 PHP 無法感受的,而這也是我打從心裡喜歡 Laravel 的主要原因,除此之外,你也可以把 Laravel 的原始碼當成學習物件導向的範本,在 trace 其程式碼時,去體會 SOLID 的內涵,去看看高手如何實踐 SOLID,這也是寫傳統 PHP 所學不到的。

什麼是Composer?


當程式開始以物件導向方式開發後,一些高手就會開始將與商業邏輯無關,卻又常常會用到的功能以套件的方式打包,讓我們開發程式時,不用每次都重新製造輪子,可以站在高手的肩膀上,使用他們開發的套件繼續開發。

但問題來了,套件也可能是依賴其他套件所開發,所以安裝A套件時,必須先安裝B套件,而B套件又可能依賴C套件,所以在安裝套件時,就面臨了套件相依性的問題了。

還記得我們在使用 Ubuntu 時,要安裝甚麼套件,只要下 apt-get install 即可嗎?剩下的 apt-get 都會幫你搞定,而 Composer 就類似 apt-get 一樣,只是 apt-get 是管理 Linux 套件,而 Composer 是管理 PHP 套件。

什麼是Namespace?


由於 PHP 從原本從頭到尾自己打造的開發方式,變成以套件為主的開發方式,面臨了一個很基本的問題 : 若我的 class 名稱與套件內的 class 名稱相衝突怎麼辦?在沒有 namespace 的 PHP 時,只能去改變我們自己的 class 名稱,沒有別的辦法,本來使用套件是為了加速開發,結果卻因為 class 名稱相衝突而問題更大…。

為了解決這個問題,PHP 5.3 提出了 namespace,也就是說,套件可以有自己的 namespace,我們的專案可以有自己的 namespace,只要在 namespace 不相衝突的情況下,class 名稱相衝突是允許的。這就類似台北市可以有博愛路,高雄市也可以有博愛路,雖然都是博愛路 ( class名稱相同 ),但因為分別在台北市與高雄市 ( namespace 不同 ),所以我們仍然可以分辨兩者的不同。

所以建議從現在開始,寫 PHP 一定要搭配 namespace,這樣才可以避免 class 名稱與套件的 class 名稱相衝突的問題。

什麼是ORM?


ORM全名稱為 Object Relational Mapping ,Laravel 提供的 ORM 稱為 Eloquent

寫 PHP 一定要面臨資料庫,傳統 PHP 會使用 SQL 搭配 PDO 去存取資料庫,但這種寫法有一些問題 :

  1. 寫 PHP思考的是 OOP,寫SQL卻要思考 JOIN ,這是兩個完全不同的思考方式。
  2. SQL 的 JOIN 寫法較難理解,與 PHP 一行一行執行的方式不一樣。
  3. SQL 的 JOIN 較難 debug,常常必須在 phpMyAdmin 上一翻兩瞪眼看結果,而無法一行一行的 debug。
  4. 傳統會以湊字串的方式寫 SQL,一不小心很容易造成 SQL Injection 。

而 ORM 就是將 SQL 加以物件導向化,讓我們以習慣的方法與屬性存取資料庫,至於 SQL 呢? ORM 會幫我們組出適當的 SQL 傳到資料庫。

什麼是Migration?


Git 的出現讓我們可以對程式碼加以做版本控制,但資料庫欄位呢? 如今天我們發現資料庫欄位開錯了,想回到幾天前的資料庫欄位狀態呢?

簡單的說,migration 就是幫我們對資料庫欄位做版本控制,由於 migration 是使用 PHP 開發,可以進 git 做版本控管,所以有了 migration,我們也可以輕易的將資料庫欄位回復到某一天的狀態,相當於對資料庫欄位也做了版本管理。

什麼是Blade?


簡單的說,Blade 就是 Laravel 所提供的樣版引擎,它有幾個特點 :

  1. 如網頁有重複的地方,可以使用 blade 的 @extends,類似 PHP 的繼承,將來要修改時就不用每個網頁都修改,只要修改一處即可。
  2. Blade 提供有限的邏輯功能,讓我們可以實現顯示邏輯,而不會讓我們不自覺的寫太多 PHP,而又回到傳統 PHP 的 PHP 與 HTML 混在一起的寫法。

什麼是TDD?


TDD 全名為 Test Driven Development ,是一種先寫測試,然後開發的開發方式,這有幾項優點 :

  1. 由於先寫測試,會使得我們對 Spec 更加了解。
  2. 由於先寫測試,使得將來的重構更有屏障,不用擔心重構將程式改壞掉。
  3. 由於先寫測試,使我們能提早發現程式架構問題,若自己寫的程式連測試都不好寫,表示架構一定不符合 SOLID。

Laravel 是一個支援 TDD 的framework,當你安裝好 Laravel,已經將 PHPUnit、PHPSpec、Mockery…等會用到的套件裝好,且 Laravel 本身也提供很多的 helper function 讓我們更方便測試的 model、view 與 controller。

如何學習Laravel?


  • PHP 書籍 : 不要再看坊間任何 PHP + MySQL 的書了,那種都是教傳統 PHP 的寫法,若真要看 PHP 的書,只推 Modern PHP,作者是 Slim framework 的作者 Josh Lockhart,這本書講的是全新的PHP,使用OOP、PSR、Composer、package、framework、TDD 的開發方式。

  • Laravel 書籍 : 我覺得 Easy Laravel 的可貴之處,在於作者寫作功力很高,能將 Laravel 抽象的概念,一步一步的鋪梗,讓你很輕易的吸收。若你覺得 Laravel 官網文件看不懂,這本書很推薦給初學者。

  • Laravel Dojo : 幫我們很豐富的 Laravel 學習資源,尤其新北市樹林國小Laravel工作坊的 slide 對初學者來說非常完整,當初我也是看這一份 slide 開始學 Laravel。

  • Laracast : Laravel官方教學頻道,初級教學免費,一些中高級課程雖然要收費,但非常值得,尤其很多實戰的例子,可以讓你在最短時間掌握Laravel。

  • Laravel官網 :當你有基礎後,建議將官網資料全部看一遍,官網資料不算 tutorial,但卻是最完整的參考資料。

  • 多參加社團活動 : Laravel台灣PHP也有Day 每個月都有社團活動,兩次是 LaraDiner 讀書會,一次是 PHP也有Day 演講,每個月活動日期會在月初在 Facebook 公告,也歡迎你帶問題來發問,或帶作品來這裡分享。

  • 探索 Laravel 原始碼 : Taylor Otwell 並沒有將所有的功能寫在文件上,有些用法必須直接看原始碼才知道,所幸 Laravel 的原始碼很優美,還可以學習 Taylor 如何寫出符合 SOLID 原則的 PHP。

Conclusion


  • 為了寫出更好的 PHP,一定得付出學習代價,所幸 Laravel 的學習曲線相當平緩,而且參考資料又多,社群非常熱心活躍,相當值得投資。
2015-10-03