1. 程式人生 > >laravel路由、中介軟體、控制器等簡單筆記

laravel路由、中介軟體、控制器等簡單筆記

1.基本路由 - http://laravelacademy.org/post/398.html
	get()
	post()
	put()
	patch()
	delete()
	options()
	match() - ['get', 'post']
	any() - 任意http方法
	路由引數 - 普通引數 {name}
	路由引數 - 可選約束 {name?}
	路由引數 - 正則約束 - {name} + 鏈式where(name)
	路由引數 - 正則約束 - 全域性約束(所有路由都會進行正則約束) - RouteServiceProvider->boot()裡新增 $router->pattern('name', '\w{6}')

2.路由命名和路由分組 - http://laravelacademy.org/post/417.html
	1>路由+路由命名 - as
	2>路由分組+路由命名 - 'as' => 'admin::' + 'as' => 'dashboard' ---> route('admin::dashboard')
	3>路由分組:
		middleware - 中介軟體
		namespace - 名稱空間
		domain - 子域名
		prefix - 路由字首

3.CSRF攻擊 - http://laravelacademy.org/post/525.html
	表單 - 普通token
	ajax - X-CSRF-Token
	cookie - X-XSRF-Token
	從CSRF保護中排除指定URL - VerifyCsrfToken->except 中介軟體

4.路由模型繫結
	Laravel 會自動解析定義在路由或控制器動作(變數名匹配路由片段)中的 Eloquent 模型型別宣告
	Route::get('api/users/{user}', function (App\User $user) {		// $user - 資料庫查詢到的使用者資訊(Eloquent模型類的例項化)
    	return $user->email;
	});

5.表單方法偽造
	表單不支援put、patch、delete方法,新增隱藏欄位 _method

