データベースとドクトリン ORM
あらゆるアプリケーションにとって最も一般的かつ困難なタスクの 1 つは、データベースからデータ情報を読み取って保持することです。 symfony フレームワークはデータベースの使用を必要とするコンポーネントを統合していませんが、Doctrine と呼ばれるサードパーティのクラス ライブラリと緊密に統合されています。 Doctrine の主な目標は、データベースの操作をより簡単かつ柔軟にする強力なツールを提供することです。
この章では、symfony プロジェクトで豊富なデータベース インタラクションを提供するために doctrine を使用する方法を学びます。
Doctrine と symfony は完全に分離されており、それらの使用はオプションです。この章では、オブジェクトをリレーショナル データベース (MySQL、PostgreSQL、Microsoft SQL など) にマップできるようにすることを目的とした Doctrine ORM について説明します。データベースの生のクエリを使用したい場合、これは非常に簡単です。説明については、記事 Doctrine DBAL の使用方法 を参照してください。
Doctrine ODM クラス ライブラリを使用してデータを MongoDB に永続化することもできます。詳細については、DoctrineMongoDBBundle を参照してください。
簡単な例: 製品 ¶
Doctrine がどのように機能するかを理解する最も簡単な方法は、実際のアプリケーションを確認することです。このセクションでは、データベースを構成し、Product
オブジェクトを作成し、それをデータベースに保存してから取得する必要があります。
データベースの構成 ¶
実際に開始する前に、データベース接続情報を構成する必要があります。慣例により、情報のこの部分は通常、app/config/parameters.yml
ファイルで構成されます:
# app/config/parameters.ymlparameters: database_host: localhost database_name: test_project database_user: root database_password: password # ...
#から 設定を定義するためのパラメータ.yml
は単なる慣例です。 Doctrine を設定するとき、そのファイルで定義されたパラメータはメイン設定ファイルによって参照されます:
# app/config/config.ymldoctrine: dbal: driver: pdo_mysql host: "%database_host%" dbname: "%database_name%" user: "%database_user%" password: "%database_password%"
<!-- app/config/config.xml --><?xml version="1.0" encoding="UTF-8" ?><container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:doctrine="http://symfony.com/schema/dic/doctrine" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/doctrine http://symfony.com/schema/dic/doctrine/doctrine-1.0.xsd"> <doctrine:config> <doctrine:dbal driver="pdo_mysql" host="%database_host%" dbname="%database_name%" user="%database_user%" password="%database_password%" /> </doctrine:config></container>
// app/config/config.php$configuration->loadFromExtension('doctrine', array( 'dbal' => array( 'driver' => 'pdo_mysql', 'host' => '%database_host%', 'dbname' => '%database_name%', 'user' => '%database_user%', 'password' => '%database_password%', ),));
データベース情報を別のファイルに分割することで、サーバーごとに異なるバージョンを簡単に保存できます。たとえば、Apache の構成情報と同様に、データベース構成 (または機密情報) をプロジェクトの外部に簡単に保存することもできます。詳細については、サービス コンテナの外部パラメータを設定する方法を参照してください。
これで Doctrine がデータベースに接続できるようになりました。次のコマンドで空の test_project
データベースを自動的に生成できます:
$ php bin/console doctrine:database:create
SQLite をデータベースとして使用する場合は、パス オプションでデータベース パスを設定します。
# app/config/config.ymldoctrine: dbal: driver: pdo_sqlite path: "%kernel.root_dir%/sqlite.db" charset: UTF8
<!-- app/config/config.xml --><?xml version="1.0" encoding="UTF-8" ?><container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:doctrine="http://symfony.com/schema/dic/doctrine" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/doctrine http://symfony.com/schema/dic/doctrine/doctrine-1.0.xsd"> <doctrine:config> <doctrine:dbal driver="pdo_sqlite" path="%kernel.root_dir%/sqlite.db" charset="UTF-8" /> </doctrine:config></container>
// app/config/config.php$container->loadFromExtension('doctrine', array( 'dbal' => array( 'driver' => 'pdo_sqlite', 'path' => '%kernel.root_dir%/sqlite.db', 'charset' => 'UTF-8', ),));
エンティティの作成class ¶
いくつかの製品を表示する必要があるプログラムを構築しているとします。 Doctrine やデータベースについて考えなくても、これらの製品を表すには Product
オブジェクトが必要であることはすでにわかっています。このクラスを AppBundle の Entity
ディレクトリに作成します。
// src/AppBundle/Entity/Product.phpnamespace AppBundle\Entity; class Product{ private $name; private $price; private $description;}
このクラス - 多くの場合「エンティティ」と呼ばれ、データを保持する基本クラス - これはシンプルで、プログラムで必要な製品のビジネス ニーズを満たします。このクラスはまだデータベースに保存できません。これは単なる単純な PHP クラスです。
Doctrine の背後にある概念を学習したら、Doctrine にエンティティ クラスを作成させることができます。エンティティの作成に役立つ対話型の質問がいくつか表示されます:
$ php bin/console doctrine:generate:entity
マッピング情報の追加 ¶
Doctrine を使用すると、単にスカラー データの行を配列に取り込むのではなく、より興味深い方法でデータベースを使用できます。 Doctrine を使用すると、データベースから object 全体を取得し、同時にオブジェクト全体をデータベースに保存できます。 Doctrine でこれを実現するには、データテーブルを特定の PHP クラスに マップ する必要があり、それらのテーブルの列を対応する PHP クラスの特定の属性にマップする必要があります。
このマッピング情報を「ミートデータ」の形式で提供する必要があります。Doctrine に Product
クラスと プロパティを 特定のデータ テーブルにマッピングする方法。このメタデータは、YAML、XML などのさまざまな形式で指定することも、DocBlock アノテーション (アノテーション: アノテーション) を通じて Product
クラスに直接定義することもできます。バンドルは 1 つのメタデータ定義形式のみを受け入れることができます。たとえば、YAML メタデータ定義と、アノテーションが追加された PHP エンティティ クラスを混在させることはできません。
Doctrine では、それぞれ独自の設定を持つ幅広いフィールド タイプから選択できます。利用可能なフィールド タイプの詳細については、「Doctrine フィールド タイプ リファレンス」を参照してください。
Doctrine 公式ドキュメント Basic Mapping Documentation を参照して、マッピングに関するすべての詳細を学ぶこともできます。注釈を使用する場合は、すべての注釈に
ORM\) を追加する必要がありますが、これは Doctrine ドキュメントには記載されていません。また、use Doctrine\ORM\Mapping as ORM;
宣言を含める必要があります。これにより、import (インポート)
ORM
アノテーション プレフィックスを実行できます。
Group の場合、デフォルトではテーブル名は group になり、一部のデータベース エンジンで SQL エラーが発生する可能性があります。これらの名前を正しく回避する方法については、予約済み SQL キーワードのドキュメントを参照してください。オプションで、データベースのスキーマを任意に選択し、それを別のテーブル名または列名に簡単にマップできます。 「データベースおよびプロパティ マッピングのクラスの作成」ドキュメントを参照してください。
アノテーションを使用する他のライブラリまたはプログラム (Doxygen など) を使用する場合、@IgnoreAnnotation
アノテーションをクラスに追加して、Symfony がどのアノテーションを無視するかを示す必要があります。
たとえば、@fn
アノテーションが例外をスローしないようにするには、次のアノテーションを追加します。
// src/AppBundle/Entity/Product.phpnamespace AppBundle\Entity; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity * @ORM\Table(name="product") */class Product{ /** * @ORM\Column(type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @ORM\Column(type="string", length=100) */ private $name; /** * @ORM\Column(type="decimal", scale=2) */ private $price; /** * @ORM\Column(type="text") */ private $description;
エンティティを作成した後、次のコマンドを使用してマッピングを確認する必要があります:
# src/AppBundle/Resources/config/doctrine/Product.orm.ymlAppBundle\Entity\Product: type: entity table: product id: id: type: integer generator: { strategy: AUTO } fields: name: type: string length: 100 price: type: decimal scale: 2 description: type: text
ゲッターとセッターの生成 ¶
##Doctrine はその方法を認識しましたが、Product オブジェクトをデータベースに保存しますが、クラス自体にはまだ本当の目的がありません。
Product は
private プロパティを持つ通常の PHP クラスであるため、
public ゲッター メソッドとセッター メソッド (
getName()# など) を作成する必要があります # #, setName($name)
) を使用して、プログラムの他の部分にあるプロパティ (プロパティは保護されています) にアクセスします。幸いなことに、次のコマンドを使用すると、これらのテンプレート化されたメソッドを自動的に生成できます。
このコマンドにより、<!-- src/AppBundle/Resources/config/doctrine/Product.orm.xml --><?xml version="1.0" encoding="UTF-8" ?><doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"> <entity name="AppBundle\Entity\Product" table="product"> <id name="id" type="integer"> <generator strategy="AUTO" /> </id> <field name="name" type="string" length="100" /> <field name="price" type="decimal" scale="2" /> <field name="description" type="text" /> </entity></doctrine-mapping>
クラスのすべてのゲッターとセッターが確実に生成されます。これは安全なコマンド ラインです。複数回実行でき、存在しないゲッターとセッターのみが生成されます (つまり、既存のメソッドは置き換えられません)。
次の文は非常に奥深く、Doctrine を効果的に使用するための鍵となります。誰もがそれをしなければなりません。
Doctrine エンティティ ジェネレーターは単純なゲッター/セッターを生成することを覚えておいてください。生成されたメソッドを確認し、必要に応じてアプリケーションのニーズを満たすロジックを追加する必要があります。