Symfony-Doctrine ORM

Symfony Webフレームワークでは、モデルが重要な役割を果たします。彼らは事業体です。それらは顧客によって提供されるか、バックエンドデータベースからフェッチされ、ビジネスルールに従って操作され、データベースに永続化されます。これらは、ビューによって提示されるデータです。この章では、モデルと、モデルがバックエンドシステムとどのように相互作用するかについて学びましょう。

データベースモデル

モデルを安全かつ効率的にフェッチして永続化するには、モデルをバックエンドのリレーショナルデータベースアイテムにマッピングする必要があります。このマッピングは、オブジェクトリレーショナルマッピング(ORM)ツールを使用して実行できます。symfonyは別のバンドルを提供しますDoctrineBundle、SymfonyをサードパーティのPHPデータベースORMツールと統合します。 Doctrine

Doctrine ORM

デフォルトでは、Symfonyフレームワークはデータベースを操作するためのコンポーネントを提供しません。しかし、それは緊密に統合されていますDoctrine ORM。Doctrineには、データベースストレージとオブジェクトマッピングに使用されるいくつかのPHPライブラリが含まれています。

次の例は、Doctrineがどのように機能するか、データベースを構成する方法、およびデータを保存および取得する方法を理解するのに役立ちます。

DoctrineORMの例

この例では、最初にデータベースを構成してStudentオブジェクトを作成し、次にその中でいくつかの操作を実行します。

これを行うには、次の手順に従う必要があります。

ステップ1:Symfonyアプリケーションを作成する

symfonyアプリケーションを作成し、 dbsample 次のコマンドを使用します。

symfony new dbsample

ステップ2:データベースを構成する

通常、データベース情報は「app / config /parameters.yml」ファイルで構成されます。

ファイルを開き、次の変更を追加します。

parameter.yml

parameters: 
   database_host: 127.0.0.1 
   database_port: null
   database_name: studentsdb 
   database_user: <user_name> 
   database_password: <password> 
   mailer_transport: smtp 
   mailer_host: 127.0.0.1 
   mailer_user: null 
   mailer_password: null 
   secret: 037ab82c601c10402408b2b190d5530d602b5809 
   
   doctrine: 
      dbal: 
      driver:   pdo_mysql 
      host:     '%database_host%' 
      dbname:   '%database_name%' 
      user:     '%database_user%' 
      password: '%database_password%' 
      charset: utf8mb4

これで、DoctrineORMはデータベースに接続できます。

ステップ3:データベースを作成する

次のコマンドを発行して、「studentsdb」データベースを生成します。このステップは、DoctrineORMでデータベースをバインドするために使用されます。

php bin/console doctrine:database:create

コマンドを実行すると、空の「studentsdb」データベースが自動的に生成されます。画面に次の応答が表示されます。

Created database `studentsdb` for connection named default

ステップ4:地図情報

マッピング情報は「メタデータ」に他なりません。これは、Studentクラスとそのプロパティが特定のデータベーステーブルにどのようにマッピングされるかをDoctrineORMに正確に通知するルールのコレクションです。

このメタデータは、YAML、XMLなど、さまざまな形式で指定できます。または、アノテーションを使用してStudentクラスを直接渡すこともできます。それは次のように定義されます。

Student.php

次の変更をファイルに追加します。

<?php  
namespace AppBundle\Entity;  

use Doctrine\ORM\Mapping as ORM;  
/** 
   * @ORM\Entity 
   * @ORM\Table(name = "students") 
*/ 
class Student { 
   /** 
      * @ORM\Column(type = "integer") 
      * @ORM\Id 
      * @ORM\GeneratedValue(strategy = "AUTO") 
   */ 
   private $id;  
    
   /** 
      * @ORM\Column(type = "string", length = 50) 
   */ 
   private $name;  
   
   /** 
     * @ORM\Column(type = "text") 
     */ 
   private $address; 
}

ここで、テーブル名はオプションです。テーブル名が指定されていない場合は、エンティティクラスの名前に基づいて自動的に決定されます。

ステップ5:エンティティをバインドする

Doctrineはあなたのために単純なエンティティクラスを作成します。エンティティを構築するのに役立ちます。

次のコマンドを発行して、エンティティを生成します。

php bin/console doctrine:generate:entities AppBundle/Entity/Student

次に、次の結果が表示され、エンティティが更新されます。

Generating entity "AppBundle\Entity\Student" 
   > backing up Student.php to Student.php~ 
   > generating AppBundle\Entity\Student

Student.php

<?php 
namespace AppBundle\Entity; 

use Doctrine\ORM\Mapping as ORM;  
/** 
   * @ORM\Entity 
   * @ORM\Table(name="students") 
*/ 
class Student { 
   /** 
      * @ORM\Column(type="integer") 
      * @ORM\Id 
      * @ORM\GeneratedValue(strategy="AUTO") 
   */ 
   private $id;  
    
   /** 
      * @ORM\Column(type = "string", length = 50) 
   */ 
   private $name; 
    
   /** 
      * @ORM\Column(type = "text") 
   */
   private $address; 
    
   /** 
      * Get id 
      * 
      * @return integer 
   */ 
   public function getId() { 
      return $this->id; 
   }  
    
   /** 
      * Set name 
      * 
      * @param string $name 
      * 
      * @return Student 
   */ 
    
   public function setName($name) { 
      $this->name = $name;  
      return $this; 
   }  
    
   /** 
      * Get name 
      * 
      * @return string 
   */ 
    
   public function getName() { 
      return $this->name; 
   }  
    
   /**
      * Set address 
      * 
      * @param string $address 
      * 
      * @return Student 
   */ 
    
   public function setAddress($address) { 
      $this->address = $address;  
      return $this; 
   }  
    
