Попробуем создать простое 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.





