БД и маршруты
В Laravel 5.4 используется кодировка utf8mb4, поэтому нужно использовать БД с поддержкой этой кодировки. Иначе будет ошибка:
[Illuminate\Database\QueryException]
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter table users add unique users_email_unique(email))
[PDOException]
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes
Если нет возможности использовать БД с кодировкой utf8mb4, то стандартную длину строки можно подкорректировать в файле app/Providers/AppServiceProvider.php. Для этого в начале файла нужно указать:
use Illuminate\Support\Facades\Schema;
В метод boot() добавить:
Schema::defaultStringLength(191);
Для форума нам потребуются следующие таблицы: threads, replies, channels, favorites. Таблица threads будет содержать темы форума; replies будет содержать сообщения пользователей внутри тем; channels – это рубрики (каждая тема относится к определенной рубрике); favorites – используется для создания полиморфной связи (отношения) между голосами за сообщение (favorites) и самим сообщением (reply).
Для создания таблиц воспользуемся Laravel-миграциями. По умолчанию, в папке database/migrations уже есть два файла: create_users_table.php и create_password_resets_table.php. Как видно из названий они нужны для работы системы авторизации/регистрации. Для работы приложения нам потребуются модели, чтобы одновременно создать файлы моделей и файлы миграций воспользуемся консолью:
php artisan make:model Channel -m
php artisan make:model Favorite -m
php artisan make:model Reply -m
php artisan make:model Thread -m
К моделям вернемся позже, а пока разберемся с файлами миграций.
Начнем с файла миграции «threads». Здесь содержимое метода up() должно выглядеть следующим образом:
Schema::create('threads', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('user_id');
$table->unsignedInteger('channel_id');
$table->string('title');
$table->text('body');
$table->timestamps();
});
Метод up() файла миграции «replies» должен выглядеть следующим образом:
Schema::create('replies', function (Blueprint $table) {
$table->increments('id');
$table->integer('thread_id');
$table->integer('user_id');
$table->text('body');
$table->timestamps();
});
Метод up() файла миграции «channels» должен выглядеть следующим образом:
Schema::create('channels', function (Blueprint $table) {
$table->increments('id');
$table->string('name', 50);
$table->string('slug', 50);
$table->timestamps();
});
Метод up() файла миграции «favorites» должен выглядеть следующим образом:
Schema::create('favorites', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('user_id');
$table->unsignedInteger('favorited_id');
$table->string('favorited_type', 50);
$table->timestamps();
$table->unique(['user_id', 'favorited_id', 'favorited_type']);
});
Как уже говорилось выше таблица «favorites» используется для создания полиморфной связи (отношения) между голосами за сообщение (favorites) и самим сообщением (reply). Главные поля, на которые нужно обратить внимание: favorited_id и favorited_type. Первое содержит id сообщения, а второе — имя класса-модели (App\Reply). В последней строчке мы задаем уникальный составной ключ, который предотвращает повторное голосование за одно и то же сообщение.
Теперь для того чтобы создать таблицы в БД воспользуемся командой:
php artisan migrate
На этом предварительная работа с БД закончена. Далее перейдем к маршрутам.
Все маршруты (routes) для нашего приложения должны быть расположены в файле routes/web.php. Содержимое этого файла должно быть следующим:
Auth::routes();
Route::get('/home', 'HomeController@index');
Route::get('/', 'ThreadsController@index');
Route::get('threads/create', 'ThreadsController@create');
Route::get('threads/{channel}/{thread}', 'ThreadsController@show');
Route::delete('threads/{channel}/{thread}', 'ThreadsController@destroy');
Route::post('threads', 'ThreadsController@store');
Route::get('threads/{channel}', 'ThreadsController@index');
Route::post('/threads/{channel}/{thread}/replies', 'RepliesController@store');
Route::delete('/replies/{reply}', 'RepliesController@destroy');
Route::get('channels/create', 'ChannelsController@create');
Route::post('channels', 'ChannelsController@store');
Route::post('/replies/{reply}/favorites', 'FavoritesController@store');
Route::get('/profiles/{user}', 'ProfilesController@show')->name('profile');
В следующих разделах мы перейдем к рассмотрению работы составных частей приложения (контроллеры, модели, виды).