www.example.com/John-Doe
www.example.com/Mary-Smith
我认为没有正常的方法来使用这些网址,因为首先控制器(在你的情况下它是ProfileController
)需要确定。从这些网址来看这是不可能的。
您提供的网址的第二个问题 - 无法保证唯一性。如果另一个用户同名怎么办John Doe
会现场报名吗?
例如,查看您在 Stack Overflow 上的个人资料链接:
http://stackoverflow.com/users/4395794/black-room-boy
它不是http://stackoverflow.com/black-room-boy
甚至没有http://stackoverflow.com/users/black-room-boy
.
组合id
and name
是更广泛、更稳健的方法。它们也可以与破折号结合使用,如下所示:http://stackoverflow.com/users/4395794-black-room-boy
Yii 2 有内置的行为,称为Sluggable行为 http://www.yiiframework.com/doc-2.0/yii-behaviors-sluggablebehavior.html.
将其附加到您的模型:
use yii\behaviors\SluggableBehavior;
public function behaviors()
{
return [
[
'class' => SluggableBehavior::className(),
'attribute' => 'name',
// In case of attribute that contains slug has different name
// 'slugAttribute' => 'alias',
],
];
}
对于您的特定网址格式,您还可以指定$value
:
'value' => function ($event) {
return str_replace(' ', '-', $this->name);
}
这只是生成自定义 slug 的示例。根据你的情况改正name
保存前的属性特征和验证/过滤。
另一种实现唯一 url 的方法是设置$ensureUnique http://www.yiiframework.com/doc-2.0/yii-behaviors-sluggablebehavior.html#%24ensureUnique-detail财产给true
.
所以如果是John-Doe
存在John-Doe-1
会生成slug等等。
请注意,您还可以通过设置来指定自己独特的生成器$uniqueSlugGenerator http://www.yiiframework.com/doc-2.0/yii-behaviors-sluggablebehavior.html#%24uniqueSlugGenerator-detail可调用。
我个人不喜欢这种方法。
如果您选择与 Stack Overflow 使用的选项类似的选项,请将其添加到您的 url 规则中:
'profile/<id:\d+>/<slug:[-a-zA-Z]+>' => 'profile/view',
In ProfileController
:
public function actionView($id, $slug)
{
$model = $this->findModel($id, $slug);
...
}
protected function findModel($id, $slug)
{
if (($model = User::findOne(['id' => $id, 'name' => $slug]) !== null) {
return $model;
} else {
throw new NotFoundHttpException('User was not found.');
}
}
但实际上id
足以找到用户。如果您使用正确的方式访问,Stack Overflow 会重定向id
但不同slug
。当您也完全跳过名称时,就会发生重定向。
例如http://stackoverflow.com/users/4395794/black-room-bo
重定向到原始页面http://stackoverflow.com/users/4395794/black-room-boy
以避免 SEO 不希望出现的内容重复。
如果你也想使用这个,请修改findModel()
像这样的方法:
protected function findModel($id)
{
if (($model = User::findOne($id) !== null) {
return $model;
} else {
throw new NotFoundHttpException('User was not found.');
}
}
And actionView()
像这样:
public function actionView($id, $slug = null)
{
$model = $this->findModel($id);
if ($slug != $model->slug) {
return $this->redirect(['profile/view', ['id' => $id, 'slug' => $model->slug]]);
}
}