Создание динамических страниц yii2 с URL: www.example.com/pageName

В моей системе пользователи должны иметь свои страницы профиля. Мне просили, чтобы эти страницы отображались в URL-адресе:

www.example.com/John-Doe www.example.com/Mary-Smith 

Как достичь этих URL-адресов в yii2? Эти John-Doe и Mary-Smith могут быть именами пользователей или именами пользователей. Например, у меня есть поле в пользовательской таблице с именем «имя», и в нем будут имена «Джон Доу», «Мэри Смит». Обратите внимание, что мне нужны дружественные URL-адреса для SEO с «-» вместо пробелов.

Такие URL-адреса: www.example.com/profile/view?id=1 не являются вариантом.

Related of "Создание динамических страниц yii2 с URL: www.example.com/pageName"

 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- адреса – установить свойство $ makeUnique в true .

Таким образом, в случае существования John-Doe Доэ, будет сформирован пул John-Doe-1 и т. Д.

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

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

Если вы выберете вариант, похожий на то, что использует 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 достаточно, чтобы найти пользователя. 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.'); } } 

И 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]]); } }