Для работы со слагами в Laravel нам понадобится простой и удобный пакет cviebrock/eloquent-sluggable. Устанавливаем его для Ларавел 5.5:
composer require cviebrock/eloquent-sluggable:^4.3
Если вы захотите изменить какие-либо дефолтные настройки, то создайте файл конфигурации:
php artisan vendor:publish --provider="Cviebrock\EloquentSluggable\ServiceProvider"
После этой команды будет создан новый конфиг: config/sluggable.php в котором можно поменять некоторые значения. Думаю, что разберетесь с этим.
Теперь выбираете файл модели, к которой хотите создать слаг. Пусть, к примеру, эта модель называется Post. В этой модели нужно указать пространство имен и создать метод для генерации слага из какого-либо поля таблицы:
use Cviebrock\EloquentSluggable\Sluggable;
class Post extends Model
{
use Sluggable;
/**
* Return the sluggable configuration array for this model.
*
* @return array
*/
public function sluggable()
{
return [
'slug' => [
'source' => 'title'
]
];
}
}
Как видно выше, то слаг будет создан из поля title (заголовок). Но это еще не все. Ведь нам нужно этот слаг где-то хранить. А для этого нужно создать новое поле в таблице posts (мы ведь помним, что название таблицы - это множественное от названия модели).
Рассмотрим вариант, когда таблица у вас уже существует и необходимо создать новую миграцию, для добавления одного поля:
php artisan make:migration AddCollumnSlugPosts
После чего будет создана новая миграция и вы увидите в командной строке, что-то наподобие этого:
Created Migration: 2017_09_21_123338_AddCollumnSlugPosts
Внутри созданного файла создаем новое поле:
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddColumnSlugPosts extends Migration
{
/**
* Add column slug to posts table.
*
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('posts', function (Blueprint $table) {
$table->string('slug')->nullable()->index();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('posts', function (Blueprint $table) {
$table->dropColumn('slug');
});
}
}
И запускаем миграцию:
php artisan migrate
Теперь к вашей таблице posts добавится новое поле slug. Поздравляю! Часть работы выполнена. Да, кстати. Почему поле мы назвали именно slug, а не как-то иначе. Ответ становится понятен из метода модели Post:
public function sluggable() { return [ 'slug' => [ 'source' => 'title' ] ]; }
Ключ массива slug указывает на поле в таблице posts, куда автоматически будет записан слаг, созданный из поля-источника этой же таблицы. В нашем конкретном случае - это поле title. Можно создавать слаг из любого строкового поля. Вам нет нужны создавать слаг вручную. Он будет создаваться сам, автоматически. Надеюсь, это понятно.
Идем дальше. Теперь нас интересует, как для слага создать свой роут (route). Это очень просто - так же само, как и для числового индекса {id}:
// Paths for posts.
Route::get('post', 'PostController@index')->name('post.index');
Route::post('post', 'PostController@store')->name('post.store');
Route::get('post/create', 'PostController@create')->name('post.create');
Route::get('post/{slug}', 'PostController@show')->name('post.show');
Route::patch('post/{slug}', 'PostController@update')->name('post.update');
Route::delete('post/{slug}', 'PostController@destroy')->name('post.destroy');
Route::get('post/{slug}/edit', 'PostController@edit')->name('post.edit');
А в контроллере PostController, например, в методе show, пишем следующее:
/**
* Display the specified resource.
*
* @param string $slug
*
* @return \Illuminate\Http\RedirectResponse
*/
public function show($slug)
{
// If user come from ols link where was id then make 301 redirect.
if (is_numeric($slug)) {
// Get post for slug.
$post = Post::findOrFail($slug);
return Redirect::to(route('post.show', $post->slug), 301);
}
// Get post for slug.
$post = Post::whereSlug($slug)->firstOrFail();
return view('posts.show', [
'post' => $post
]);
}
Вначале мы проверяем, не является ли слаг числом. Зачем мы это делаем?! Часто слаги внедряют в программу уже после того, как был другой механизм построения пути. Например, через числовые индексы. Тогда может получится ситуация, что пользователь, зайдя на сайт по старой ссылке, увидит 404 ошибку, что такой страницы не существует. Ведь мы теперь работаем через слаги. Поэтому, нам необходимо сделать 301 редирект со старой страницы, на новую.
Для этого мы и проверяем полученный аргумент на числовое значение, пытаемся по этому значению получить коллекцию (collection), и если такой пост действительно существует (если нет, то выводим 404 ошибку), то делаем 301 редирект на страницу со слагом.
Если же вы создаете сайт с нуля и сразу используете слаги, то вам такой проверки и редирект делать не нужно.
Построения ссылки в шаблоне тоже очень простое:
href="{!! route('post.show', $post->slug) !!}"
class="btn btn-info">ReadMore
В принципе, это и все!
Как видите, сложности нет вообще никакой, а использование слагов очень просто и удобно для пользователей и поисковиков.
Комментарии (12):
Updating your Eloquent Models).
Суть такова, что мы подключаем в классе модели трэит Sluggable:
в котором описан абстрактный метод sluggable() который должен вернуть массив. Поскольку метод абстрактный:
то мы не можем его заюзать напрямую, а обязаны переопределить (реализовать). Таким образом достигается автоматическая генерация слага и запись его в базу (благодаря логике пакета).
Теперь непосредственно о самом массиве. Запись вида:
говорит нам, что мы создаем в нашей таблице модели запись для поля slug, которое должно быть сформировано из источника source, которым в нашем примере является поле title
При сохранении модели с полем title="Привет мир" будет сформирован слаг (название поля в таблице/модели slug) из этого поля ('source' => 'title'): privet-mir
Надеюсь, я прояснил для вас этот момент. Если не поняли, то спрашивайте. Попробую объяснить по другому.
Устанавливаю через composer, пишет то что на картинке, пробовал менять цифры вместо 4.3 написал 5.4, вот тогда и выдала консоль что надо php 5.4