Псевдонимы записей в Yii2. Создание и управление
Настройка ЧПУ – неотъемлемый атрибут работы по SEO-оптимизации любого сайта. Формировать URL только по id записи – не лучший вариант.
В данном уроке мы добавим псевдонимы записей (слаг/алиас) для постов блога.
Суть такова. В форме (создания, редактирования) поста есть текстовове поле, в которое мы можем прописать свой собственный slug и при этом оно должно валидироваться. Если мы оставим поле пустым, то Yii2 сам сделает эту работу методом Inflector::slug()
, куда мы передадим название поста (то есть, по умолчанию слаг будет транслитом названия поста). В базе данных поле slug
обязательно для заполнения (NOT NULL
) и является уникальным.
Добавим в базу данных поле slug
(если его не было изначально). Пример добавления поля через миграцию:
// Из консоли
php yii migrate/create add_post_field_slug
В созданной миграции:
public function safeUp()
{
$this->addColumn('{{%post}}', 'slug', $this->string(255)->notNull()->after('status')->unique());
$this->createIndex('{{%idx-post-slug}}', '{{%post}}', 'slug', true);
}
public function safeDown()
{
$this->dropColumn('{{%post}}', 'slug');
}
В форме (backend\views\post\_form.php
) добавим поле:
<?= $form->field($model, 'slug')->textInput(['maxlength' => true]) ?>
В модель Post
добавляем следующий код:
private $_post;
public function rules()
{
return [
[['name'], 'required'], // На стороне клиента "slug" необязательный
[['name', 'slug'], 'string', 'max' => 255], // "slug" - ограниченная строка
['slug', SlugValidator::class], // "slug" валидируется классом SlugValidator
// "name" и "slug" - уникальны (фильтр по ID поста при редактировании)
[['name', 'slug'], 'unique', 'targetClass' => Post::class, 'filter' => $this->_post ? ['<>', 'id', $this->_post->id] : null]
];
}
Класс SlugValidator
:
<?php
namespace common\models\validators;
use yii\validators\RegularExpressionValidator;
class SlugValidator extends RegularExpressionValidator
{
public $pattern = '#^[a-z0-9_-]*$#s';
public $message = 'Only [a-z0-9_-] symbols are allowed.';
}
Контроллер backend\controllers\PostController.php
:
public function actionCreate()
{
$model = new Post();
if ($model->load(Yii::$app->request->post())) {
$model->slug = $model->slug ?: Inflector::slug($model->name);
if($model->save()) {
return $this->redirect(['view', 'id' => $model->id]);
}
}
return $this->render('create', [
'model' => $model,
]);
}
Обновление записи происходит аналогично. В метод actionUpdate($id)
необходимо тоже добавить:
$model->slug = $model->slug ?: Inflector::slug($model->name);
Теперь ссылка на пост во фронтенде будет выглядеть так:
<a href="<?= Url::to(['/blog/post/view', 'slug' => $model->slug]) ?>"><?= Html::encode($model->name) ?></a>
// Или
<?
$name = Html::encode($model->name);
$url = Url::to(['/blog/post/view', 'slug' => $model->slug]);
$options = [
'title' => $name
];
echo Html::a($name, $url, $options);
?>
Метод, в котором получаем отдельный пост:
public function actionView($slug)
{
// Получаем пост по его слагу
if (!$post = Post::find()->where(['slug' => $slug])->one()) {
throw new NotFoundHttpException('Page not found!');
}
return $this->render('view', [
'post' => $post
]);
}
Правило в urlManager
:
[
'pattern' => 'blog/post/<slug:[\w-]+>',
'route' => 'blog/post/view',
'suffix' => '.html'
]
Теперь посты открываются по красивым адресам по типу:
http://site.ru/blog/post/primer-slaga.html
В прочем, если бы мы заострили на это внимание и оптимизировали бы каждую страницу тщательно, то было бы лучше прописать его самостоятельно. Например так:
http://site.ru/blog/post/slug-example.html
Это был, наверное, самый простой способ сделать слаги (алиасы, псевдонимы) у постов на фреймворке Yii2. Есть, конечно, готовые решения, типа SluggableBehavior
. Это поведение, которое будет производить всю валидацию и транслитерацию за вас. В примере, который я описал выше есть возможность управлять всем этим делом. Фишка заключается в том, что по большому счёту никакой автоматической генерации в принципе не нужно. В большинстве случаев имеет бОльший смысл прописать его самостоятельно. Ну, а если вам вдруг стало просто лень, то пусть себе транслитерирует и сохраняет в базу транслит. Это уже будет ЧПУ.
Предыдущая запись
Постраничная навигация в Yii2Следующая запись
Добавление (регистрация) мета-тегов в Yii2
Комментарии (0)