Переглянути джерело

ORM: building ManyToOne / OneToMany relationships.

Frederic G. MARAND 6 роки тому
батько
коміт
3d407afd91

+ 59 - 0
src/Entity/Category.php

@@ -0,0 +1,59 @@
+<?php
+
+namespace App\Entity;
+
+use Doctrine\ORM\Mapping as ORM;
+
+/**
+ * @ORM\Entity(repositoryClass="App\Repository\CategoryRepository")
+ */
+class Category
+{
+  /**
+   * @ORM\Id
+   * @ORM\GeneratedValue
+   * @ORM\Column(type="integer")
+   */
+  private $id;
+
+  /**
+   * @ORM\Column(type="string")
+   */
+  private $name;
+
+  /**
+   * The OneToMany annotation is NOT required unless the associated access is
+   * needed. If not set mappedBy on Category.products and inversedBy on
+   * Product.category are not needed.
+   *
+   * @ORM\OneToMany(
+   *   targetEntity = "App\Entity\Product",
+   *   mappedBy = "category"
+   * )
+   */
+  private $products;
+
+  /**
+   * @return mixed
+   */
+  public function getId() {
+    return $this->id;
+  }
+
+  /**
+   * @return mixed
+   */
+  public function getName() {
+    return $this->name;
+  }
+
+  /**
+   * @param mixed $name
+   *
+   * @return Category
+   */
+  public function setName($name) {
+    $this->name = $name;
+    return $this;
+  }
+}

+ 31 - 0
src/Entity/Product.php

@@ -16,6 +16,20 @@ use Doctrine\ORM\Mapping as ORM;
  */
 class Product
 {
+
+  /**
+   * The ManyToOne annotation is required to build the relation.
+   *
+   * @ORM\ManyToOne(
+   *   targetEntity = "App\Entity\Category",
+   *   inversedBy = "products"
+   * )
+   * @ORM\JoinColumn(
+   *   nullable = true
+   * )
+   */
+  private $category;
+
   /**
    * @ORM\Column(type="text"))
    */
@@ -38,6 +52,13 @@ class Product
    */
   private $price;
 
+  /**
+   * @return mixed
+   */
+  public function getCategory() {
+    return $this->category;
+  }
+
   /**
    * @return mixed
    */
@@ -66,6 +87,16 @@ class Product
     return $this->price;
   }
 
+  /**
+   * @param mixed $category
+   *
+   * @return Product
+   */
+  public function setCategory($category) {
+    $this->category = $category;
+    return $this;
+  }
+
   /**
    * @param string $description
    *

+ 34 - 0
src/Migrations/Version20180103085203.php

@@ -0,0 +1,34 @@
+<?php declare(strict_types = 1);
+
+namespace DoctrineMigrations;
+
+use Doctrine\DBAL\Migrations\AbstractMigration;
+use Doctrine\DBAL\Schema\Schema;
+
+/**
+ * Auto-generated Migration: Please modify to your needs!
+ */
+class Version20180103085203 extends AbstractMigration
+{
+    public function up(Schema $schema)
+    {
+        // this up() migration is auto-generated, please modify it to your needs
+        $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
+
+        $this->addSql('CREATE TABLE category (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB');
+        $this->addSql('ALTER TABLE product ADD category_id INT DEFAULT NULL');
+        $this->addSql('ALTER TABLE product ADD CONSTRAINT FK_D34A04AD12469DE2 FOREIGN KEY (category_id) REFERENCES category (id)');
+        $this->addSql('CREATE INDEX IDX_D34A04AD12469DE2 ON product (category_id)');
+    }
+
+    public function down(Schema $schema)
+    {
+        // this down() migration is auto-generated, please modify it to your needs
+        $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
+
+        $this->addSql('ALTER TABLE product DROP FOREIGN KEY FK_D34A04AD12469DE2');
+        $this->addSql('DROP TABLE category');
+        $this->addSql('DROP INDEX IDX_D34A04AD12469DE2 ON product');
+        $this->addSql('ALTER TABLE product DROP category_id');
+    }
+}

+ 28 - 0
src/Repository/CategoryRepository.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace App\Repository;
+
+use App\Entity\Category;
+use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
+use Symfony\Bridge\Doctrine\RegistryInterface;
+
+class CategoryRepository extends ServiceEntityRepository
+{
+    public function __construct(RegistryInterface $registry)
+    {
+        parent::__construct($registry, Category::class);
+    }
+
+    /*
+    public function findBySomething($value)
+    {
+        return $this->createQueryBuilder('c')
+            ->where('c.something = :value')->setParameter('value', $value)
+            ->orderBy('c.id', 'ASC')
+            ->setMaxResults(10)
+            ->getQuery()
+            ->getResult()
+        ;
+    }
+    */
+}

+ 3 - 1
src/Repository/ProductRepository.php

@@ -45,8 +45,10 @@ ORDER BY p.price ASC
   public function findProductsLessThanSQL(float $price) {
     $conn = $this->getEntityManager()->getConnection();
 
+    // With SELECT * we would get category_id, which is not returned by the
+    // other queries, as it is a physical DB field, not an entity field.
     $sql = <<<SQL
-SELECT *
+SELECT p.description, p.id, p.name, p.price
 FROM product p
 WHERE p.price < :price
 ORDER BY p.price ASC;