Статьи

Создайте приложение React с помощью RESTful-части Laravel RESTful: Часть 1, Laravel 5.5 API

Laravel и React — две популярные технологии веб-разработки, используемые для создания современных веб-приложений. Laravel — это серверная PHP-инфраструктура, а React — клиентская JavaScript-библиотека. Этот учебник служит введением в Laravel и React, объединяя их для создания современного веб-приложения.

В современном веб-приложении сервер имеет ограниченную работу по управлению внутренним сервером через некоторые конечные точки API (Application Programming Interface). Клиент отправляет запросы на эти конечные точки, а сервер возвращает ответ. Однако сервер не заботится о том, как клиент отображает представление, что полностью соответствует принципу разделения проблем. Эта архитектура позволяет разработчикам создавать надежные приложения для Интернета, а также для различных устройств.

В этом руководстве мы будем использовать последнюю версию Laravel версии 5.5 для создания RESTful back-end API. Внешний интерфейс будет состоять из компонентов, написанных на React. Мы создадим приложение для создания списка продуктов. Первая часть урока будет больше сфокусирована на концепциях Laravel и серверной части. Давайте начнем.

Laravel — это PHP-фреймворк, разработанный для современного Интернета. У этого есть выразительный синтаксис, который одобряет соглашение по парадигме конфигурации . Laravel имеет все функции, которые вам нужны, чтобы начать проект прямо из коробки. Но лично мне нравится Laravel, потому что он превращает разработку с PHP в совершенно другой опыт и рабочий процесс.

С другой стороны, React — это популярная библиотека JavaScript, разработанная Facebook для создания одностраничных приложений. React помогает вам разбить ваше представление на компоненты, где каждый компонент описывает часть пользовательского интерфейса приложения. Компонентный подход имеет дополнительное преимущество повторного использования и модульности компонентов.

Если вы разрабатываете для Интернета, вы можете быть склонны использовать одну кодовую базу как для сервера, так и для клиента. Однако не каждая компания дает разработчику свободу использовать технологию по своему выбору и по ряду веских причин. Использование стека JavaScript для всего проекта является текущей нормой, но ничто не мешает вам выбрать две разные технологии для серверной и клиентской сторон.

Итак, насколько хорошо Laravel и React подходят друг другу? Довольно хорошо, на самом деле. Хотя в Laravel задокументировано, что он поддерживается для Vue.js, который является еще одной платформой JavaScript, мы будем использовать React для внешнего интерфейса, поскольку он более популярен.

Прежде чем начать, я собираюсь предположить, что у вас есть общее представление об архитектуре RESTful и о том, как работают конечные точки API. Кроме того, если у вас есть опыт работы в React или Laravel, вы сможете извлечь максимальную пользу из этого урока.

Однако, если вы новичок в обеих платформах, не беспокойтесь. Учебник написан с точки зрения начинающего, и вы сможете наверстать упущенное без особых проблем. Вы можете найти исходный код руководства на GitHub .

Laravel использует Composer для управления всеми зависимостями. Итак, прежде чем начать работу с Laravel, скачайте и установите Composer на свой компьютер. Вам также может потребоваться настроить переменную среды пути, чтобы Composer был доступен глобально.

Запустите следующую команду, чтобы загрузить установщик laravel.

1
composer global require «laravel/installer»

Если вы правильно настроили $PATH и добавили ~/.composer/vendor/bin в свой путь, вы сможете сгенерировать новый проект Laravel следующим образом:

1
laravel new PROJECT-NAME

Кроме того, вы можете использовать Composer для создания нового проекта без установщика laravel.

1
composer create-project —prefer-dist laravel/laravel blog

Если все идет хорошо, вы сможете разместить свое приложение на сервере разработки по адресу http://localhost:8000 .

1
php artisan serve

Примечание: Artisan — это инструмент командной строки, без которого вы не можете жить, работая с Laravel. Artisan принимает большой список команд, которые позволяют генерировать код для вашего приложения. Запустите php artisan list для просмотра всех доступных команд artisan.

Ваше приложение будет иметь файл .env внутри корневого каталога. Вся информация о конфигурации конкретной среды объявляется здесь. Создайте базу данных для своего приложения, если вы этого еще не сделали, и добавьте детали базы данных в файл .env .

1
2
3
4
5
6
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=sampledb
DB_USERNAME=root
DB_PASSWORD=

Laravel — это фреймворк, который следует архитектуре Model-View-Controller (MVC). Вообще говоря, MVC помогает вам отделить запросы к базе данных (Модель) от логики, связанной с тем, как должны обрабатываться запросы (Контроллер) и как должен отображаться макет (Представление). Изображение ниже демонстрирует работу типичного приложения Laravel.

