LoginSignup
0
0

【PHP】マイナーフレームワーク「Flow」を試してみる~DB接続&データ登録編~

Last updated at Posted at 2023-11-25

初めに

前回はこちらの記事でマイナフレームワークFlowを使った簡単なAPI作成を行いました。
今回はMySQLにデータを登録するAPIを作成していきます。

FlowにおけるDB接続処理

Flowはdoctrineと呼ばれるORMを内包しています。
今回はこのライブラリを用いてTBL作成やDB接続を行っていきます。

doctrineでできること

doctrineはORM形式でDB操作を行います。
具体的には以下のような特徴を持ちます。

  • SELECTなどのDMLを記載する必要がなく、doctrineで用意されているメソッドを利用してDB操作を行う。
  • 事前のテーブル作成が不要。1つのTBL対応するデータクラスを作成し、doctrine のmigrateコマンドを実行することでTBL作成を行う。

DB接続試してみた

ということで、DB接続を行うAPIを作成していきましょう。
今回は商品情報を登録するAPIを作成していきます。

  • リクエストで商品情報を受け取る
  • 商品TBLにデータを登録
  • レスポンスで商品情報を返す

商品TBLは以下です。

論理名 物理名 データ型 その他制約
商品名 item_name varchar(20) NOT NULL
商品説明 description varchar(100)
価格 price int(11) NOT NULL

プロジェクト構成は以下です。
ControllerからRepositoryを呼び出してデータを登録するというシンプルな作りにします。

Quickstart
    ├ Configration/
    |    └ Settings.yaml(★)
    └ Packages/
         ├ Application/
         |    └ Neos.Welcome/
         |         └ Classes/
         |              ├ Controller/
         |              |    └ ItemController.php(★)
         |              └ Domain/
         |                   ├ Model
         |                   |    └ Item.php(★)
         |                   └ Repository
         |                        └ ItemRepository.php(★)
         ├ Framework/
         └ Libraries/

環境

  • OS:Windows11 Pro
  • PHP:8.1.25
  • Flow:8.3.5
  • composer:2.6.5
  • MySQL:5.7.43
  • doctrine:2.17.1

0.事前手順

まずは事前準備として以下の2つを行います。

  • MySQLの構築
  • Flow側のMySQL接続設定

MySQLの構築

ローカルにMySQLを構築しておきましょう。
今回はdockerを用いて作成しました。

以下のdocker-compose.ymlを用意し、docker compose up -dを実行しました。

docker-compose.yml
# docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: mydatabase
    ports:
      - "3306:3306"

volumes:
  db_data: {}

docker compose up -dコマンドを実行しコンテナを起動します。

$ docker compose up -d
[+] Running 3/3
 ✔ Network docker_default   Created                                                                                                                     0.0s
 ✔ Volume "docker_db_data"  Created                                                                                                                     0.0s
 ✔ Container docker-db-1    Started

Flow側のMySQL接続設定

FlowではConfigration直下にあるSettings.yamlにMySQLの接続設定を記載します。
以下のように記載しました。

Settings.yaml
Neos:
  Flow:
    persistence:
      backendOptions:
        driver: 'pdo_mysql'
        charset: 'utf8mb4'
        host: '127.0.0.1'    # Docker service name
        dbname: 'mydatabase'  # Database name
        user: 'root'  # MySQL user
        password: 'root'  # MySQL password
        port: '3306'  # MySQL port
        driverOptions:
          1002: 'SET SESSION wait_timeout=5'

1.Modelクラス作成

doctrineを使用してTBL作成を行います。
flowに用意されているkickstart:modelコマンドを実行してItemクラスを作成しました。

$ ./flow kickstart:model Neos.Welcome Item
Created .../Neos.Welcome/Classes/Domain/Model/Item.php
Created .../Neos.Welcome/Tests/Unit/Domain/Model/ItemTest.php
As a new model was generated, don't forget to update the database schema with the respective doctrine:* commands.
Item.php
<?php
namespace Neos\Welcome\Domain\Model;

/*
 * This file is part of the Neos.Welcome package.
 */

use Neos\Flow\Annotations as Flow;
use Doctrine\ORM\Mapping as ORM;

/**
 * @Flow\Entity
 */
class Item
{


}

モデルが作成できました。
このままではdoctrineを用いたマイグレーションができないので、いくつか修正していきます。

