Creating yii2 dynamic pages with url: www.example.com/pageName

bla*_*boy 5 php url seo routing yii2

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
Run Code Online (Sandbox Code Playgroud)

如何在yii2中实现这些URL?这些John-Doe和Mary-Smith可以是用户用户名或配置文件名.例如,我在用户表中有一个名为"name"的字段,它将包含名称"John Doe","Mary Smith".注意我需要SEO友好的URL与" - "而不是空格.

像这样的网址:www.example.com/profile/view?id = 1不是一个选项.

aro*_*hev 9

www.example.com/John-Doe

www.example.com/Mary-Smith
Run Code Online (Sandbox Code Playgroud)

我认为没有正常的方法来使用这些网址,因为首先ProfileController需要确定控制器(在你的情况下).从这些网址来看,这是不可能的.

您提供的网址存在第二个问题 - 无法保证唯一性.如果有其他名字的用户John Doe会在网站上注册怎么办?

例如,在Stack Overflow的配置文件链接中查找:

http://stackoverflow.com/users/4395794/black-room-boy
Run Code Online (Sandbox Code Playgroud)

它不是http://stackoverflow.com/black-room-boy,甚至不是http://stackoverflow.com/users/black-room-boy.

结合id并且name是更广泛和更健全的方法.他们也可以像这样结合破折号:http://stackoverflow.com/users/4395794-black-room-boy

Yii 2具有内置的行为,它被称为SluggableBehavior.

将它附加到您的模型:

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',
        ],
    ];
}
Run Code Online (Sandbox Code Playgroud)

对于您的特定网址格式,您还可以指定$value:

'value' => function ($event) {
    return str_replace(' ', '-', $this->name);
}
Run Code Online (Sandbox Code Playgroud)

这只是生成自定义slug的一个示例.name保存之前,请根据属性功能和验证/过滤进行更正.

实现唯一URL的另一种方法是将$ ensureUnique属性设置为true.

所以在的情况下,John-Doe存在性John-Doe-1蛞蝓将产生等.

请注意,您还可以通过设置$ uniqueSlugGenerator callable 来指定您自己的唯一生成器.

我个人不喜欢这种方法.

如果您选择类似于Stack Overflow使用的选项,请将其添加到您的网址规则中:

'profile/<id:\d+>/<slug:[-a-zA-Z]+>' => 'profile/view',
Run Code Online (Sandbox Code Playgroud)

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.');
    }
}
Run Code Online (Sandbox Code Playgroud)

但实际上id足以找到用户.如果您使用正确id但不同的访问权限,Stack Overflow会重定向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.');
    }
}
Run Code Online (Sandbox Code Playgroud)

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]]);
    }
}
Run Code Online (Sandbox Code Playgroud)