Обзор архитектуры Laravels для построения конечных точек API RESTful
Архитектура Ларавела. Контроллер возвращает ответ и, следовательно, слой представления не требуется.

Поскольку мы создаем API с использованием Laravel, мы ограничимся обсуждением модели и контроллера. Мы рассмотрим наши варианты создания View во второй части этого урока.

Когда сервер получает HTTP-запрос, Laravel пытается сопоставить его с маршрутом, зарегистрированным в любом из файлов маршрута. Все файлы маршрутов находятся внутри каталога маршрутов. маршруты / web.php содержат маршрут для веб-интерфейса, тогда как маршруты / api.php содержат маршрут для API. Маршруты, зарегистрированные в api.php, будут иметь префикс /api (как в localhost: 3000 / api). Если вам нужно изменить это поведение, RouteServiceProvider класс RouteServiceProvider в /app/Providers/RouteServiceProvider.php и внесите в него изменения.

Поскольку мы создаем приложение для создания списка продуктов, здесь представлены конечные точки для API и действия HTTP, связанные с этими конечными точками.

  • ПОЛУЧИТЬ /products/ : получить все продукты.
  • GET /product/{id} : получить продукт, соответствующий id .
  • POST /products : создайте новый продукт и вставьте его в базу данных.
  • PUT /products/{id} : обновить существующий продукт, соответствующий id .
  • DELETE /products/{id} : Удалить продукт с указанным id .

Давайте разберемся в терминологии. GET, POST, PUT и DELETE — это HTTP-глаголы (более известные как HTTP-методы), в основном необходимые для создания службы RESTful. /products — это URI, связанный с ресурсом products. Методы HTTP запрашивают у сервера выполнение желаемого действия с данным ресурсом.

Действия HTTP, действующие на ресурс Product
GET, POST, PUT и DELETE — наиболее часто используемые действия REST

Маршрутизатор позволяет вам объявлять маршруты для ресурса вместе с методами HTTP, которые нацелены на этот ресурс. Вот пример файла маршрутов, который возвращает некоторые жестко закодированные данные.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
** Basic Routes for a RESTful service:
**
** Route::get($uri, $callback);
** Route::post($uri, $callback);
** Route::put($uri, $callback);
** Route::delete($uri, $callback);
**
**/
 
Route::get(‘products’, function () {
    return response([‘Product 1’, ‘Product 2’, ‘Product 3’],200);
});
 
Route::get(‘products/{product}’, function ($productId) {
    return response()->json([‘productId’ => «{$productId}»], 200);
});
  
 
Route::post(‘products’, function() {
    return response()->json([
            ‘message’ => ‘Create success’
        ], 201);
});
 
Route::put(‘products/{product}’, function() {
    return response()->json([
            ‘message’ => ‘Update success’
        ], 200);
});
 
Route::delete(‘products/{product}’,function() {
    return response()->json(null, 204);
});

Если вы хотите убедиться, что маршруты работают должным образом, вы должны использовать такой инструмент, как POSTMAN или curl.

Ресурсу товаров нужна модель, которая может взаимодействовать с базой данных. Модель — это слой, который находится поверх базы данных и скрывает весь специфичный для базы данных жаргон. Laravel использует Eloquent ORM для моделирования базы данных.

Eloquent ORM, включенный в Laravel, обеспечивает красивую и простую реализацию ActiveRecord для работы с вашей базой данных. Каждая таблица базы данных имеет соответствующую «Модель», которая используется для взаимодействия с этой таблицей. Модели позволяют запрашивать данные в ваших таблицах, а также вставлять новые записи в таблицу.
Laravel Docs

Как насчет определения схемы базы данных? Миграция Ларавела позаботится об этом. Artisan имеет команду миграции, которая позволяет вам определять схему и постепенно обновлять ее на более позднем этапе. Давайте создадим модель и миграцию для сущности Product.

1
$ php artisan make:model Product -m

Примечание: существует множество команд Artisan, и их легко потерять. Таким образом, каждая команда ремесленника включает вспомогательный экран, который отображает дополнительную информацию, такую ​​как доступные параметры и аргументы. Чтобы перейти на страницу справки, имени команды должен предшествовать help . Запустите следующую команду справки, чтобы узнать, что означает опция -m : $ php artisan help make:model .

Вот сгенерированный файл миграции.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
 
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
 
class CreateProductsTable extends Migration
{
   
