🎣

Symfony+API Platformを動かしてみた

2023/07/22に公開

はじめに

本記事では、PHP + Symfony + API PlatformDocker上で実行することを目指します。

環境・バージョン

  • ローカル環境
    • macOS Ventura 13.4.1(c)
  • Docker環境
    • PHP: 8.2
      • Symfony: 6.3系
      • api-platform: 3.1
    • MySQL: 8.0

コンテナ立ち上げからAPI実行まで

コード

本記事のコードはGitHubにありますので、適宜確認ください。

ディレクトリ構成とDockerfile

ディレクトリ構成は次のようになっています。

.
├── backend
│  └── src 👈 PHPのプロジェクトのディレクトリ(最初は空っぽ)
├── docker
│  ├── nginx
│  │  ├── default.conf
│  │  └── Dockerfile
│  └── php
│     ├── Dockerfile
│     └── php.ini
└── docker-compose.yaml

PHPのDockerfileは以下のように作成しました。
本記事では利用しないパッケージもこのタイミングでインストールしています。

docker/php/Dockerfile
FROM php:8.2-fpm

COPY php.ini /usr/local/etc/php/conf.d/docker-php-config.ini

RUN apt-get update && apt-get install -y \
    gnupg \
    g++ \
    procps \
    openssl \
    git \
    unzip \
    zlib1g-dev \
    libzip-dev \
    libfreetype6-dev \
    libpng-dev \
    libjpeg-dev \
    libicu-dev  \
    libonig-dev \
    libxslt1-dev \
    acl

RUN pecl install apcu redis
RUN docker-php-ext-enable apcu
RUN docker-php-ext-enable redis
RUN docker-php-ext-configure gd --with-jpeg --with-freetype
RUN docker-php-ext-install pdo pdo_mysql zip xsl gd intl opcache exif mbstring

WORKDIR /var/www/zenn_example

# php extensions installer: https://github.com/mlocati/docker-php-extension-installer
COPY --from=composer /usr/bin/composer /usr/bin/composer

RUN curl -sS https://get.symfony.com/cli/installer | bash
RUN mv /root/.symfony5/bin/symfony /usr/local/bin/symfony

PHPのDockerfileを利用している、docker-compose.yamlファイルです。

docker-compose.yaml
version: "3.8"

services:
  
  php:
    build:
      context: docker/php
    container_name: zenn-php-symfony
    restart: unless-stopped
    volumes:
      - ./backend/src:/var/www/zenn_example
    healthcheck:
      interval: 10s
      timeout: 3s
      retries: 3
      start_period: 30s

  nginx:
    build:
      context: docker/nginx
    container_name: zenn-nginx-symfony
    ports:
      - "8080:80"
    volumes:
      - ./backend/src:/var/www/zenn_example
    depends_on:
      - php

  mysql:
    image: mysql:8.0
    container_name: zenn-mysql-symfony
    volumes:
      - ./volumes/mysql:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: zenn_example
      MYSQL_USER: symfony
      MYSQL_PASSWORD: symfony

その他のファイルについては、GitHubを参照してください。

立ち上げ

ディレクトリ直下で以下のコマンドを実行し、zenn-php-symfonyコンテナ内に入ります。

$ docker compose up --build
$ docker compose exec -it php /bin/bash

初期化とパッケージのインストール

ここからは全てコンテナ内での操作です。
インストールされているSymfonyのバージョンを確認します。

$ symfony -V
Symfony CLI version 5.5.7 (c) 2021-2023 Fabien Potencier #StandWithUkraine Support Ukraine (2023-07-21T10:15:00Z - stable)

Symfonyの5.5系が入っていることを確認し、新しいプロジェクトを作成します。

$ symfony new . -no-git
(...中略)
 [OK] Your project is now ready in /var/www/zenn_example

必要なパッケージをインストールします。途中で聞かれる質問はnで大丈夫です。

$ composer require doctrine twig orm api
(...中略)
    This may create/update docker-compose.yml or update Dockerfile (if it exists).

    Do you want to include Docker configuration from recipes?
    [y] Yes
    [n] No
    [p] Yes permanently, never ask again for this project
    [x] No permanently, never ask again for this project
    (defaults to y): n

$ composer require symfony/maker-bundle maker ormfixtures --dev

設定の編集

最初に環境変数ファイルをコピーします。

$ cp .env .env.local

環境変数ファイルを以下の箇所を変更します。

.env.local
- DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=15&charset=utf8"
+ DATABASE_URL="mysql://root:secret@zenn-mysql-symfony:3306/zenn_example?serverVersion=8.0"

エンティティの作成

以下のコマンドを実行すると、実行可能コマンドの一覧が出てきます。
今回はそのうちのmake:entityコマンドを使います。

