使用 url 创建 yii2 动态页面:www.example.com/pageName
在我的系统中,用户需要有他们的个人资料页面.我要求这些页面将显示在 url 中,如下所示:
In my system, users need to have their profile pages. It is requested from me that these pages will be displayed in url like this:
www.example.com/John-Doe
www.example.com/Mary-Smith
如何在 yii2 中实现这些 URL?这些 John-Doe 和 Mary-Smith 可以是用户用户名或个人资料名称.例如,我在用户表中有一个名为name"的字段,它将保存名称John Doe"、Mary Smith".请注意,我需要带有-"而不是空格的 SEO 友好 URL.
How to achieve these URLs in yii2 ? These John-Doe and Mary-Smith can be user usernames or profile names. For example I have field in user table called "name" and it will hold names "John Doe", "Mary Smith". Pay attention that I need SEO friendly URLs with "-" instead of blank spaces.
像这样的网址:www.example.com/profile/view?id=1不是一个选项.
URLs like this: www.example.com/profile/view?id=1 are not an option.
推荐答案
www.example.com/John-Doe
www.example.com/Mary-Smith
我认为没有使用这些 url 的正常方法,因为首先需要确定控制器(在您的情况下是 ProfileController
).从这些网址是不可能做到的.
I think there is no normal way to use these urls because at first controller (in your case it's ProfileController
) needs to be determined. From these urls it's impossible to do.
您提供的网址的第二个问题 - 不保证唯一性.如果另一个名为 John Doe
的用户在网站上注册会怎样?
Second problem with the urls you provided - uniqueness is not guaranteed. What if another user with name John Doe
will sign up on site?
以您在 Stack Overflow 上的个人资料链接为例:
Look for example at your profile link at Stack Overflow:
http://stackoverflow.com/users/4395794/black-room-boy
它不是 http://stackoverflow.com/black-room-boy
甚至不是 http://stackoverflow.com/users/black-room-boy
.
It's not http://stackoverflow.com/black-room-boy
and not even http://stackoverflow.com/users/black-room-boy
.
结合 id
和 name
是更广泛和更强大的方法.它们也可以像这样与破折号结合使用:http://stackoverflow.com/users/4395794-black-room-boy
Combining id
and name
is more widespread and robust approach. Also they can be combined with dash like this: http://stackoverflow.com/users/4395794-black-room-boy
Yii 2 为此具有内置行为,称为 SluggableBehavior.
Yii 2 has built-in behavior for this, it's called SluggableBehavior.
将其附加到您的模型:
use yiiehaviorsSluggableBehavior;
public function behaviors()
{
return [
[
'class' => SluggableBehavior::className(),
'attribute' => 'name',
// In case of attribute that contains slug has different name
// 'slugAttribute' => 'alias',
],
];
}
对于您的特定 url 格式,您还可以指定 $value
:
For your specific url format you can also specify $value
:
'value' => function ($event) {
return str_replace(' ', '-', $this->name);
}
这只是生成自定义 slug 的示例.保存前根据您的 name
属性特征和验证/过滤进行更正.
This is just an example of generating custom slug. Correct it according to your name
attribute features and validation / filtering before save.
实现唯一网址的另一种方法是设置 $ensureUnique属性为 true
.
Another way of achieving unique url is setting $ensureUnique property to true
.
所以如果 John-Doe
存在 John-Doe-1
slug 将被生成等等.
So in case of John-Doe
existense John-Doe-1
slug will be generated and so on.
请注意,您还可以通过设置 $uniqueSlugGenerator 来指定自己的唯一生成器 可调用.
Note that you can also specify your own unique generator by setting $uniqueSlugGenerator callable.
我个人不喜欢这种方法.
Personally I don't like this approach.
如果您选择的选项类似于 Stack Overflow 使用的选项,请将其添加到您的 url 规则中:
If you choose the option similar to what Stack Overflow uses, then add this to your url rules:
'profile/<id:d+>/<slug:[-a-zA-Z]+>' => 'profile/view',
在 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
足以找到用户.如果您使用正确的 id
但不同的 slug
访问,则堆栈溢出会重定向.当您也完全跳过名称时会发生重定向.
But actually id
is enough to find user. Stack Overflow does redirect if you access with correct id
but different slug
. The redirects occurs when you are completely skipping the name too.
例如 http://stackoverflow.com/users/4395794/black-room-bo
重定向到原始页面 http://stackoverflow.com/users/4395794/black-room-boy
以避免内容重复,这对 SEO 来说是不受欢迎的.
For example http://stackoverflow.com/users/4395794/black-room-bo
redirects to original page http://stackoverflow.com/users/4395794/black-room-boy
to avoid content duplicates that are undesirable for SEO.
如果您也想使用它,请像这样修改 findModel()
方法:
If you want use this as well, modify findModel()
method like so:
protected function findModel($id)
{
if (($model = User::findOne($id) !== null) {
return $model;
} else {
throw new NotFoundHttpException('User was not found.');
}
}
和 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]]);
}
}
相关文章