    public function up()
    {
        Schema::create(‘products’, function (Blueprint $table) {
            $table->increments(‘id’);
            $table->timestamps();
        });
    }
 
   
    public function down()
    {
        Schema::dropIfExists(‘products’);
    }
}

Метод up вызывается при переносе новых таблиц и столбцов в базу данных, тогда как метод down вызывается при откате миграции. Мы создали схему для таблицы с тремя строками: id , created_at и updated_at . Метод $table->timestamps() отвечает за поддержание столбцов created_at и updated_at . Давайте добавим еще пару строк к определению схемы.

01
02
03
04
05
06
07
08
09
10
11
12
13
/* Let’s add columns for title, description, price, availability */
   
  public function up()
   {
       Schema::create(‘products’, function (Blueprint $table) {
           $table->increments(‘id’);
           $table->timestamps();
           $table->string(‘title’);
           $table->text(‘description’);
           $table->integer(‘price’);
           $table->boolean(‘availability’);
       });
   }

Мы обновили схему четырьмя новыми столбцами. Конструктор схемы Laravel поддерживает различные типы столбцов, такие как string , text , integer , boolean и т. Д.

Чтобы выполнить отложенные миграции, вам нужно выполнить следующую команду:

1
php artisan migrate

По условию Laravel предполагает, что модель Product связана с таблицей продуктов . Однако если вам нужно связать модель с настраиваемым именем таблицы, вы можете использовать свойство $table для объявления имени таблицы. Затем модель будет связана с таблицей с именем custom_products .

1
protected $table = ‘custom_products’;

Но мы будем просты и будем придерживаться соглашения. Сгенерированная модель продукта находится в каталоге app / . Хотя класс модели может показаться пустым, он оснащен различными методами построения запросов, которые можно использовать для запроса к базе данных. Например, вы можете использовать Product::all() для получения всех продуктов или Product::find(1) для получения конкретного продукта с идентификатором 1.

Модели Laravel имеют встроенный механизм защиты от уязвимости массового назначения . Свойство fillable используется для объявления имен атрибутов, которые можно безопасно назначать массовым образом.

1
2
3
/* Add the fillable property into the Product Model */
 
protected $fillable = [‘title’, ‘description’, ‘price’, ‘availability’];

Приведенный выше код заносит в белый список атрибуты title , description , price и availability и обрабатывает их как массовые. Теперь мы можем использовать метод Product::create для вставки новых строк в таблицу products.

Laravel позволяет вам заполнить вашу базу данных разработки и производства фиктивными данными, которые вы затем можете использовать для тестирования ваших конечных точек API. Вы можете создать начальный класс, выполнив следующую команду Artisan.

1
$ php artisan make:seeder ProductsTableSeeder

Сгенерированные файлы сеялки будут помещены в каталог database / seed .

Чтобы сгенерировать фиктивные данные, вы можете использовать что-то вроде str_random(10) которое возвращает случайную строку. Но если вам нужны данные, которые достаточно близки к фактическим данным, вы должны использовать что-то вроде библиотеки фейеров. Faker — сторонняя библиотека, которая поставляется с платформой Laravel для генерации поддельных данных.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
use App\Product;
 
class ProductsTableSeeder extends Seeder
{
    public function run()
    {
 
        $faker = \Faker\Factory::create();
 
        // Create 50 product records
        for ($i = 0; $i < 50; $i++) {
            Product::create([
                ‘title’ => $faker->title,
                ‘description’ => $faker->paragraph,
                ‘price’ => $faker->randomNumber(2),
                ‘availability’ => $faker->boolean(50)
            ]);
        }
    }
}

Выполните команду db:seed artisan, чтобы заполнить базу данных.

1
$ php artisan db:seed —class=ProductsTableSeeder

Давайте вернемся к routs / api.php и заполните недостающие фрагменты.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
**Basic Routes for a RESTful service:
**Route::get($uri, $callback);
**Route::post($uri, $callback);
**Route::put($uri, $callback);
**Route::delete($uri, $callback);
**
*/
Route::get(‘products’, function () {
    return response(Product::all(),200);
});
 
Route::get(‘products/{product}’, function ($productId) {
    return response(Product::find($productId), 200);
});
  
 
Route::post(‘products’, function(Request $request) {
   $resp = Product::create($request->all());
    return $resp;
 
});
 
Route::put(‘products/{product}’, function(Request $request, $productId) {
    $product = Product::findOrFail($productId);
    $product->update($request->all());
    return $product;
});
 
Route::delete(‘products/{product}’,function($productId) {
    Product::find($productId)->delete();
 
    return 204;
 
});

