如何使用 PHP 和 Laravel 使用唯一 ID 加冗余信息 (UPRI) 制作更易读的 URI
How to make morre readable URIs using unique-id-plus-redundant-information (UPRI) using PHP with Laravel
我想知道将冗余位添加到我的 restful uris 的最佳(也是最一致的)方法,以便它们更具可读性,同时在用户名等某些内容发生变化时保持不变。
我在 this excellent blog post 上读到了这个概念,它类似于堆栈溢出 /users/3836923/inkalimeva
URI 的最后一段是多余的并且可能会更改,但会使 URI 更具可读性和 SEO友好。
目前我正在使用 Laravel 的 Route::resource()
但创建的路由仅包含 id 段。
您可以使用 eloquent-sluggable 为您的用户创建 slug。这样当他们更新用户名时,slug 就会改变。您也可以简单地在 url 方法中调用他们的用户名,尽管这会导致更难看的 urls.
此方法仍然需要您删除 Route::resource() 并显式编写您的路线。
这是代码,经过测试并且可以工作:
ROUTES.PHP(不介意路线详情)
Route::get('route-name/{id}/{slugOrUsernameAsYouPlease}', [
'as' => 'admin-confirm-detach-admin',
'uses' => 'AdminController@confirmDetachAdmin'
]);
在你看来
<a href="{{ url('route-name/'. $user->id . '/' . $user->name) }}">Click me!</a>
或
<a href="{{ url('route-name/'. $user->id . '/' . $user->slug) }}">Click me!</a>
URL 结果 (我的用户名是 Fnup。仅供测试)
用户名:http://website.local/route-name/8/Fnup
有鼻涕虫:http://website.local/route-name/8/fnup
最后的简短说明
我刚刚将 fnup 的用户名更改为 fnupper,结果如下:
http://website.local/route-name/8/Fnupper
但是 slug 并没有自动改变。您必须自己将该代码添加到用户更新方法中。否则,该 slug 将保持第一次创建资源时的状态。这是我使用 eloquent-sluggable
时的代码
public function update(UpdateUserRequest $request)
{
$user = \Auth::user();
$user->name = $request->name;
$user->email = $request->email;
$user->resluggify();
$user->save();
session()->flash('message', 'Din profil er opdateret!');
return redirect()->route('user-show');
}
这导致:http://website.local/route-name/8/fnupper
每个请求的新编辑:控制器方法示例
这是我在 AdminController.php
中的 confirmDetachAdmin()
方法。澄清一下,方法的工作是在修改用户状态之前显示 "confirm" 视图。就像 edit/update 和 create/store 一样,我弥补了伴随销毁的确认(因为我想要 javascript 免费确认选项应该 javascript 被禁用)。
public function confirmAttachAdmin($id)
{
$user = User::findOrFail($id);
/* Prevent error if user already has role */
if ( $user->hasRole('admin')) {
return redirect()->back();
}
return view('admin.confirmAttachAdmin', compact('user'));
}
如果你愿意,你可以添加你的 slug/username 作为第二个参数,但我没有看到原因,因为当你通过 id 找到它们时,你可以从 $user 访问它。
与@MartinJH 的回答相反,如果您在 URI 中不依赖 only,我认为您不应该将 slug 存储在数据库中。在你的模型上一个简单的 link()
方法,一个明确的路线就足够了。
App\User
class User extends \Illuminate\Database\Eloquent\Model {
public function link()
{
return route('user-profile', [ $this->id, Str::slug($this->username) ]);
}
}
routes.php
Route::get('{id}/{username}', [ 'as' => 'user-profile', 'uses' => 'UserController@profile' ])
->where('id', '\d+')
->where('username', '[a-zA-Z0-9\-\_]+');
App\Http\Controllers\UserController
...
public function profile($id, $username)
{
$user = \App\User::findOrFail($id);
return view('profile')->with('user', $user);
}
...
我想知道将冗余位添加到我的 restful uris 的最佳(也是最一致的)方法,以便它们更具可读性,同时在用户名等某些内容发生变化时保持不变。
我在 this excellent blog post 上读到了这个概念,它类似于堆栈溢出 /users/3836923/inkalimeva
URI 的最后一段是多余的并且可能会更改,但会使 URI 更具可读性和 SEO友好。
目前我正在使用 Laravel 的 Route::resource()
但创建的路由仅包含 id 段。
您可以使用 eloquent-sluggable 为您的用户创建 slug。这样当他们更新用户名时,slug 就会改变。您也可以简单地在 url 方法中调用他们的用户名,尽管这会导致更难看的 urls.
此方法仍然需要您删除 Route::resource() 并显式编写您的路线。
这是代码,经过测试并且可以工作:
ROUTES.PHP(不介意路线详情)
Route::get('route-name/{id}/{slugOrUsernameAsYouPlease}', [
'as' => 'admin-confirm-detach-admin',
'uses' => 'AdminController@confirmDetachAdmin'
]);
在你看来
<a href="{{ url('route-name/'. $user->id . '/' . $user->name) }}">Click me!</a>
或
<a href="{{ url('route-name/'. $user->id . '/' . $user->slug) }}">Click me!</a>
URL 结果 (我的用户名是 Fnup。仅供测试)
用户名:http://website.local/route-name/8/Fnup
有鼻涕虫:http://website.local/route-name/8/fnup
最后的简短说明
我刚刚将 fnup 的用户名更改为 fnupper,结果如下:
http://website.local/route-name/8/Fnupper
但是 slug 并没有自动改变。您必须自己将该代码添加到用户更新方法中。否则,该 slug 将保持第一次创建资源时的状态。这是我使用 eloquent-sluggable
时的代码public function update(UpdateUserRequest $request)
{
$user = \Auth::user();
$user->name = $request->name;
$user->email = $request->email;
$user->resluggify();
$user->save();
session()->flash('message', 'Din profil er opdateret!');
return redirect()->route('user-show');
}
这导致:http://website.local/route-name/8/fnupper
每个请求的新编辑:控制器方法示例
这是我在 AdminController.php
中的 confirmDetachAdmin()
方法。澄清一下,方法的工作是在修改用户状态之前显示 "confirm" 视图。就像 edit/update 和 create/store 一样,我弥补了伴随销毁的确认(因为我想要 javascript 免费确认选项应该 javascript 被禁用)。
public function confirmAttachAdmin($id)
{
$user = User::findOrFail($id);
/* Prevent error if user already has role */
if ( $user->hasRole('admin')) {
return redirect()->back();
}
return view('admin.confirmAttachAdmin', compact('user'));
}
如果你愿意,你可以添加你的 slug/username 作为第二个参数,但我没有看到原因,因为当你通过 id 找到它们时,你可以从 $user 访问它。
与@MartinJH 的回答相反,如果您在 URI 中不依赖 only,我认为您不应该将 slug 存储在数据库中。在你的模型上一个简单的 link()
方法,一个明确的路线就足够了。
App\User
class User extends \Illuminate\Database\Eloquent\Model {
public function link()
{
return route('user-profile', [ $this->id, Str::slug($this->username) ]);
}
}
routes.php
Route::get('{id}/{username}', [ 'as' => 'user-profile', 'uses' => 'UserController@profile' ])
->where('id', '\d+')
->where('username', '[a-zA-Z0-9\-\_]+');
App\Http\Controllers\UserController
...
public function profile($id, $username)
{
$user = \App\User::findOrFail($id);
return view('profile')->with('user', $user);
}
...