Примерно неделю назад (15 февраля 2018 г.) в кинотеатрах по всему миру прошла премьера первого фильма «Черная пантера». Вуп! Ууп! Я большой поклонник фильмов Marvel (и немного научной фантастики) и страстный последователь MCU (кинематографическая вселенная Marvel). Давайте продолжим и напишем API, который возвращает данные о персонажах Черной пантеры. Давай заставим Шури гордиться! Не замерзай! 😃

Что такое Люмен?

Lumen - это потрясающе быстрая микро-инфраструктура PHP для создания веб-приложений с выразительным и элегантным синтаксисом. Мы считаем, что разработка должна быть приятной и творческой, чтобы приносить истинное удовлетворение. Lumen пытается облегчить разработку, упростив общие задачи, используемые в большинстве веб-проектов, такие как маршрутизация, абстракция базы данных, организация очередей и кеширование. - Github

Требования к проекту

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

  1. PHP ≥ 7.1.3 (должны быть установлены расширения OpenSSL, PDO и Mbstring PHP)
  2. Композитор
  3. База данных MySQL (инструкция по настройке)
  4. Инструмент базы данных для MySQL (выберите здесь) - для управления нашей базой данных MySQL. Я использую SequelPro, потому что у меня Mac.

Начиная

Давайте начнем. Сначала мы загружаем установщик Lumen через Composer - менеджер зависимостей PHP. Если у вас еще нет Composer, загрузите его здесь и установите глобально. Затем мы запускаем следующую команду, чтобы установить Lumen в нашей системе. Инструкции по настройке Lumen можно найти здесь.

После завершения настройки Lumen мы создаем новый проект. Команда для создания нового проекта Lumen:

lumen new [app name]

В нашем случае мы запускаем:

lumen new black-panther-api

Эта команда устанавливает новый проект lumen в папке с именем black-panther-api. Мы cd в каталог:

cd black-panther-api

PS: Чтобы убедиться, что все пакеты установлены, давайте запустим composer install, чтобы повторить процесс (загрузить пакеты). Затем мы загружаем приложение с помощью следующей команды:

php -S localhost:8000 -t public

Это служит нашему приложению. Мы можем получить к нему доступ, перейдя по адресу http: // localhost: 8000 в нашем браузере. Вы должны увидеть, что установленная версия Lumen вернулась или распечаталась на вашем экране. В этом случае; Lumen (5.6.1) (Компоненты Laravel 5.6. *) - последняя версия на момент написания этого Сообщение блога.

Пачкаем руки

Большой! Все идет нормально. (Здесь я делаю глоток из чашки кофе). Мы собираемся использовать Eloquent (дерзкий ORM Laravel) и Фасады (понять паттерн проектирования фасадов здесь). По умолчанию в Lumen они деактивированы. Мы активируем их, раскомментировав две строки кода в файле bootstrap / app.php в строках 26 и 28, так что у нас есть;

$app->withFacades();

$app->withEloquent();

