Yii2 uniqueSlugGenerator [дубликат]

У меня была аналогичная проблема, но в моем случае решение было другим. мой файл, который содержал php-код, назывался «somename.html», изменил его на «somename.php», работал отлично

5
задан black-room-boy 16 January 2015 в 18:23
поделиться

1 ответ

www.example.com/John-Doe

www.example.com/Mary-Smith

Я думаю, что нет нормального способа использования этих URL-адресов, потому что сначала необходимо определить контроллер (в вашем случае это ProfileController). Из этих URL-адресов это невозможно сделать.

Вторая проблема с указанными вами адресами - уникальность не гарантируется. Что делать, если на сайте будет зарегистрирован другой пользователь с именем 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 и 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',
        ],
    ];
}

Для вашего конкретного формата URL-адреса вы также можете указать $value:

'value' => function ($event) {
    return str_replace(' ', '-', $this->name);
}

Это всего лишь пример создания пользовательского пула. Исправьте его в соответствии с вашими атрибутами атрибута name и проверкой / фильтрацией перед сохранением.

Другой способ достижения уникального URL-адреса - установить свойство $equUnique на true.

Таким образом, в случае John-Doe existense John-Doe-1 будет генерироваться slug и т. д.

Обратите внимание, что вы также можете указать свой собственный уникальный генератор, установив $ uniqueSlugGenerator ] callable.

Лично мне не нравится этот подход.

Если вы выберете вариант, аналогичный тому, что использует Stack Overflow, добавьте это в свои правила URL:

'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. Переадресация происходит, когда вы также полностью пропускаете имя.

Например, 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.');
    }
}

И 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]]);
    }
}
9
ответ дан arogachev 22 August 2018 в 04:59
поделиться
  • 1
    Большое спасибо! Но что, если я хочу найти пользователя по его id + или просто id, но я не хочу отображать id в URL-адресе, я хочу отображать только имя. Возможно ли это с помощью slug или пользовательских правил urlManager? – black-room-boy 16 January 2015 в 20:02
  • 2
    Это возможно с такими пулями, как «John-Doe-1» (приращение) или «John-Doe-255» / «255-John-Doe». (Я бы). Укажите $ secureUnique и $ uniqueSlugGenerator (в случае объединения с идентификаторами) в SluggableBehavior. Затем измените findModel, чтобы найти по slug и действия, чтобы получить $ slug как параметр get. – arogachev 16 January 2015 в 20:05
  • 3
    Вы хотите изменить строку findModel и viewAction в коде exmple (Контроллер профиля)? – black-room-boy 16 January 2015 в 20:15
  • 4
    Да. С URL-адресами, такими как «John-Doe» в случае использования нескольких пользователей с таким же именем при поиске модели с помощью findOne (), не гарантируется, что модель результата содержит желаемого пользователя. – arogachev 16 January 2015 в 20:22
  • 5
    Хороший ответ! есть ли способ сопоставления статических страниц, таких как «политика конфиденциальности» с методом contentControllers content () с передачей 2 или любым числовым параметром? Моя идея - извлечь контент из db с этим идентификатором. – RN Kushwaha 4 October 2015 в 14:36
Другие вопросы по тегам:

Похожие вопросы: