У меня была аналогичная проблема, но в моем случае решение было другим. мой файл, который содержал php-код, назывался «somename.html», изменил его на «somename.php», работал отлично
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]]);
}
}