テーブルとの紐づけ

classに@ORM\Tableというアノテーションを追加し、紐づけるテーブル名を記載しました。

/**
 * @Flow\Entity
 * @ORM\Table(name="item")
 */
class Item

テーブルカラムの作成

@ORM\Columnアノテーションを付与したメンバ変数をいくつか作成しました。
これが商品TBLのカラムになります。
@ORM\Columnでtypeやuniqueなどを指定することで、カラムの属性を決めることができます。

    /**
     * @ORM\Column(type="string", name="item_name", length=20, nullable=false, unique=true)
     * @var string
     */
    protected $name;

@varがない場合や、アクセス修飾子がの場合、privateとdoctrineがカラムとして読み込まれませんので注意が必要です。

コンストラクタも追加し、最終的には以下のようになりました。

<?php
namespace Neos\Welcome\Domain\Model;

use Neos\Flow\Annotations as Flow;
use Doctrine\ORM\Mapping as ORM;

/**
 * @Flow\Entity
 * @ORM\Table(name="item")
 */
class Item
{

    /**
     * @ORM\Column(type="string", name="item_name", length=20, nullable=false, unique=true)
     * @var string
     */
    protected $name;

    /**
     * @ORM\Column(type="string", length=100)
     * @var string
     */
    protected $description;

    /**
     * @ORM\Column(type="integer", nullable=false)
     * @var int
     */
    protected $price;

    public function __construct(string $name, string $description, int $price)
    {
        $this->name = $name;
        $this->description = $description;
        $this->price = $price;
    }

}

この時、./flow doctrine:validateを実行することで、文法的に問題がないかどうかを確認することができます。

$ ./flow doctrine:validate

Mapping validation passed, no errors were found.

2.TBL作成

作成されたmodel元にテーブルを作成してきます。
テーブル作成は以下の2ステップです。

  • doctrine:migrateの実行
  • doctrine:updateの実行

doctrine:migrateの実行

まず初めに、flowのdoctrine:migrateコマンドを実行しましょう。
このコマンドで、doctrineの実行自体に必要なTBLなどのデータが作成されます。

