網絡資源訪問,路由是多麼重要不消多言了。而友好的url地址更是能讓人一目了然,增加用戶的好感。同時對於爬蟲也是好的示例,搜尋引擎可以友好地展開工作了。
本文就來講講,如何在laravel中構造友好的url路由。
在早期的網際網路時代,為了在頁面之間傳遞數據,複雜的交互一般都會使用cookie等本地緩存,但是瀏覽器版本的約束,使得伺服器端交互仍然需要即時訪問。所以各種各樣的url地址,帶參數跳轉的,表單提交的,混為一談,製作出符合統一規範的路由很不容易。
比如下面的路由,訪問一個地址,並且攜帶querystring參數:
http://example.com/events.php?id=42
相應地,不同的用戶,這個id也不相同。不同的頁面,也不相同。像這樣帶參傳遞的路由地址,是最為原始的。我們在之前的章節已經使用laravel Route功能,重新構造了url,所以訪問起來像是連貫的:
http://example.com/events/42
直接使用位置參數綁定的方式傳遞。因為數字42對用戶而言沒有實際意義,而對資料庫來說是索引欄位。如果使用如下方式,效果要友好的多:
http://example.com/events/laravel-hacking-and-coffee
這種基於字符串位置參數綁定的URL方式,被稱為 slug。有一個第三方類庫專門用於url的友好化。使用 composer 安裝:
composer require cviebrock/eloquent-sluggable:^4.3
引入 eloquent-sluggable 類庫,只需要在laravel模型文件內引入對應trait,並重載實現sluggable方法:
use Cviebrock\EloquentSluggable\Sluggable;class Event extends Model { use Sluggable; public function sluggable() { return [ 'slug' => [ 'source' => 'name' ] ]; }}
上述 sluggable 方法指定了,哪個欄位用於slug搜索,(此處是 slug)。以及slug欄位對應的資料庫表的欄位來源,此處是 name 欄位。
接著我們需要修改 events 表,為其追加 slug 欄位。命令行創建遷移文件:
php artisan make:migration add_slug_column_to_events_table --table=events
執行成功返回:
Created Migration: 2020_10_04_225240_add_slug_column_to_events_table
然後手動實現遷移文件的 up 方法:
public function up(){ Schema::table('events', function (Blueprint $table) { $table->string('slug')->nullable(); });}
以及回滾使用的 down 方法:
public function down(){ Schema::table('events', function (Blueprint $table) { $table->dropColumn('slug'); });}
在命令行執行遷移成功後,資料庫表events就會追加上slug欄位了。
如果原來資料庫表內已經又生產數據,此時我們需要手動更新一下。使用 tinker 快捷操作:
namespace App;$events = Event::all();foreach($events as $event) { $event->save();}
數據量不大,我們也不考慮效率不效率的問題了。foreach循環直接用了。
資料庫準備好了,模型準備好了,現在讓我們把slug功能用起來。
如果你有印象的話,應該會記得laravel模型的find等方法,是基於primary key進行索引,以便加快查詢速度。拿到模型的ID,查詢該條目數據,然後返回模型實例。這是基於ID這個integer類型的查詢。
而slug查詢,是基於字符串的,如果要使用slug此功能,需要改寫默認的列名。在模型文件內手動重寫如下方法:
public function getRouteKeyName(){ return 'slug';}
返回字符串,就是查詢所依據的「欄位名」。這樣默認的查詢就不走默認的 $primaryKey = 'id' 這個欄位,而是使用手動指定的 slug欄位了。
當然了,如果沒有使用路由參數綁定,eloquent-sluggable類庫也為我們提供了友好的trait,在模型文件內直接引入就好了:
use Cviebrock\EloquentSluggable\Sluggable;use Cviebrock\EloquentSluggable\SluggableScopeHelpers;class Event extends Model{ use Sluggable, SluggableScopeHelpers;}
從名字你就能猜測的到,SluggableScopeHelpers 是一個全局作用域文件,這是我們上一章所講內容,不再贅述。
完成引入後,在使用模型進行查詢時,就可以這樣使用了:
$event = Event::findBySlug('laravel-hacking-and-coffee');$event = Event::findBySlugOrFail('laravel-hacking-and-coffee');
歸根結底,就是使用slug欄位記錄查詢的字符串,而slug欄位在對應關係中定義為 source => 『name』 欄位,所以SQL查詢仍然是根據slug欄位嚴格匹配約束返回數據集。
數據量大了之後,這種等於的WHERE子句性能必然不如ID欄位的主鍵索引來的快。所以在資料庫層面也同樣需要優化。
寫在最後
本文介紹了在模型文件內,引入slug的功能,並通過修改模型的查詢方式,讓模型的默認查詢方式修改為通過字符串進行查詢,從而可以在路由文件內構造更友好的查詢url。
Happy coding :-)
我是@程式設計師小助手,專注編程知識,圈子動態的IT領域原創作者