Файл маршрута в настоящее время содержит логику для маршрутизации и обработки запросов. Мы можем переместить логику обработки запросов в класс Controller, чтобы наш код был лучше организован и более читабелен. Давайте сначала сгенерируем класс контроллера.

1
$ php artisan make:controller ProductsController

Класс Controller состоит из различных методов (index, show, store, update и delete), которые соответствуют различным действиям HTTP. Я переместил логику обработки запросов с маршрута на контроллер.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?php
 
namespace App\Http\Controllers;
 
use Illuminate\Http\Request;
use App\Product;
 
class ProductsController extends Controller
{
 
    public function index()
    {
        return Product::all();
    }
 
    public function show(Product $product)
    {
        return $product;
    }
 
    public function store(Request $request)
    {
        $product = Product::create($request->all());
 
        return response()->json($product, 201);
    }
 
    public function update(Request $request, Product $product)
    {
        $product->update($request->all());
 
        return response()->json($product, 200);
    }
 
    public function delete(Product $product)
    {
        $product->delete();
 
        return response()->json(null, 204);
    }
 
}
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
/**
**Basic Routes for a RESTful service:
**Route::get($uri, $callback);
**Route::post($uri, $callback);
**Route::put($uri, $callback);
**Route::delete($uri, $callback);
**
*/
 
 
Route::get(‘products’, ‘ProductsController@index’);
 
Route::get(‘products/{product}’, ‘ProductsController@show’);
 
Route::post(‘products’,’ProductsController@store’);
 
Route::put(‘products/{product}’,’ProductsController@update’);
 
Route::delete(‘products/{product}’, ‘ProductsController@delete’);

Если вы не заметили, я внедрил экземпляр Product в методы контроллера. Это пример неявного связывания Laravel. Laravel пытается сопоставить имя экземпляра модели Product $product с именем сегмента URI {product} . Если совпадение найдено, экземпляр модели Product внедряется в действия контроллера. Если база данных не имеет продукта, она возвращает ошибку 404. Конечный результат такой же, как и раньше, но с меньшим количеством кода.

Откройте POSTMAN, и конечные точки для продукта должны работать. Убедитесь, что у вас включен заголовок Accept : application/json .

Если вы перейдете на несуществующий ресурс, это то, что вы увидите.

Страница ошибки, отображаемая для NotFoundHTTPException

NotFoundHTTPException — это то, как Laravel отображает ошибку 404. Если вы хотите, чтобы сервер возвращал ответ JSON, вам придется изменить поведение обработки исключений по умолчанию. В Laravel есть класс Handler, предназначенный для обработки исключений, который находится в app / Exceptions / Handler.php . Класс в основном имеет два метода: report() и render() . Метод report полезен для создания отчетов и регистрации событий исключений, тогда как метод render используется для возврата ответа при обнаружении исключения. Обновите метод рендеринга, чтобы он возвращал ответ JSON:

01
02
03
04
05
06
07
08
09
10
11
12
public function render($request, Exception $exception)
 {
    
     if ($exception instanceof \Illuminate\Database\Eloquent\ModelNotFoundException)
     {
      return response()->json([
           ‘message’ => ‘Resource not found’
       ], 404);
     }
      
     return parent::render($request, $exception);
 }

Laravel также позволяет нам проверять входящие HTTP-запросы с использованием набора правил проверки и автоматически возвращать ответ JSON, если проверка не удалась. Логика для проверки будет размещена внутри контроллера. Объект Illuminate\Http\Request предоставляет метод validate, который мы можем использовать для определения правил проверки. Давайте добавим несколько проверок правильности в метод store.

01
02
03
04
05
06
07
08
09
10
11
12
public function store(Request $request)
   {
       $this->validate($request, [
       ‘title’ => ‘required|unique:products|max:255’,
       ‘description’ => ‘required’,
       ‘price’ => ‘integer’,
       ‘availability’ => ‘boolean’,
   ]);
       $product = Product::create($request->all());
 
       return response()->json($product, 201);
   }

Теперь у нас есть работающий API для приложения с перечнем продуктов. Однако в API отсутствуют основные функции, такие как аутентификация и ограничение доступа неавторизованным пользователям. Laravel имеет встроенную поддержку аутентификации, и создать API для нее относительно просто. Я рекомендую вам реализовать API аутентификации в качестве упражнения.

Для тех из вас, кто только начинает работать с Laravel или хочет расширить свои знания, сайт или приложение с помощью расширений, у нас есть множество вещей, которые вы можете изучить на Envato Market .

Теперь, когда мы закончили работу с серверной частью, мы переключим наше внимание на интерфейсные концепции. Оставайтесь с нами для второй части серии. Поделитесь своими мыслями в комментариях.