引言
網路資源訪問,路由是多麼重要不消多言了。而友好的url地址更是能讓人一目瞭然,增加使用者的好感。同時對於爬蟲也是好的示例,搜尋引擎可以友好地展開工作了。
本文就來講講,如何在laravel中構造友好的url路由。
啥是slug?
在早期的網際網路時代,為了在頁面之間傳遞資料,複雜的互動一般都會使用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
模型引入 Slug 功能
引入 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 的模型查詢
資料庫準備好了,模型準備好了,現在讓我們把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領域原創作者
本作品採用《CC 協議》,轉載必須註明作者和本文連結