$ symfony console
(...前略)
  make:entity                                Creates or updates a Doctrine entity class, and optionally an API Platform resource
(...後略)

例として、Bookエンティティを作ってみます。
対話形式で必要なフィールドを入力していくとクラスを作成してくれます。

$ symfony console make:entity Book
 created: src/Entity/Book.php
 created: src/Repository/BookRepository.php

 Entity generated! Now let's add some fields!
 You can always add more fields later manually or by re-running this command.

 New property name (press <return> to stop adding fields):
 > title

 Field type (enter ? to see all types) [string]:
 > string

 Field length [255]:
 >

 Can this field be null in the database (nullable) (yes/no) [no]:
 >

 updated: src/Entity/Book.php

 Add another property? Enter the property name (or press <return> to stop adding fields):
 > author

 Field type (enter ? to see all types) [string]:
 > string

 Field length [255]:
 >

 Can this field be null in the database (nullable) (yes/no) [no]:
 >

 updated: src/Entity/Book.php

 Add another property? Enter the property name (or press <return> to stop adding fields):
 >



  Success!


 Next: When you're ready, create a migration with symfony console make:migration

以下に自動作成されたエンティティを載せておきます。

作成されたエンティティ。
src/Entity/Book
<?php

namespace App\Entity;

use App\Repository\BookRepository;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity(repositoryClass: BookRepository::class)]
class Book
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 255)]
    private ?string $title = null;

    #[ORM\Column(length: 255)]
    private ?string $author = null;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getTitle(): ?string
    {
        return $this->title;
    }

    public function setTitle(string $title): static
    {
        $this->title = $title;

        return $this;
    }

    public function getAuthor(): ?string
    {
        return $this->author;
    }

    public function setAuthor(string $author): static
    {
        $this->author = $author;

        return $this;
    }
}

マイグレーション

エンティティ作成時に指示されたコマンドを実行するだけで、versionファイルが作成されます。

$ symfony console make:migration
 created: migrations/Version20230721135723.php
 
  Success!

 Review the new migration then run it with symfony console doctrine:migrations:migrate
(...後略)

生成されたファイルを確認して問題なければ、以下のコマンドでマイグレーションを実行します。

$ symfony console doctrine:migrations:migrate
 WARNING! You are about to execute a migration in database "zenn_example" that could result in schema changes and data loss. Are you sure you wish to continue? (yes/no) [yes]:
 >

[notice] Migrating up to DoctrineMigrations\Version20230721135723
[notice] finished in 23.3ms, used 16M memory, 1 migrations executed, 1 sql queries

 [OK] Successfully migrated to version : DoctrineMigrations\Version20230721135723

MySQLのコンテナに入って確認してみます。

# ローカルから実行
$ docker compose exec -it mysql /bin/bash
bash-4.4# mysql -usymfony -p -h localhost zenn_example
Enter password: (symfonyと入力)

mysql> show tables;
+-----------------------------+
| Tables_in_zenn_example      |
+-----------------------------+
| book                        |
| doctrine_migration_versions |
+-----------------------------+
2 rows in set (0.00 sec)

mysql> desc `book`;
+--------+--------------+------+-----+---------+----------------+
| Field  | Type         | Null | Key | Default | Extra          |
+--------+--------------+------+-----+---------+----------------+
| id     | int          | NO   | PRI | NULL    | auto_increment |
| title  | varchar(255) | NO   |     | NULL    |                |
| author | varchar(255) | NO   |     | NULL    |                |
+--------+--------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)

意図したbookテーブルが作成されていることが確認できました。

CRUDのAPI作成

最後にAPI Platformの機能を使って、単純なCURDのAPIを作成します。
最も単純なパターンは以下に2箇所コードを追記するだけです。

src/Entity/Book.php
<?php

namespace App\Entity;

use App\Repository\BookRepository;
+ use ApiPlatform\Metadata\ApiResource;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity(repositoryClass: BookRepository::class)]
+ #[ApiResource]
class Book
{
(...後略)

追記したらhttp://localhost:8080/api にアクセスします。

この画面で適当なAPIを叩いてみます。

すると以下の結果が返ってきます。

データベースを覗いてみるとデータが入っていることが確認できます。

# mysqlのコンテナ
mysql> select * from book;
+----+----------------+-------------+
| id | title          | author      |
+----+----------------+-------------+
|  1 | zenn-example-1 | some author |
+----+----------------+-------------+
1 row in set (0.00 sec)

GET /api/books/1を実行しても結果が返ってくることが確認できました。

おわりに

Bookエンティティに対してCRUDのAPIを作成しました。
これからAPI Platformの機能を利用してAPIを作成していきたいです。

https://zenn.dev/gsy0911/articles/8c1eaef195c857

参考文献

GitHubで編集を提案

Discussion