   /** 
      * Get address 
      * 
      * @return string 
   */ 
   
   public function getAddress() { 
      return $this->address; 
   } 
}

ステップ6:マップの検証

エンティティを作成したら、次のコマンドを使用してマッピングを検証する必要があります。

php bin/console doctrine:schema:validate

次の結果が得られます-

[Mapping]  OK - The mapping files are correct. 
[Database] FAIL - The database schema is not in sync with the current mapping file

学生テーブルを作成していないため、エンティティは同期していません。次のステップでSymfonyコマンドを使用してstudentsテーブルを作成しましょう。

ステップ7:スキーマを作成する

Doctrineは、Studentエンティティに必要なすべてのデータベーステーブルを自動的に作成できます。これは、次のコマンドを使用して実行できます。

php bin/console doctrine:schema:update --force

コマンドを実行すると、次の応答が表示されます。

Updating database schema... 
Database schema updated successfully! "1" query was executed

このコマンドは、データベースの外観と実際の外観を比較し、データベーススキーマを本来の場所に更新するために必要なSQLステートメントを実行します。

ここで、次のコマンドを使用してスキーマを再度検証します。

php bin/console doctrine:schema:validate

次の結果が得られます-

[Mapping]  OK - The mapping files are correct. 
[Database] OK - The database schema is in sync with the mapping files

ステップ8:ゲッターとセッター

[エンティティのバインド]セクションに示されているように、次のコマンドは、Studentクラスのすべてのゲッターとセッターを生成します。

$ php bin/console doctrine:generate:entities AppBundle/Entity/Student

ステップ9:オブジェクトをデータベースに永続化する

これで、Studentエンティティを対応するStudentテーブルにマップしました。これで、Studentオブジェクトをデータベースに永続化できるようになります。バンドルのStudentControllerに次のメソッドを追加します。

StudentController.php

<?php  
namespace AppBundle\Controller; 

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; 
use Symfony\Bundle\FrameworkBundle\Controller\Controller; 
use Symfony\Component\HttpFoundation\Response;  
use AppBundle\Entity\Student; 

class StudentController extends Controller { 
   /** 
      * @Route("/student/add") 
   */ 
   public function addAction() { 
      $stud = new Student(); 
      $stud->setName('Adam'); 
      $stud->setAddress('12 north street'); 
      $doct = $this->getDoctrine()->getManager();
      
      // tells Doctrine you want to save the Product 
      $doct->persist($stud);
      
      //executes the queries (i.e. the INSERT query) 
      $doct->flush(); 
      
      return new Response('Saved new student with id ' . $stud->getId()); 
   } 
}

ここでは、ベースコントローラーのgetDoctrine()を介してgetManager()メソッドを使用してDoctrine Managerにアクセスし、Doctrine Managerのpersist()メソッドを使用して現在のオブジェクトを永続化します。 persist() メソッドはコマンドをキューに追加しますが、 flush() メソッドは実際の作業を行います(学生オブジェクトを永続化します)。

ステップ10:データベースからオブジェクトをフェッチする

StudentControllerで、学生の詳細を表示する関数を作成します。

StudentController.php

/** 
   * @Route("/student/display") 
*/ 
public function displayAction() { 
   $stud = $this->getDoctrine() 
   ->getRepository('AppBundle:Student') 
   ->findAll();
   return $this->render('student/display.html.twig', array('data' => $stud)); 
}

ステップ11:ビューを作成する

表示アクションを指すビューを作成しましょう。viewsディレクトリに移動し、ファイル「display.html.twig」を作成します。次の変更をファイルに追加します。

display.html.twig

<style> 
   .table { border-collapse: collapse; } 
   .table th, td { 
      border-bottom: 1px solid #ddd; 
      width: 250px; 
      text-align: left; 
      align: left; 
   } 
</style> 

<h2>Students database application!</h2>  
<table class = "table">  
   <tr>  
      <th>Name</th>  
      <th>Address</th>  
   </tr>  
   {% for x in data %} 
   <tr>  
      <td>{{ x.Name }}</td>   
      <td>{{ x.Address }}</td>   
   </tr>  
   {% endfor %} 
</table>

ブラウザでURL「http:// localhost:8000 / student / display」をリクエストすると、結果を取得できます。

画面に次の出力が表示されます-

ステップ12:オブジェクトを更新する

StudentControllerでオブジェクトを更新するには、アクションを作成し、次の変更を追加します。

/** 
   * @Route("/student/update/{id}") 
*/ 
public function updateAction($id) { 
   $doct = $this->getDoctrine()->getManager(); 
   $stud = $doct->getRepository('AppBundle:Student')->find($id);  
   
   if (!$stud) { 
      throw $this->createNotFoundException( 
         'No student found for id '.$id 
      ); 
   } 
   $stud->setAddress('7 south street'); 
   $doct->flush(); 
   
   return new Response('Changes updated!'); 
}

ここで、URL「http:// localhost:8000 / Student / update / 1」をリクエストすると、次の結果が生成されます。

画面に次の出力が表示されます-

ステップ13:オブジェクトを削除する

オブジェクトの削除も同様であり、エンティティ(doctrine)マネージャーのremove()メソッドを呼び出す必要があります。

これは、次のコマンドを使用して実行できます。

/** 
   * @Route("/student/delete/{id}") 
*/ 
public function deleteAction($id) { 
   $doct = $this->getDoctrine()->getManager(); 
   $stud = $doct->getRepository('AppBundle:Student')->find($id);  
    
   if (!$stud) { 
      throw $this->createNotFoundException('No student found for id '.$id); 
   }  
    
   $doct->remove($stud); 
   $doct->flush();  
   
   return new Response('Record deleted!'); 
}