Browse Source

ORM: DQL/QB subtleties with relations.

Frederic G. MARAND 6 years ago
parent
commit
2c0d8bd04e

+ 33 - 0
src/Controller/CategoryController.php

@@ -0,0 +1,33 @@
+<?php
+
+namespace App\Controller;
+
+
+use App\Entity\Category;
+use Doctrine\ORM\EntityManagerInterface;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\Routing\Annotation\Route;
+
+class CategoryController {
+  const DEVICES = 'Computer Peripherals';
+
+  /**
+   * @Route(
+   *   name = "category_add",
+   *   path = "/category/add"
+   * )
+   *
+   * @param \Doctrine\ORM\EntityManagerInterface $em
+   *
+   * @return \Symfony\Component\HttpFoundation\Response
+   */
+  public function add(EntityManagerInterface $em) {
+    $cat = new Category();
+    $cat->setName(self::DEVICES);
+    $em->persist($cat);
+    $em->flush();
+
+    return new Response('Saved new category with id ' . $cat->getId(),
+      Response::HTTP_CREATED);
+  }
+}

+ 16 - 5
src/Controller/ProductController.php

@@ -2,6 +2,7 @@
 
 namespace App\Controller;
 
+use App\Entity\Category;
 use App\Entity\Product;
 use App\Repository\ProductRepository;
 use Doctrine\ORM\EntityManagerInterface;
@@ -19,7 +20,7 @@ class ProductController extends Controller
    *  path = "/product"
    * )
    *
-   * @param \Doctrine\ORM\EntityManagerInterface $em
+   * @param \App\Repository\ProductRepository $repository
    *
    * @return \Symfony\Component\HttpFoundation\Response
    */
@@ -31,12 +32,16 @@ class ProductController extends Controller
     $productsSQL = $repository->findProductsLessThanSQL($priceLimit);
 
     // These two build the exact same query object.
-    assert($productsDQL === $productsQB);
+    $dql_qb = ($productsDQL === $productsQB);
 
-    // But these only return the same results, not the same query object.
-    assert($productsDQL == $productsSQL);
+    // But these only return the same raw results, missing the initialization.
+    $dql_sql = ($productsDQL == $productsSQL);
 
-    return $this->render('product/index.html.twig', ['products' => $productsQB]);
+    return $this->render('product/index.html.twig', [
+      'products' => $productsQB,
+      'dql_qb' => $dql_qb,
+      'dql_sql' => $dql_sql,
+    ]);
   }
 
   /**
@@ -54,11 +59,17 @@ class ProductController extends Controller
       ->setPrice(19.99)
       ->setDescription('Ergonomic and stylish!');
 
+    $cat = $em->getRepository(Category::class)->findOneBy([
+      'name' => CategoryController::DEVICES,
+    ]);
+    $product->setCategory($cat);
+
     // tell Doctrine you want to (eventually) save the Product (no queries yet)
     $em->persist($product);
 
     // actually executes the queries (i.e. the INSERT query)
     $em->flush();
+    $products = $cat->getProducts();
 
     return new Response('Saved new product with id ' . $product->getId(),
       Response::HTTP_CREATED);

+ 24 - 1
src/Entity/Category.php

@@ -2,6 +2,7 @@
 
 namespace App\Entity;
 
+use Doctrine\Common\Collections\ArrayCollection;
 use Doctrine\ORM\Mapping as ORM;
 
 /**
@@ -23,7 +24,7 @@ class Category
 
   /**
    * The OneToMany annotation is NOT required unless the associated access is
-   * needed. If not set mappedBy on Category.products and inversedBy on
+   * needed. If not set, mappedBy on Category.products and inversedBy on
    * Product.category are not needed.
    *
    * @ORM\OneToMany(
@@ -33,6 +34,10 @@ class Category
    */
   private $products;
 
+  public function __construct() {
+    $this->products = new ArrayCollection();
+  }
+
   /**
    * @return mixed
    */
@@ -47,6 +52,13 @@ class Category
     return $this->name;
   }
 
+  /**
+   * @return mixed
+   */
+  public function getProducts() {
+    return $this->products;
+  }
+
   /**
    * @param mixed $name
    *
@@ -56,4 +68,15 @@ class Category
     $this->name = $name;
     return $this;
   }
+
+  /**
+   * @param mixed $products
+   *
+   * @return Category
+   */
+  public function setProducts($products) {
+    $this->products = $products;
+    return $this;
+  }
+
 }

+ 6 - 0
templates/product/index.html.twig

@@ -28,4 +28,10 @@
             {% endfor %}
         </tbody>
     </table>
+
+<h3>Lists comparison</h3>
+<ul>
+    <li>DQL === QueryBuilder ? {{ dql_qb ? "Y" : "N" }}</li>
+    <li>DQL == SQL ? {{  dql_sql ? "Y" : "N" }}</li>
+</ul>
 {% endblock %}