6.中介軟體 - http://laravelacademy.org/post/2803.html
	理解中介軟體的最好方式就是將中介軟體看做 HTTP 請求到達目標動作之前必須經過的“層”,每一層都會檢查請求並且可以完全拒絕它。
	目錄:
		app/Http/Middleware
	定義中介軟體:	
		php artisan make:middleware OldMiddleware
		中介軟體前:
			1>如果我們想在請求處理前執行業務邏輯,則在$next閉包執行前執行業務邏輯操作:
			class BeforeMiddleware
			{
			    public function handle($request, Closure $next)
			    {
			        // 執行業務邏輯操作					// 1.先執行我們自定義邏輯

			        return $next($request); 		// 2.後執行$next()
			    }
			}
		中介軟體後:
			1>如果想要在請求處理後執行中介軟體業務邏輯,則在$next閉包執行後執行操作:
			class AfterMiddleware
			{
			    public function handle($request, Closure $next)
			    {
			        $response = $next($request); 	// 1.先$next()

			        // 執行動作						// 2.執行我們自定義邏輯

			        return $response;				// 3.返回$next()之前的結果
			    }
			}
		我們處理的大部分操作都是第一種場景,即在請求處理前執行操作,比如使用者認證、CSRF驗證、維護模式等都是這樣,但也有用到第二種場景的時候,比如StartSession中介軟體,該中介軟體在請求處理前後都有操作
	註冊中介軟體 - app/Http/Kernel.php:
		全域性中介軟體:
			想要中介軟體在每一個HTTP請求期間被執行,設定 $middleware(1) 陣列即可
		分配中介軟體到路由:
			protected $routeMiddleware(2) = [
			    'auth' => \App\Http\Middleware\Authenticate::class,
			    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
			    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
			    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
			];
			新增到該陣列的元素,就可在路由選項陣列中,呼叫
				Route::get('admin/profile', ['middleware' => 'auth', function () {
				    //
				}]);
			使用陣列分配多箇中間件到路由:
				Route::get('/', ['middleware' => ['first', 'second'], function () {
				    //
				}]);
			除了使用陣列外,還可以使用 middleware 方法鏈的方式定義路由:
				Route::get('/', function () {
				    //
				})->middleware(['first', 'second']);
		中介軟體組:
			protected $middlewareGroups(3) = [
			    'web' => [
			        \App\Http\Middleware\EncryptCookies::class,
			        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
			        \Illuminate\Session\Middleware\StartSession::class,
			        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
			        \App\Http\Middleware\VerifyCsrfToken::class,
			    ],

			    'api' => [
			        'throttle:60,1',
			        'auth:api',
			    ],
			];
			中介軟體組可以被分配給路由和控制器動作,使用和單箇中間件分配同樣的語法。再次申明,中介軟體組的目的只是讓一次分配給路由多箇中間件的實現更加簡單:
				Route::group(['middleware' => ['web']], function () {
				    //
				});
	中介軟體引數:
		class RoleMiddleware
		{
		    public function handle($request, Closure $next, $role) - 該中介軟體,需要一個$role引數
		    {
		        if (! $request->user()->hasRole($role)) {
		            // Redirect...
		        }
		        return $next($request);
		    }
		}
		中介軟體引數可以在定義路由時通過:分隔中介軟體名和引數名來指定,多箇中間件引數可以通過逗號分隔:
		Route::put('post/{id}', ['middleware' => 'role:editor', function ($id) {	// role-中介軟體 & editor-引數值
		    //
		}]);

	可終止的中介軟體:
		中介軟體可能需要在 HTTP 響應傳送到瀏覽器之後做一些工作!例如:Laravel 內建的“session”中介軟體會在響應傳送到瀏覽器之後將 Session 資料寫到儲存器中,為了實現這個,定義一個可終止的中介軟體並新增 terminate 方法到這個中介軟體:
			class StartSession
			{
			    public function handle($request, Closure $next)
			    {
			        return $next($request);
			    }

			    public function terminate($request, $response)		// 終止中介軟體,需要新增 'terminate()',看到沒,可以接收 $response 引數了 --- 表示請求已經發送到了瀏覽器,瀏覽器的響應結果!
			    {
			        // 儲存session資料...
			    }
			}
		這個東西,得解釋下,看了好幾遍才理解了意思:
			1.中介軟體的定義是:HTTP請求到達目標頁面,新增的一些約束層。所以,中介軟體都具有 $request,而不可能出現 $response 響應
			2.終止中介軟體,添加了 terminate() 方法,它就可以接收 $response 響應了。它是在請求已到達了目標後的響應結果
			3.一旦你定義了一個可終止的中介軟體,應該將其加入到 HTTP kernel 的全域性中介軟體列表中 ------- 就是kernel.php中的$middleware陣列
			4.當呼叫中介軟體上的 terminate 方法時,Laravel 將會從服務容器中取出該 '中介軟體的新的例項'(新例項化的中介軟體物件)。並不是之前的 '中介軟體例項化物件'
				如果你想要在呼叫 handle 和 terminate 方法時使用同一個中介軟體例項,則需要使用容器的 singleton 方法將該中介軟體註冊到容器中。
				因為http請求執行過程,肯定是:先執行了 handle(),然後等請求完畢後,再執行 $terminate(),會例項化同一個中介軟體的2個不同的物件。如果想保持同一個物件,就得采用 '單例模式' - 即文件中說的 'singleton()'

7.控制器 - http://laravelacademy.org/post/2816.html & 
	1>簡介:
		將所有的請求處理邏輯都放在 route.php 中是不合理的! ------- route.php是定義路由的,這個我們都清楚!記得路由中是支援 function(){} 匿名函式的,這裡面就是匹配的路由,對應的請求邏輯!(所以,route.php 也是可以進行邏輯程式碼的)
		需要使用controller來管理邏輯,放在 'app/Http/Controllers/' 下,在route.php中,通過 
