Doctrineって?
データベース操作って素でやるととっても面倒ですよね。
SQLゴリゴリ書いて、ごにょごにょやって、汚く長ったらしいコードの出来上がり。
もう少し簡潔に、OOPっぽく書きたいなーって時に使うといい感じに手抜きさせてくれるライブラリ、ORM(O/R マッパー)というものがあります。
ORMはPHPに限らずJavaや.NET等いろんな界隈でいろんな種類の物があります。
PHPではEloquent
やDoctrine
などいろんなORMライブラリがあります。
個人的にはDoctrine使っていこうかということでDoctrineのメモになります。
Doctrineはエンティティが特定の実装に依存しないピュアな設計なのと(POJO
とかPOCO
でググってください、PHPだとPOPO
かも)、
エンティティの一意性をいい感じに保障してくれるとか、.NETのEntity Framework
のように使えそうなのでこっちを選びました。
大まかな機能。
ざっくりコードでイメージしてください。
例えばデータベースに製品に関する情報を作成したいとします。
データベース(MySQL想定)では
CREATE TABLE Product(
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(124) NOT NULL
...
)
といったテーブルを定義すると思います。
ORMを使うと、
class Product
{
private int $id;
private string $name;
...
}
こういったクラスを作成すれば、クラスから自動的にテーブルを作成してくれます。
さらにデータベースからデータをとってくるときは通常次のようなSQLを投げますが、
SELECT * FROM Product;
ORMを使うとSQLを書く必要もなく次のようなPHPコードでProduct型の配列で取得できるようになります。
// Productにマップされたテーブルからデータを引っ張ってきて、Productクラスの配列で返す。
$products = $em->getRepository(Product::class)->findAll();
つまりクラスを作成すれば、それに基づいてテーブル操作やCRUDやってくれる便利なやつです。
インストール
まずはPHPがインストールされていること、Composerが使えることが前提です。
{
"require": {
"symfony/cache": "^6.0",
"doctrine/orm": "^2.11",
"doctrine/annotations": "^1.13"
},
"autoload": {
"psr-4": {
"App\\": "src/"
}
}
}
必要なもの
doctrine/orm
一番必要なもの。
symfony/cache
、あるいは最新のdoctrine/cache
ではなくver1.11
をインストールします。
無いとクラス定義からテーブルを作成する時にエラーになります。
doctrine/annotations
も必要なようです。
環境によってはこれが無いとエラーが出る場合があります。
Uncaught Error: Class "Doctrine\Common\Annotations\AnnotationRegistry" not found in
/doctrine-migration-test/vendor/doctrine/orm/lib/Doctrine/ORM/Configuration.php:165
"App\\": "src/"
autoloadもエンティティを使用する時必要になります。
この設定は、プロジェクトのsrcディレクトリ以降に置いたクラスが名前空間App
から始まるようにしてます。
例えば、my-projectがプロジェクトのルートで次のようにItem.phpを配置したら
/my-project/src/Entities/Item.php
namespaceやuseで使用する名前空間はこのようになります。
App\Entities\Item
エンティティの定義
まずテーブルとマップするクラスを作成します。
一般的にはクラスにアノテーションを付与します。
規則があるので注意してください。
早速Item
というクラスを定義します。
特に用途を考えず適当にメンバ変数を定義しました。
ファイルを/my-project/src/Entities/Item.php
に作成したとして。
namespace App\Entities;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
*/
class Item
{
/**
* @ORM\Id
* @ORM\Column
* @ORM\GeneratedValue
*/
private int $id;
/**
* @ORM\Column
*/
private string $name;
/**
* @ORM\Column
*/
private int $power;
public function __construct(string $name, int $power)
{
$this->name = $name;
$this->power = $power;
}
public function getId(): int
{
return $this->id;
}
public function getName(): string
{
return $this->name;
}
public function setName(string $name): void
{
$this->name = $name;
}
public function getPower(): int
{
return $this->power;
}
public function setPower(int $power): void
{
$this->power = $power;
}
}
アノテーションは次の名前空間を使います。
use Doctrine\ORM\Mapping as ORM;
以下アノテーションの説明です。
@ORM\Entity
クラスにこのアノテーションを付けると、このクラスはエンティティだぜ!ってこになります。
測定ではデータベースにはクラス名と同じProduct
テーブルが作成されるようになります。
@ORM\Column
メンバー変数に付けると、これはカラムですよってことになります。
@ORM\Id
メンバー変数に付けると、これはカラムでも主キーになりますって意味です。
@ORM\GeneratedValue
メンバー変数に付けると、これは自動インクリメントですって意味です。
クラス名はデータベースのテーブル名に、メンバ変数はそのままテーブルのカラム名になります。
もし名前を任意のものにしたければ
テーブル名を変更したければクラスに以下の属性を追加(products
になる)
@ORM\Table(name="products")
カラム名を変更したければメンバ変数を次のようにします。
@ORM\Column(name="onamae")
コマンドの用意。
エンティティを定義しただけでは何も置きません。
ターミナルからコマンドを実行することでテーブルの作成、削除などを行います。
そのための設定ファイル等が必要です。
プロジェクトディレクトリに以下のファイルを書きます。
今回作成するのは、接続情報、EntityManagerのインスタンス, CLIの設定ファイルの三つです。
- 接続情報は、DBの接続に必要なパスワードとか一式
- EntityManagerはDoctrineの中核的なクラスで多用する
- CLIの設定ファイルはコマンドラインからテーブル作成などの操作するために必要な設定ファイル
です。
接続情報
ファイル名は適当にconnection-settings.php
とでもします。
MySQLを使う場合は、
return [
'dbname' => 'doctrinetest',
'user' => 'root',
'password' => 'wwwwwwwwwwwwwwwwww',
'host' => 'localhost',
'driver' => 'pdo_mysql'
];
で、キーを見ると大体意味分かると思います。
使いやすく留守ため、単に連想配列を返すだけのPHPファイルを作りました。
EntityManagerのインスタンス作成
ファイル名は適当にcreateManager.php
にします。
require 'vendor/autoload.php';
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Tools\Setup;
// エンティティの置き場、今回は一つだけ/my-project/src/Entitiesに用意。
$path = __DIR__ . '/src/Entities';
// Doctrineの設定情報
$config = Setup::createAnnotationMetadataConfiguration(
[$path],
true,
null,
null,
false
);
// 接続情報
$conn = require 'connection-settings.php';
// EntityManagerを作成して返す
return EntityManager::create($conn, $config);
EntityManagerのインスタンスを作成するPHPファイルを用意しました。
これを使用する時は次のようにして作成することが出来るようになります。
$em = require 'createManager.php';
CLIの設定
プロジェクトディレクトリにcli-config.php
を作成します。
この名前は固定です。
$manager = require 'createManager.php';
return \Doctrine\ORM\Tools\Console\ConsoleRunner::createHelperSet($manager);
これでコマンドラインからテーブル操作が出来るようになります。
これまでのディレクトリ
これまで作成してきたファイルのディレクトリ構造。
[プロジェクトルート]
composer.json
src
Entities
Item.php
connection-config.php
createManager.php
cli-config.php
エンティティを増やす場合はsrc/Entities
にどんどん追加していきます。
コマンドの実行
とりあえず作成、削除のコマンドです。
テーブル作成のコマンド
まずはいきなりテーブルを作成せず、テーブル作成のSQLを吐き出します。
vendor/bin/doctrine orm:schema-tool:create --dump-sql
ターミナルからコマンドを実行すると
CREATE TABLE Item (
id INT AUTO_INCREMENT NOT NULL,
name VARCHAR(255) NOT NULL,
power INT NOT NULL,
PRIMARY KEY(id)
)
DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB;
SQLが吐き出されます。これは接続情報がMySQLの場合です。
src/Entitiesからエンティティを片っ端から拾った(今回はItem.phpだけ)SQLです。
もし複数合ったりリレーションがある場合はそれに応じたSQLが吐き出されます。
今度はSQL出力ではなく実際にテーブルを作成するコマンドです。
vendor/bin/doctrine orm:schema-tool:create
ちょっと警告されますが無視です。
[CAUTION] This operation should not be executed in a production environment!
成功したらデータベースに反映されているはずです。
テーブル削除のコマンド
vendor/bin/doctrine orm:schema-tool:drop --force
これで作成されたテーブルは無くなります。
あと、エンティティの定義を編集したばあい
vendor/bin/doctrine orm:schema-tool:update --force
もあります。
最後に
今回はエンティティを定義して、それからテーブルを作成、削除するための一連の流れを解説しました。
次からは実際にCRUDやっていきます。