Псевдонимы записей в Yii2. Создание и управление

Настройка ЧПУ – неотъемлемый атрибут работы по SEO-оптимизации любого сайта. Формировать URL только по id записи – не лучший вариант.

В данном уроке мы добавим псевдонимы записей (слаг/алиас) для постов блога.

Суть такова. В форме (создания, редактирования) поста есть текстовове поле, в которое мы можем прописать свой собственный slug и при этом оно должно валидироваться. Если мы оставим поле пустым, то Yii2 сам сделает эту работу методом Inflector::slug(), куда мы передадим название поста (то есть, по умолчанию слаг будет транслитом названия поста). В базе данных поле slug обязательно для заполнения (NOT NULL) и является уникальным.

Добавим в базу данных поле slug (если его не было изначально). Пример добавления поля через миграцию:


 
  1. // Из консоли
  2. php yii migrate/create add_post_field_slug

В созданной миграции:


 
  1. public function safeUp()
  2. {
  3. $this->addColumn('{{%post}}', 'slug', $this->string(255)->notNull()->after('status')->unique());
  4. $this->createIndex('{{%idx-post-slug}}', '{{%post}}', 'slug', true);
  5. }
  6.  
  7. public function safeDown()
  8. {
  9. $this->dropColumn('{{%post}}', 'slug');
  10. }

В форме (backend\views\post\_form.php) добавим поле:


 
  1. <?= $form->field($model, 'slug')->textInput(['maxlength' => true]) ?>

В модель Post добавляем следующий код:


 
  1.  
  2. private $_post;
  3.  
  4. public function rules()
  5. {
  6. return [
  7. [['name'], 'required'], // На стороне клиента "slug" необязательный
  8. [['name', 'slug'], 'string', 'max' => 255], // "slug" - ограниченная строка
  9. ['slug', SlugValidator::class], // "slug" валидируется классом SlugValidator
  10. // "name" и "slug" - уникальны (фильтр по ID поста при редактировании)
  11. [['name', 'slug'], 'unique', 'targetClass' => Post::class, 'filter' => $this->_post ? ['<>', 'id', $this->_post->id] : null]
  12. ];
  13. }

Класс SlugValidator:


 
  1. <?php
  2.  
  3. namespace common\models\validators;
  4.  
  5. use yii\validators\RegularExpressionValidator;
  6.  
  7. class SlugValidator extends RegularExpressionValidator
  8. {
  9. public $pattern = '#^[a-z0-9_-]*$#s';
  10. public $message = 'Only [a-z0-9_-] symbols are allowed.';
  11. }

Контроллер backend\controllers\PostController.php:


 
  1. public function actionCreate()
  2. {
  3. $model = new Post();
  4. if ($model->load(Yii::$app->request->post())) {
  5.  
  6. $model->slug = $model->slug ?: Inflector::slug($model->name);
  7.  
  8. if($model->save()) {
  9. return $this->redirect(['view', 'id' => $model->id]);
  10. }
  11. }
  12.  
  13. return $this->render('create', [
  14. 'model' => $model,
  15. ]);
  16. }

Обновление записи происходит аналогично. В метод actionUpdate($id) необходимо тоже добавить:


 
  1. $model->slug = $model->slug ?: Inflector::slug($model->name);

Теперь ссылка на пост во фронтенде будет выглядеть так:


 
  1. <a href="<?= Url::to(['/blog/post/view', 'slug' => $model->slug]) ?>"><?= Html::encode($model->name) ?></a>
  2.  
  3. // Или
  4. <?
  5. $name = Html::encode($model->name);
  6. $url = Url::to(['/blog/post/view', 'slug' => $model->slug]);
  7. $options = [
  8. 'title' => $name
  9. ];
  10. echo Html::a($name, $url, $options);
  11. ?>

Метод, в котором получаем отдельный пост:


 
  1. public function actionView($slug)
  2. {
  3. // Получаем пост по его слагу
  4. if (!$post = Post::find()->where(['slug' => $slug])->one()) {
  5. throw new NotFoundHttpException('Page not found!');
  6. }
  7.  
  8. return $this->render('view', [
  9. 'post' => $post
  10. ]);
  11. }

Правило в urlManager:


 
  1. [
  2. 'pattern' => 'blog/post/<slug:[\w-]+>',
  3. 'route' => 'blog/post/view',
  4. 'suffix' => '.html'
  5. ]

Теперь посты открываются по красивым адресам по типу:

http://site.ru/blog/post/primer-slaga.html

В прочем, если бы мы заострили на это внимание и оптимизировали бы каждую страницу тщательно, то было бы лучше прописать его самостоятельно. Например так:

http://site.ru/blog/post/slug-example.html

Это был, наверное, самый простой способ сделать слаги (алиасы, псевдонимы) у постов на фреймворке Yii2. Есть, конечно, готовые решения, типа SluggableBehavior. Это поведение, которое будет производить всю валидацию и транслитерацию за вас. В примере, который я описал выше есть возможность управлять всем этим делом. Фишка заключается в том, что по большому счёту никакой автоматической генерации в принципе не нужно. В большинстве случаев имеет бОльший смысл прописать его самостоятельно. Ну, а если вам вдруг стало просто лень, то пусть себе транслитерирует и сохраняет в базу транслит. Это уже будет ЧПУ.

Источник: Перейти
Комментарии (0):
Чтобы оставить свой комментарий, необходимо пройти аутентификацию