RDRybinAvatar photo

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *