Попробуем создать простое CRUD (CreateReadUpdateDelete) приложение, которое умеет: читать, писать, редактировать и удалять записи в базе данных с использованием Laravel 9. Для этого будем использовать OpenServer.
Установка Laravel в OpenServer
Создадим папку (например, test-laravel.loc) в папке проектов domains OpenServer.
Далее запустим консоль OpenServer-а. По умолчанию мы находимся в корневом каталоге программы, нам нужно попасть в папку domains
cd domains
Теперь нужно обновить Composer, для этого используем команду
composer self-update
И вот теперь приступим к самой установке Laravel с помощью команды
composer create-project --prefer-dist laravel/laravel test-laravel.loc
В конце команды указывайте имя директории своего проекта, в моем случае это test-laravel.loc
После успешного выполнения этой команды в директории проекта должны появиться каталоги и файлы Laravel.
Теперь необходимо произвести настройку OpenServer для корректной работы Laravel для этого:
- Заходим в настройки;
- Переходим во вкладку Домены ;
- Выставляем в Управление доменами значение Ручное + Автопоиск;
- Заполняем имя домена и указываем путь до папки public вашей установки Laravel;
- Жмем Добавить;
- Жмем Сохранить.
Laravel 9 требует для работы php версии не ниже 8.0, так что проверьте и измените при необходимости версию php в настройках OpenServer во вкладке Модули.
Поле всех этих манипуляций по адресу http://test-laravel.loc/ (в моем случае) должна открыться стартовая страничка.
Установка закончена, перейдем к работе с Laravel.
Создание и подключение к базе данных
Для начала создадим нашу базу данных через phpMyAdmin входящий в поставку OpenServer и назовем ее например, test-laravel.
Теперь нужно настроить подключение Laravel к этой базе. Эти настройки хранятся в файле .env в корне вашего веб-приложения. В этом файле есть строки начинающиеся с префикса DB, они то нас и интересуют. Меняем их на свои данные:
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=test-laravel //имя базы данных DB_USERNAME=root // имя пользователя DB_PASSWORD=root // пароль к базе
В моем случае пришлось поменять только DB_DATABASE — имя базы данных. А пароль у меня не установлен.
Создаем Модель (model) и Миграцию (migration)
Назовем нашу модель Post и создадим одной командой Модель и Миграцию через консоль, но для начала перейдем в каталог проекта
cd test-laravel.loc php artisan make:model Post --migration
Теперь в каталоге database/migrations/ файл 2022_08_08_103037_create_posts_table.php. В функции up() описана структура создаваемой таблицы, в которой изначально есть два поля id и timestamps. Добавим поля title и description.
<?php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('posts', function (Blueprint $table) { $table->id(); $table->string('title'); //наши добавленные поля $table->text('description'); //наши добавленные поля $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('posts'); } };
Сохраним и перейдем в командную строку где запустим миграцию
php artisan migrate
Видим, что таблица создалась.
Переходим к файлу модели app\Models\Post.php и в классе Post добавляем массив $fillable с title и description, таким образом разрешаем запись этих полей. Должно получиться так:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Post extends Model { use HasFactory; protected $fillable = [ 'title', 'description' ]; // Разрешаем массовое присваивание }
Добавляем маршруты (routes)
Для этого нам нужно открыть файл routes/web.php, подключить контроллер и указать маршрут для posts. Получится должно так:
<?php use Illuminate\Support\Facades\Route; use App\Http\Controllers\PostController; //контроллер /* |-------------------------------------------------------------------------- | Web Routes |-------------------------------------------------------------------------- | | Here is where you can register web routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | contains the "web" middleware group. Now create something great! | */ Route::resource('posts', PostController::class); // зарегистрируем маршрут контроллера нашего ресурса Route::get('/', function () { return view('welcome'); });
Создаем Контроллер (controller)
Вновь возвращаемся в консоль и выполняем команду создания контроллера ресурса (Resource Controller):
php artisan make:controller PostController --resource
Теперь открываем файл app\Http\Controllers\PostController.php и видим класс PostController
с пустыми методами:
- index() — метод представления всех записей;
- create() — метод создания записи;
- store() — метод сохранения записи в базе;
- show() — метод вывода записи;
- edit() — метод редактирования записи;
- update() — метод обновления записи в базе данных;
- destroy() — метод удаления записи.
А вот готовый файл с методами, заметим, что некоторые методы ссылаются на соответствующие представления (view)
<?php namespace App\Http\Controllers; use App\Models\Post; use Illuminate\Http\Request; class PostController extends Controller { /** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index() { $data = Post::latest()->paginate(5); return view('posts.index', compact('data')) ->with('i', (request()->input('page', 1) - 1) * 5); } /** * Show the form for creating a new resource. * * @return \Illuminate\Http\Response */ public function create() { return view('posts.create'); } /** * Store a newly created resource in storage. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request) { $request->validate([ 'title' => 'required', 'description' => 'required', ]); Post::create($request->all()); return redirect()->route('posts.index') ->with('success', 'Post created successfully.'); } /** * Display the specified resource. * * @param int $id * @return \Illuminate\Http\Response */ public function show(Post $post) { return view('posts.show', compact('post')); } /** * Show the form for editing the specified resource. * * @param int $id * @return \Illuminate\Http\Response */ public function edit(Post $post) { return view('posts.edit', compact('post')); } /** * Update the specified resource in storage. * * @param \Illuminate\Http\Request $request * @param int $id * @return \Illuminate\Http\Response */ public function update(Request $request, Post $post) { $request->validate([ 'title' => 'required', 'description' => 'required', ]); $post->update($request->all()); return redirect()->route('posts.index') ->with('success', 'Post updated successfully'); } /** * Remove the specified resource from storage. * * @param int $id * @return \Illuminate\Http\Response */ public function destroy(Post $post) { $post->delete(); return redirect()->route('posts.index') ->with('success', 'Post deleted successfully'); } }
Создание представлений (views)
Для этого нам необходимо создать blade файлы каждого представления:
- resources/views/posts/layout.blade.php — каркас шаблонов
<!DOCTYPE html> <html> <head> <title>Laravel 9</title> <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha/css/bootstrap.css" rel="stylesheet"> </head> <body> <div class="container"> @yield('content')<!-- используется для отображения содержимого секции дочернего шаблона --> </div> </body> </html>
- resources/views/posts/index.blade.php — шаблон отображения списка постов
@extends('posts.layout') <!-- указываем родительский шаблон --> @section('content') <!-- объявляем нашу секцию --> <div class="row" style="margin-top: 5rem;"> <div class="col-lg-12 margin-tb"> <div class="pull-left"> <h2>Посты</h2> </div> <div class="pull-right"> <a class="btn btn-success" href="{{ route('posts.create') }}"> Создать новый пост</a> </div> </div> </div> @if ($message = Session::get('success')) <div class="alert alert-success"> <p>{{ $message }}</p> </div> @endif <pre> </pre> <table class="table table-bordered"> <tr> <th>№</th> <th>Заголовок</th> <th>Описание</th> <th>Дата создания</th> <th>Дата обновления</th> <th width="280px">Действия</th> </tr> @foreach ($data as $key => $value) <tr> <td>{{ ++$i }}</td> <td>{{ $value->title }}</td> <td>{{ \Str::limit($value->description, 100) }}</td> <td>{{ $value->created_at }}</td> <td>{{ $value->updated_at }}</td> <td> <form action="{{ route('posts.destroy', $value->id) }}" method="POST"> <a class="btn btn-info" href="{{ route('posts.show', $value->id) }}">Просмотреть</a> <a class="btn btn-primary" href="{{ route('posts.edit', $value->id) }}">Редактировать</a> @csrf @method('DELETE') <button type="submit" class="btn btn-danger">Удалить</button> </form> </td> </tr> @endforeach </table> {!! $data->links() !!} <!-- вывод пагинации--> @endsection
- resources/views/posts/create.blade.php — шаблон создания поста
@extends('posts.layout') @section('content') <div class="row" style="margin-top: 5rem;"> <div class="col-lg-12 margin-tb"> <div class="pull-left"> <h2>Добавить новый пост</h2> </div> <div class="pull-right"> <a class="btn btn-primary" href="{{ route('posts.index') }}">Назад</a> </div> </div> </div> @if ($errors->any()) <div class="alert alert-danger"> <strong>Ошибка!</strong> Возникли проблемы при сохранении поста<br><br> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif <form action="{{ route('posts.store') }}" method="POST"> @csrf <div class="row"> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <strong>Заголовок:</strong> <input type="text" name="title" class="form-control" placeholder="Введите заголовок"> </div> </div> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <strong>Описание:</strong> <textarea class="form-control" style="height:150px" name="description" placeholder="Введите описание"></textarea> </div> </div> <div class="col-xs-12 col-sm-12 col-md-12 text-center"> <button type="submit" class="btn btn-primary">Сохранить</button> </div> </div> </form> @endsection
- resources/views/posts/edit.blade.php — шаблон редактирования поста
@extends('posts.layout') @section('content') <div class="row" style="margin-top: 5rem;"> <div class="col-lg-12 margin-tb"> <div class="pull-left"> <h2>Редактировать пост</h2> </div> <div class="pull-right"> <a class="btn btn-primary" href="{{ route('posts.index') }}">Назад</a> </div> </div> </div> @if ($errors->any()) <div class="alert alert-danger"> <strong>Ошибка!</strong> Возникли проблемы при сохранении поста.<br><br> <ul> @foreach ($errors->all() as $error) <li>{{ $error }}</li> @endforeach </ul> </div> @endif <form action="{{ route('posts.update', $post->id) }}" method="POST"> @csrf @method('PUT') <div class="row"> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <strong>Заголовок:</strong> <input type="text" name="title" value="{{ $post->title }}" class="form-control" placeholder="Title"> </div> </div> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <strong>Описание:</strong> <textarea class="form-control" style="height:150px" name="description" placeholder="Detail">{{ $post->description }}</textarea> </div> </div> <div class="col-xs-12 col-sm-12 col-md-12 text-center"> <button type="submit" class="btn btn-primary">Сохранить</button> </div> </div> </form> @endsection
- resources/views/posts/show.blade.php — шаблон отображения поста
@extends('posts.layout') @section('content') <div class="row" style="margin-top: 5rem;"> <div class="col-lg-12 margin-tb"> <div class="pull-left"> <h2>Просмотр поста</h2> </div> <div class="pull-right"> <a class="btn btn-primary" href="{{ route('posts.index') }}">Назад</a> </div> </div> </div> <div class="row"> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <strong>Заголовок:</strong> {{ $post->title }} </div> </div> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <strong>Описание:</strong> {{ $post->description }} </div> </div> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <strong>Дата создания:</strong> {{ $post->created_at }} </div> </div> <div class="col-xs-12 col-sm-12 col-md-12"> <div class="form-group"> <strong>Дата изменения:</strong> {{ $post->updated_at }} </div> </div> </div> @endsection
Преходим на страницу http://test-laravel.loc/posts (в моем случае). Должно все работать.
Таким образом мы получили базовое представление о работе с Laravel.