Давайте изменим текст, возвращаемый при переходе по базовому URL-адресу (http: // localhost: 8000) нашего приложения. Откройте файл web.php в папке routes. Удалите строку с

return $router->app->version();

заменить;

return 'Black Panther API v1.0.0 - Wakanda Forever!';

Сохраните файл и обновите или загрузите http: // localhost: 8000, чтобы изменения вступили в силу.

База данных - модели и миграции

Lumen делает подключение к базам данных и выполнение запросов чрезвычайно простым. В настоящее время Lumen поддерживает четыре системы баз данных: MySQL, Postgres, SQLite и SQL Server.

Документация Lumen определяет миграции следующим образом;

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

Подробнее о миграциях можно прочитать здесь.

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

Давайте создадим наш файл миграции, чтобы создать таблицу Символы:

php artisan make:migration create_characters_table

Эта команда создает файл в каталоге database / migrations. Все миграции имеют временные метки, и именно так приложение отслеживает миграции по порядку. В моем случае 2018_01_24_133302_create_characters_table.php. Мы открываем этот файл в нашей любимой среде IDE, а затем добавляем туда атрибуты персонажей Черной Пантеры. Мы хотим, чтобы у наших персонажей были следующие атрибуты: id, uuid, имя, псевдоним, род занятий, пол, место рождения, биография, способности, кем играл, image_path, которые будут создавать соответствующие столбцы в нашей базе данных.

Наш файл миграции с указанными выше атрибутами будет выглядеть так:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateCharactersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('characters', function (Blueprint $table) {
            $table->increments('id');
            $table->uuid('uuid')->unique(); 
            $table->string('name')->unique();
            $table->string('alias');
            $table->string('occupation');
            $table->string('gender');
            $table->string('place_of_birth');
            $table->text('bio');
            $table->text('abilities');
            $table->string('played_by');
            $table->string('image_path');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('characters');
    }
}

Затем мы запускаем нашу миграцию;

php artisan migrate

Это создает таблицу символов вместе со столбцами, определенными в нашей базе данных. Теперь у нас должно быть две таблицы в нашей базе данных; персонажи и миграции.

Следующий шаг - создание модели. Создайте файл app / Character.php и добавьте следующий код:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Character extends Model
{
   public $timestamps = false;
   protected $primaryKey = 'uuid';
   /**
    * The attributes that are mass assignable.
    *
    * @var array
    */
   protected $fillable = [
      'uuid', 'name', 'occupation', 'place_of_birth', 'gender', 'abilities', 'played_by', 'image_path', 'bio', 'alias'
   ];

   /**
    * The attributes excluded from the model's JSON form.
    *
    * @var array
    */
   protected $hidden = ['id'];
}

В приведенном выше коде мы скрыли атрибут id от возвращаемых ответов JSON. О массовом размещении можно прочитать здесь.

Настройка Cloudinary

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

Перейдите в Cloudinary, чтобы создать учетную запись. Если у вас уже есть учетная запись, просто войдите в систему. После этого вы получите такую ​​панель управления;

На панели инструментов мы можем видеть детали нашей учетной записи. Нам понадобятся имя облака Cloudinary, ключ API и секрет API. Эти значения будут сохранены в файле .env в корне проекта. Замените «****» соответствующими значениями из панели управления Cloudinary снизу.

CLOUDINARY_API_KEY=******************
CLOUDINARY_API_SECRET=******************
CLOUDINARY_CLOUD_NAME=******************

Чтобы установить значения конфигурации Cloudinary во время выполнения, мы передаем массив методу config в классе Cloudinary. Мы делаем это в файле bootstrap / app.php. См. ниже.

Cloudinary::config(array(
   'cloud_name' => env('CLOUDINARY_CLOUD_NAME', true),
   'api_key' => env('CLOUDINARY_API_KEY', true),
   'api_secret' => env('CLOUDINARY_API_SECRET', true)
));

Заберем пакет Cloudinary от packagist. Мы ищем Cloudinary и нажимаем cloudinary / cloudinary_php в списке результатов. Мы запускаем следующую команду в пакете Cloudinary в наш проект через Composer.

composer require cloudinary/cloudinary_php

Маршрутизация - пограничное племя

Вы определите все маршруты для своего приложения в файле routes/web.php. Откройте этот файл в своей среде IDE и добавьте приведенный ниже код.

<?php

/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It is a breeze. Simply tell Lumen the URIs it should respond to
| and give it the Closure to call when that URI is requested.
|
*/

$router->get('/', function () use ($router) {
   return 'Black Panther v1.0.0 - Wakanda Forever!';
});

$router->group(['prefix' => 'api/v1'], function() use ($router){
   $router->get('characters', ['uses' => 'CharacterController@index']);
   $router->post('characters', ['uses' => 'CharacterController@create']);
   $router->get('characters/{uuid}', ['uses' => 'CharacterController@show']);
   $router->put('characters/{uuid}', ['uses' => 'CharacterController@update']);
   $router->delete('characters/{uuid}', ['uses' => 'CharacterController@destroy']);
});

Из кода в файле web.php мы используем именованные маршруты и CharacterController (который мы создадим далее). Группы маршрутов позволяют нам совместно использовать атрибуты маршрута, такие как промежуточное ПО или пространства имен, по большому количеству маршрутов без необходимости определять эти атрибуты для каждого отдельного маршрута. Узнайте больше о маршрутах здесь.

Контроллер

Вместо того, чтобы определять всю логику обработки запросов в одном routes.php файле, вы можете захотеть организовать это поведение с помощью классов контроллеров. Контроллеры могут группировать связанную логику обработки HTTP-запросов в класс. Контроллеры хранятся в каталоге app/Http/Controllers.

Мы создаем наш контроллер CharacterController в app / Http / Controllers. Затем мы добавляем следующий код:

<?php

namespace App\Http\Controllers;

use App\Character;
use Illuminate\Http\Request;
use Ramsey\Uuid\Uuid;

use Cloudinary\Uploader;

class CharacterController extends Controller
{
   public $timestamps = false;
   /**
    * Create a new controller instance.
    *
    * @return void
    */
   public function __construct()
   {
      //
   }

   public function index(){
      return response()->json(['data' => Character::all()]);
   }

   public function create(Request $request){
      $uuid = Uuid::uuid4();

      $this->validate($request, [
         'name' => 'required|unique:characters',
         'occupation' => 'required',
         'gender' => 'required',
         'place_of_birth' => 'required',
         'played_by' => 'required',
         'image_path' => 'required',
         'bio' => 'required',
      ]);

      $extension = $request->image_path->extension();

      $image = Uploader::upload($request->file('image_path')->getRealPath(), ['public_id' => strtolower($request->input('name'). '.' .$extension), 'folder' => 'black-panther']);

      $character = Character::create(array_merge($request->all(), [ 'uuid' => $uuid->toString(), 'image_path' => $image['secure_url'] ]));

      return response()->json(['data' => $character, 'status' => 201]);
   }

   public function show($uuid){
      $character = Character::where('uuid', $uuid)->firstOrFail();

      return response()->json(['data' => $character ]);
   }

   public function update(Request $request, $uuid){
      $character = Character::where('uuid', $uuid)->firstOrFail();

      $character->update($request->all());

      return response()->json(['data' => $character, 'status' => 200]);
   }

   public function destroy($uuid){
      Character::where('uuid', $uuid)->firstOrFail()->delete();

      return response('Character Squashed', 200);
   }
}

Эти методы перечисляют, создают, показывают, обновляют и уничтожают / удаляют ресурс.

  • Метод index обрабатывает запрос GET к конечной точке символов и возвращает все ресурсы символов Черной Пантеры в базе данных.
  • Метод create обрабатывает запрос POST к конечной точке символов и создает новый символьный ресурс. Мы также программно загружаем аватар персонажа в облако (облачные серверы), используя их API. При успешной загрузке возвращается объект с информацией о файле, который сохраняется в переменной image_path. Подробнее читайте в официальной документации. Мы сохраняем путь (защищенный URL) к аватару в нашей базе данных.
  • Метод show также обрабатывает запрос GET к конечной точке символов с указанным ресурсом. Например. / characters / 10a870d8-bdb9–4856–8866-c491008fd921 и возвращает ресурс с указанным uuid.
  • Метод update проверяет, существует ли указанный символьный ресурс, и позволяет обновлять ресурс. Этот метод обрабатывает запрос PUT к конечной точке символов и обновляет указанный ресурс. Например. / characters / 10a870d8-bdb9–4856–8866-c491008fd921
  • Метод destroy также проверяет, существует ли указанный ресурс символов ресурса, а затем удаляет его из базы данных. Этот метод обрабатывает запрос DELETE к конечной точке символов с указанным символьным ресурсом.

Из нашего файла маршрутов (web.php) мы понимаем, что HTTP-запрос, отправляемый на конкретную конечную точку, определяет, какое действие / метод контроллера вызывается. Просматривая код, мы импортируем или требуем модель персонажа и класс UUID через:

use App\Author;
use Ramsey\Uuid\Uuid;

В контроллере все методы возвращают данные в формате JSON.

Тестирование

Мы тестируем наш API с помощью REST-клиентов (я рекомендую Insomnia или PostMan). Ознакомьтесь с различной документацией по тестированию с использованием любого инструмента.

Заключение

Мы сделали это! Мы успешно написали список символов REST API в Black Panther, используя Lumen (супер-крутой микро-фреймворк) и Cloudinary. Lumen - это мой любимый инструмент для API, использующих PHP. Я надеюсь, вам понравится пользоваться им так же, как и мне. Вы можете найти исходный код этого проекта на github. Ваше здоровье!

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