$ ./flow doctrine:migrate
Migrating up to Neos\Flow\Persistence\Doctrine\Migrations\Version20200908155620

     -> CREATE TABLE flow3_resource_resourcepointer (hash VARCHAR(255) NOT NULL, PRIMARY KEY(hash)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB


~中略~


[warning] Migration Neos\Flow\Persistence\Doctrine\Migrations\Version20150611154419 was executed but did not result in any SQL statements.
[notice] finished in 1309.4ms, used 36M memory, 27 migrations executed, 93 sql queries

warningは出てますが、実行自体は完了しTBLが作成されました。

mysql> show tables
    -> ;
+-------------------------------------------------+
| Tables_in_mydatabase                            |
+-------------------------------------------------+
| flow_doctrine_migrationstatus                   |
| neos_flow_mvc_routing_objectpathmapping         |
| neos_flow_resourcemanagement_persistentresource |
| neos_flow_security_account                      |
+-------------------------------------------------+
4 rows in set (0.00 sec)

doctrine:updateの実行

続いてdoctrine:updateコマンドを実行します。
このコマンドにより、先ほど作成した商品TBLが作成されます。

$ ./flow doctrine:update
Executed a database schema update.
mysql> show tables
    -> ;
+-------------------------------------------------+
| Tables_in_mydatabase                            |
+-------------------------------------------------+
| flow_doctrine_migrationstatus                   |
| item                                            |
| neos_flow_mvc_routing_objectpathmapping         |
| neos_flow_resourcemanagement_persistentresource |
| neos_flow_security_account                      |
+-------------------------------------------------+
5 rows in set (0.00 sec)
mysql> 

商品TBLの詳細は以下です。モデルので定義した情報が設定されていることが確認できました。


mysql> show create table item\G
*************************** 1. row ***************************
       Table: item
Create Table: CREATE TABLE `item` (
  `persistence_object_identifier` varchar(40) COLLATE utf8mb4_unicode_ci NOT NULL,
  `item_name` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
  `description` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
  `price` int(11) NOT NULL,
  PRIMARY KEY (`persistence_object_identifier`),
  UNIQUE KEY `UNIQ_1F1B251E96133AFD` (`item_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
1 row in set (0.00 sec)

persistence_object_identifierというカラムが作成されてますが、これはdoctrineがテーブル管理に用いている主キーのようです。doctrineを用いてTBLを作成する際はこのIDのカラムが自動的に付与されます。

3.Repositoryクラス作成

続いて商品TBLを操作するためのItemRepositoryを作成していきます。
flowのkickstart:repositoryコマンドを用いて作成しました。

$ ./flow kickstart:repository Neos.Welcome Item
Created .../Neos.Welcome/Classes/Domain/Repository/ItemRepository.php
ItemRepository.php
<?php
namespace Neos\Welcome\Domain\Repository;

/*
 * This file is part of the Neos.Welcome package.
 */

use Neos\Flow\Annotations as Flow;
use Neos\Flow\Persistence\Repository;

/**
 * @Flow\Scope("singleton")
 */
class ItemRepository extends Repository
{

    // add customized methods here
}

このままではDB登録できないので、データを登録する用のメソッドを追加しました。


<?php
namespace Neos\Welcome\Domain\Repository;

use Neos\Flow\Annotations as Flow;
use Neos\Flow\Persistence\Repository;
use Neos\Welcome\Domain\Model\Item;

/**
 * @Flow\Scope("singleton")
 */
class ItemRepository extends Repository
{
    /**
     * @param string $name
     * @param string $description
     * @return void
     */
    public function addItem(string $name, string $description, int $price): void
    {
        // 商品モデルにデータを詰める
        $item = new Item($name, $description, $price);

        // 商品TBLへデータをINSERT
        $this->add($item);
    }

}

$this->add($item);にて、Flowのフレームワークを介してdoctrineで定義されたデータ登録用のメソッドを呼び出しているみたいです。

4.Controller作成

リクエストを受け取るためのControlerを作成します。
この辺は前回の記事で書いたような手順で作成しました。

ItemController.php
<?php
namespace Neos\Welcome\Controller;

use Neos\Flow\Annotations as Flow;
use Neos\Flow\Mvc\Controller\ActionController;

class ItemController extends ActionController
{

    /**
     * @Flow\Inject
     * @var \Neos\Flow\Mvc\View\JsonView
     */
    protected $view;

    /**
     * @Flow\Inject
     * @var \Neos\Welcome\Domain\Repository\ItemRepository
     */
    protected $itemRepository;
    
    public function postItemAction(string $name, string $description, int $price)
    {
        $this->itemRepository->addItem($name, $description, $price);
        $this->view->assign('value', array(
            "postedItem" => array(
                "name" => $name,
                "description" => $description,
                "price" => $price
            )
        ));
    }
}

5.動作確認

ローカルで動作確認していきます。
まずはサーバを起動します。

$ ./flow server:run
Server running. Please go to http://127.0.0.1:8081 to browse the application.
[Sat Nov 25 14:06:38 2023] PHP 8.1.25 Development Server (http://127.0.0.1:8081) started

サーバが起動できたので、リクエストを送ってみます。
リクエストパラメータは以下です。

image.png

実際に送ったjsonはこちら
リクエストBody
{
    "name": "Item Name",
    "description": "Item Description",
    "price": 100
}

レスポンスは200で返ってきました。
Bodyも問題なさそうです。

image.png

DBにも問題なくデータが登録されていることが確認できました。

mysql> select * from item
    -> ;
+--------------------------------------+-----------+------------------+-------+
| persistence_object_identifier        | item_name | description      | price |
+--------------------------------------+-----------+------------------+-------+
| 1d89b35b-0df6-4233-9ea9-8927e52cc4cc | Item Name | Item Description |   100 |
+--------------------------------------+-----------+------------------+-------+
1 row in set (0.00 sec)

終わりに

今回はFlowにおけるDB登録を行いました。
今回は簡単なTBLを使用してデータ登録を行いましたが、リレーションがもっと複雑な場合はどうなるかなどはまだ理解しきれていません。
次はそのあたりも調べたいですね。
分かり次第またまとめようと思います。

参考資料

https://flowframework.readthedocs.io/en/stable/Quickstart/index.html
https://webukatu.com/wordpress/blog/30447/
https://weblabo.oscasierra.net/php-composer-windows-install/
https://www.doctrine-project.org/

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0