1. <s id="ykofe"></s>
      <object id="ykofe"><option id="ykofe"></option></object>

      <s id="ykofe"></s>

      Laravel - 為 WEB 藝術家創造的 PHP 框架。

      PHP THAT DOESN'T HURT. CODE HAPPY & ENJOY THE FRESH AIR.

      Laravel logo

      2016 版 Laravel 系列入門教程(二)

      本教程示例代碼見:https://github.com/johnlui/Learn-Laravel-5

      在任何地方卡住,最快的辦法就是去看示例代碼。

      本篇文章中,我將跟寶寶們一起學習 Laravel 框架最重要的部分——路由系統。

      如果你讀過舊的基于 Laravel 5.0 版本的此教程,你會發現那篇文章里大書特書的 Auth 系統構建已經被 Laravel 捎帶手給解決了。在更早的 Laravel 4 版本的教程中,實際上我是通過讓大家自己動手構建高難度的 Auth 系統來提高短期學習曲線的斜率,以便寶寶們能更快地感受到 Laravel 運行的原理。但是很遺憾,現在的 Auth 系統實在是太強大了,執行幾句命令就激活了這個功能,新手其實還是云里霧里。為了彌補這個缺憾,本寶寶決定赤膊上陣,手刃路由系統,直接給大家展示 Laravel 是如何組織 MVC 架構,來控制網站運行的。

      初識路由

      路由系統是所有 PHP 框架的核心,路由承載的是 URL 到代碼片段的映射,不同的框架所附帶的路由系統是這個框架本質最真實的寫照,一絲不掛,一覽無余。Laravel 路由中文文檔:http://laravel-china.org/docs/5.1/routing

      Laravel 5 之后就把路由放到了 learnlaravel5/app/Http/routes.php 這個位置,我們先看一下目前路由中僅存的幾行代碼:

      Route::get('/', function () {
          return view('welcome');
      });
      
      Route::auth();
      
      Route::get('/home', 'HomeController@index');
      

      中間的一行代碼 Route::auth(); 就是 Auth 系統自動注入的路由配置,我們不用深究,我們的注意力主要集中頭三行和最后一行代碼上。

      命名空間

      本寶寶一直認為 Laravel 5 除了性能大幅提升之外相對于 4 最大的進步就在于新的命名空間規劃:更清晰,更合理,更有利于新手。

      Laravel 4 失敗的簡潔

      Laravel 4 時代,大量的代碼都運行在根命名空間下,路由、Controller、Model 等等。看起來這么做可以少寫幾行枯燥的 use xxxx;,實則是對于命名空間的誤使用,而且對于新手學習命名空間是有毒的。

      絕對類名

      Laravel 5 全面引入了 psr-4 命名空間標準:命名空間和實際文件所在的文件夾層級一致,文件夾首字母大寫即為此文件的約定命名空間。舉個小栗子:learnlaravel5/app/Http/Controllers/HomeController.php 的絕對類名為:\App\Http\Controllers\HomeControllerlearnlaravel5/app/User.php 的絕對類名為:\App\User

      “絕對類名”是本寶寶自創的:在啟用了命名空間的系統中,子命名空間下的類有一個全局都可以直接訪問的名稱,這個名稱就是該類的命名空間全稱。雖然命名空間在“實用主義”的 PHP 語言里看起來十分古怪,不過他也還是 PHP 嘛,依然遵循 PHP 的運行原理和哲學。同理,Laravel 無論多么強大,他都是 PHP 代碼寫成的,所以當你苦于 Laravel 沒有提供某個你需要的功能時,不要驚慌不要著急,just write the code in the PHP way。

      psr-4 的官方英文文檔在這里:http://www.php-fig.org/psr/psr-4/

      好用的資料

      命名空間其實沒什么特別難的地方,我曾經寫過一篇文章專門扒光命名空間的秘密:《PHP 命名空間 解惑 》

      基礎路由解析

      閉包路由

      路由文件中前三行即為閉包路由:

      Route::get('/', function () {
          return view('welcome');
      });
      

      閉包路由使用閉包作為此條請求的響應代碼,方便靈活,很多簡單操作直接在閉包里解決即可。例如“輸出服務器當前時間”:

      Route::get('now', function () {
          return date("Y-m-d H:i:s");
      });
      

      如果你想得到北京時間,請在 learnlaravel5/config/app.php 第 55 行左右把 timezone 設置為上海:

      'timezone' => 'Asia/Shanghai',
      

      這時候訪問 http://fuck.io:1024/now 可以得到如下結果:

      控制器@方法 路由

      閉包路由雖然靈活強大,不過大多數場景下我們還是需要回歸到 MVC 架構的:

      Route::get('/home', 'HomeController@index');
      

      這行路由代碼的意思想必大家都能猜到一二了:當以 GET 方法訪問 http://fuck.io:1024/home 的時候,調用 HomeController 控制器中的 index 方法(函數)。同理,你可以使用 Route::post('/home', 'HomeController@indexPost'); 響應 POST 方法的請求。

      控制器@方法 調用原理淺析

      Laravel 的路由跟所有 PHP 框架的路由一樣,都是用的最簡單直接的 PHP 方式來調用控制器中的方法的:使用字符串初始化類得到對象,調用對象的指定方法,返回結果。下面我簡單羅列幾步對 Laravel 路由調用過程的探測,感興趣的話可以自己研究。

      learnlaravel5/app/Providers/RouteServiceProvider.php

      全局搜索 routes.php,我們找到了這個文件。此文件最后的 mapWebRoutes 方法,給所有的路由同意加進了一個路由組,定義了一個命名空間和一個中間件:

      protected function mapWebRoutes(Router $router)
      {
          $router->group([
              'namespace' => $this->namespace, 'middleware' => 'web',
          ], function ($router) {
              require app_path('Http/routes.php');
          });
      }
      

      順著這個函數往上看,你會發現命名空間定義的地方:

      protected $namespace = 'App\Http\Controllers';
      

      之后命名空間、類、方法是如何傳遞的呢?

      learnlaravel5/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php

      經過簡單的追蹤,我們找到了這個文件。讓我們在 dispatch 方法中增加一行 var_dump($controller);,刷新就可以看到頁面上如下的輸出:

      這就是我們要調用的控制器類的“絕對類名”。

      最后一步

      Laravel 使用了完整的面向對象程序架構,對控制器的調用進行了超多層封裝,所以最簡單地探測方式其實是手動拋出錯誤,這樣就可以看到完整的調用棧:

      在 HomeController 的 index 方法里的 return 之前增加一行 throw new \Exception("我故意的", 1);,刷新頁面,你將看到以下畫面:

      我們可以看到,是 learnlaravel5/vendor/laravel/framework/src/Illuminate/Routing/Controller.php 第 80 行最終驅動起了 HomeController:

      public function callAction($method, $parameters)
      {
          return call_user_func_array([$this, $method], $parameters);
      }
      

      具體的細節不再詳解,寶寶如果感興趣的話,把這些方法一個一個地都看一遍吧,相信對于你理解 Laravel 運行原理很有幫助。其實 PHP 跟字符串結合的緊密程度已經緊逼 js 和 JSON 了。結尾分享一個小彩蛋:這個laravel路由怎么寫?


      原文:https://github.com/johnlui/Learn-Laravel-5/issues/5


      關于作者 JohnLui
      PHP 框架 TinyLara 作者。
      国模吧私拍