[email protected]
來定位哪個邏輯 2>基本控制器: class UserController extends Controller { public function showProfile($id) { return view('user.profile', ['user' => User::findOrFail($id)]); } } Route::get('user/{id}', '[email protected]'); // 請求控制器 3>控制器&名稱空間 1.定義控制器路由時,並未指定完整的 '控制器名稱空間',只定義了 'App\Http\Controllers' 之後的 'UserController'。預設情況下: RouteServiceProvider,中定義了一個 $namespace = 'App\Http\Controllers',我們相對它既可! 2.如果控制器目錄下,使用了多層目錄,例如 'App\Http\Controllers\Photos\AdminController',路由呼叫: Route::get('foo', 'Photos\
[email protected]
'); 4>控制器路由,也可以命名(別名) Route::get('foo', ['uses' => '[email protected]', 'as' => 'name']); // 使用as命名一個簡單的名字,重定向&跳轉更簡單 $url = route('name'); // 生成url更加簡單 5>控制器中介軟體: 1)傳統的方式,同匿名函式路由一樣 Route::get('profile', [ 'middleware' => 'auth', // 定義中介軟體,傳統的方式 'uses' => '
[email protected]
' ]); 2)將中介軟體放在 '控制器建構函式' 中,更加方便、靈活。建構函式中使用 middleware() 方法: class UserController extends Controller { public function __construct() { $this->middleware('auth'); // 一般的中介軟體 $this->middleware('log', ['only' => ['fooAction', 'barAction']]); // 中介軟體只能作用於控制器的這些方法 $this->middleware('subscribed', ['except' => ['fooAction', 'barAction']]); // 中介軟體作用於除了這些方法的其它方法 } } 6>RESTful資源控制器 - 可瞭解RESTful,就是所有url都真對的是一個資源處理(百度、google,我也忘記了...) 1)生成 php artisan make:controller PhotoController // 一般的控制器的建立 php artisan make:controller PhotoController --resource // RESTful風格的controller的建立 預設會新增一系列的方法: index, create, store, show, edit, update, destroy 我們可真對這個RESTful資源的一些列方法,進行路由: Route::resource('photo', 'PhotoController'); // 使用resource()方法,而非之前的get(),一個一個來設定(因為它們的標準是同一的) 2)只定義部分資源路由 Route::resource('photo', 'PhotoController', ['only' => ['index', 'show']]); // 指定哪些可用 Route::resource('photo', 'PhotoController', ['except' => ['create', 'store', 'update', 'destroy']]); // 排除哪些可用 3)重新命名資源路由 Route::resource('photo', 'PhotoController', ['names' => ['create' => 'photo.build']]); // 將create重新命名為build 4)覺得預設的RESTful方法,不夠用,我們可以給controller新增更多的方法: Route::get('photos/popular', '[email protected]'); // 如果有必要在預設資源路由之外新增額外的路由到資源控制器,應該在呼叫 Route::resource 之前定義這些路由 Route::resource('photos', 'PhotoController'); 7>依賴注入&控制器 Laravel 使用服務容器解析所有的 Laravel 控制器,因此,可以在控制器的建構函式中型別宣告任何依賴,這些依賴會被自動解析並注入到控制器例項中 1)建構函式注入: use App\Repositories\UserRepository; // 引入依賴類 class UserController extends Controller { protected $users; public function __construct(UserRepository $users) // 將依賴注入到構造方法 { $this->users = $users; } } 2)除了建構函式注入之外,還可以在控制器的動作方法中進行依賴的型別提示 use Illuminate\Http\Request; // 引入依賴類 class UserController extends Controller { public function store(Request $request) // 將依賴注入到普通的方法 { $name = $request->input('name'); // } } 3)方法中,需要傳遞其它引數,引數在其它依賴之後: Route::put('user/{id}', '[email protected]'); // 需要一個引數 use Illuminate\Http\Request; // 引入依賴類 class UserController extends Controller { public function store(Request $request, $id) // 將依賴注入到普通的方法,$id引數在$request引數之後 { $name = $request->input('name'); // } } 8>路由快取: 1)注意: 路由快取不會作用於基於閉包的路由。要使用路由快取,必須將閉包路由轉化為控制器路由。 2)命令: php artisan route:cache // 生成快取 php artisan route:clear // 清除快取 一旦,生成快取,app/Http/routes.php將不在有效,使用快取!一旦修改了routes.php,應該重新生成快取