Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [SF2][SF] Relacja n:m i dodatkowe pola w tabeli laczacej
Forum PHP.pl > Forum > PHP > Frameworki
swiezak
Witam.
Nie za bardzo wiem, w jaki sposob w modelu uwzglednic dodatkowe pola dla tabeli laczacej produkty i zamowienia.

Ponizej uproszczona struktura bazy danych:
[text]
tabela orders
id
user_id
payment_id
shipment_id
status
total_amount

tabela products
id
sku
name
price
description

tabela product_orders
products_id
orders_id

(chcialbym dodac dodatkowe pola: quantity, price)
[/text]

Fragment Orders.php (Entity)
  1. class Orders
  2. {
  3. /**
  4.   * @var integer
  5.   *
  6.   * @ORM\Column(name="id", type="integer")
  7.   * @ORM\Id
  8.   * @ORM\GeneratedValue(strategy="AUTO")
  9.   */
  10. private $id;
  11.  
  12. /**
  13.   * @Assert\NotBlank
  14.   * @ORM\ManyToOne(targetEntity="Ml\UserBundle\Entity\User", inversedBy="orders")
  15.   * @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=false)
  16.   *
  17.   */
  18. protected $user;
  19.  
  20. /**
  21.   * @Assert\NotBlank
  22.   * @ORM\ManyToOne(targetEntity="Payments", inversedBy="orders")
  23.   * @ORM\JoinColumn(name="order_payment_id", referencedColumnName="id", nullable=false)
  24.   *
  25.   */
  26. protected $orderPayment;
  27.  
  28. /**
  29.   * @Assert\NotBlank
  30.   * @ORM\ManyToOne(targetEntity="Shipments", inversedBy="orders")
  31.   * @ORM\JoinColumn(name="order_shipment_id", referencedColumnName="id", nullable=false)
  32.   *
  33.   */
  34. protected $orderShipment;
  35.  
  36. /**
  37.   * @var string
  38.   *
  39.   * @ORM\Column(name="shipping_address", type="string", length=255, nullable=true)
  40.   */
  41. private $shippingAddress;
  42.  
  43. /**
  44.   * @var string
  45.   *
  46.   * @ORM\Column(name="billing_address", type="string", length=255, nullable=true)
  47.   */
  48. private $billingAddress;
  49.  
  50. /**
  51.   * @var string
  52.   *
  53.   * @ORM\Column(name="client_description", type="text", nullable=true)
  54.   */
  55. private $clientDescription;
  56.  
  57. /**
  58.   * @var string
  59.   *
  60.   * @ORM\Column(name="admin_description_for_client", type="text", nullable=true)
  61.   */
  62. private $adminDescriptionForClient;
  63.  
  64. /**
  65.   * @var string
  66.   *
  67.   * @ORM\Column(name="admin_description", type="text", nullable=true)
  68.   */
  69. private $adminDescription;
  70.  
  71. /**
  72.   * @var string
  73.   *
  74.   * @ORM\Column(name="total_amount", type="decimal", precision=11, scale=2)
  75.   */
  76. private $totalAmount;
  77.  
  78. //opt_client_name varchar(64)
  79. //opt_client_company varchar(64)
  80.  
  81. /**
  82. * @var datetime $created
  83. *
  84. * @Gedmo\Timestampable(on="create")
  85. * @ORM\Column(type="datetime")
  86. */
  87. private $created;
  88.  
  89. /**
  90. * @var datetime $updated
  91. *
  92. * @Gedmo\Timestampable(on="update")
  93. * @ORM\Column(type="datetime")
  94. */
  95. private $updated;
  96.  
  97. /**
  98.   * @var string
  99.   *
  100.   * @ORM\Column(name="hash_code", type="string", length=255, nullable=true)
  101.   */
  102. private $hashCode;
  103.  
  104. /**
  105.   * @var boolean
  106.   *
  107.   * @ORM\Column(name="is_confirmed", type="boolean", options={"default":0})
  108.   */
  109. private $isConfirmed;
  110.  
  111. /**
  112.   * @var boolean
  113.   *
  114.   * @ORM\Column(name="is_payed", type="boolean", options={"default":0})
  115.   */
  116. private $isPayed;
  117.  
  118. /**
  119.   * @Assert\NotBlank
  120.   * @ORM\ManyToOne(targetEntity="OrdersStatus", inversedBy="orders")
  121.   * @ORM\JoinColumn(name="order_status_id", referencedColumnName="id", nullable=false)
  122.   *
  123.   */
  124. protected $orderStatus;
  125.  
  126. /**
  127.   * @var boolean
  128.   *
  129.   * @ORM\Column(name="pf_status", type="boolean", options={"default":0})
  130.   */
  131. private $pfStatus;
  132.  
  133. /**
  134.   * @var boolean
  135.   *
  136.   * @ORM\Column(name="f_status", type="boolean", options={"default":0})
  137.   */
  138. private $fStatus;
  139.  
  140. /**
  141.   * @ORM\ManyToMany(targetEntity="Products", mappedBy="orders")
  142.   */
  143. protected $products;
  144.  
  145. /**
  146.   * Constructor
  147.   */
  148. public function __construct()
  149. {
  150. $this->products = new \Doctrine\Common\Collections\ArrayCollection();
  151. }


Fragment Products.php (Entity):
  1. class Products
  2. {
  3. /**
  4.   * @var integer
  5.   *
  6.   * @ORM\Column(name="id", type="integer")
  7.   * @ORM\Id
  8.   * @ORM\GeneratedValue(strategy="AUTO")
  9.   */
  10. private $id;
  11.  
  12. /**
  13.   * @var string
  14.   *
  15.   * @Assert\NotBlank()
  16.   * @ORM\Column(name="sku", type="string", length=255)
  17.   */
  18. private $sku;
  19.  
  20. /**
  21.   * @var string
  22.   *
  23.   * @Assert\NotBlank()
  24.   * @ORM\Column(name="name", type="string", length=255)
  25.   */
  26. private $name;
  27.  
  28. /**
  29. * @var string $slug
  30. *
  31. * @Gedmo\Slug(fields={"name"})
  32. * @ORM\Column(length=255, unique=true)
  33. */
  34. private $slug;
  35.  
  36. /**
  37.   * @var string
  38.   *
  39.   * @ORM\Column(name="vat_value", type="decimal", precision=3, scale=2, options={"default":0.23})
  40.   */
  41. private $vatValue;
  42.  
  43. /**
  44.   * @var string
  45.   *
  46.   * @Assert\NotBlank()
  47.   * @ORM\Column(name="price_netto", type="decimal", precision=7, scale=2, options={"default":0.00})
  48.   */
  49. private $priceNetto;
  50.  
  51. /**
  52.   * @var string
  53.   *
  54.   * @Assert\NotBlank()
  55.   * @ORM\Column(name="price_brutto", type="decimal", precision=7, scale=2, options={"default":0.00})
  56.   */
  57. private $priceBrutto;
  58.  
  59. /**
  60.   * @var string
  61.   *
  62.   * @Assert\NotBlank()
  63.   * @ORM\Column(name="old_price_netto", type="decimal", precision=7, scale=2, options={"default":0.00})
  64.   */
  65. private $oldPriceNetto;
  66.  
  67. /**
  68.   * @var string
  69.   *
  70.   * @Assert\NotBlank()
  71.   * @ORM\Column(name="old_price_brutto", type="decimal", precision=7, scale=2, options={"default":0.00})
  72.   */
  73. private $oldPriceBrutto;
  74.  
  75. /**
  76.   * @var boolean
  77.   *
  78.   * @ORM\Column(name="is_active", type="boolean", options={"default":1})
  79.   */
  80. private $isActive;
  81.  
  82. /**
  83.   * @var boolean
  84.   *
  85.   * @ORM\Column(name="is_new", type="boolean", options={"default":0})
  86.   */
  87. private $isNew;
  88.  
  89. /**
  90.   * @var boolean
  91.   *
  92.   * @ORM\Column(name="is_promo", type="boolean", options={"default":0})
  93.   */
  94. private $isPromo;
  95.  
  96. /**
  97.   * @var boolean
  98.   *
  99.   * @ORM\Column(name="is_popular", type="boolean", options={"default":0})
  100.   */
  101. private $isPopular;
  102.  
  103. /**
  104. * @var datetime $created
  105. *
  106. * @Gedmo\Timestampable(on="create")
  107. * @ORM\Column(type="datetime")
  108. */
  109. private $created;
  110.  
  111. /**
  112. * @var datetime $updated
  113. *
  114. * @Gedmo\Timestampable(on="update")
  115. * @ORM\Column(type="datetime")
  116. */
  117. private $updated;
  118.  
  119. /**
  120.   * @var integer
  121.   *
  122.   * @ORM\Column(name="views", type="integer", nullable=true, options={"default":0})
  123.   */
  124. private $views;
  125.  
  126. /**
  127.   * @var string
  128.   *
  129.   * @ORM\Column(name="short_description", type="string", length=255, nullable=true)
  130.   */
  131. private $shortDescription;
  132.  
  133. /**
  134.   * @var string
  135.   *
  136.   * @ORM\Column(name="description", type="text", nullable=true)
  137.   */
  138. private $description;
  139.  
  140. /**
  141.   * @var boolean
  142.   *
  143.   * @ORM\Column(name="hide_price", type="boolean", options={"default":0})
  144.   */
  145. private $hidePrice;
  146.  
  147. /**
  148.   * @Assert\NotBlank
  149.   * @ORM\ManyToOne(targetEntity="Availability", inversedBy="products")
  150.   * @ORM\JoinColumn(name="availability_id", referencedColumnName="id", nullable=false)
  151.   *
  152.   */
  153. protected $availability;
  154.  
  155. /**
  156.   * @var string
  157.   *
  158.   * @ORM\Column(name="meta_title", type="string", length=255, nullable=true)
  159.   */
  160. private $metaTitle;
  161.  
  162. /**
  163.   * @var string
  164.   *
  165.   * @ORM\Column(name="meta_keywords", type="string", length=255, nullable=true)
  166.   */
  167. private $metaKeywords;
  168.  
  169. /**
  170.   * @var string
  171.   *
  172.   * @ORM\Column(name="meta_description", type="text", nullable=true)
  173.   */
  174. private $metaDescription;
  175.  
  176. /**
  177.   * @Assert\NotBlank
  178.   * @ORM\ManyToOne(targetEntity="Brands", inversedBy="products")
  179.   * @ORM\JoinColumn(name="brand_id", referencedColumnName="id", nullable=false)
  180.   *
  181.   */
  182. protected $brands;
  183.  
  184. /**
  185.   * @ORM\OneToMany(targetEntity="Images", mappedBy="products", cascade={"persist"})
  186.   */
  187. protected $images;
  188.  
  189. /**
  190.   * @ORM\OneToMany(targetEntity="Documents", mappedBy="products", cascade={"persist"})
  191.   */
  192. protected $documents;
  193.  
  194. /**
  195.   * @ORM\OneToMany(targetEntity="Attributes", mappedBy="products", cascade={"persist"})
  196.   */
  197. protected $attributes;
  198.  
  199. /**
  200.   * @ORM\ManyToMany(targetEntity="Categories", inversedBy="products")
  201.   */
  202. protected $categories;
  203.  
  204. /**
  205.   * @ORM\ManyToMany(targetEntity="Orders", inversedBy="products")
  206.   */
  207. protected $orders;
  208.  
  209. public function __toString() {
  210. return $this->name;
  211. }
  212.  
  213. /**
  214.   * Constructor
  215.   */
  216. public function __construct()
  217. {
  218. $this->images = new \Doctrine\Common\Collections\ArrayCollection();
  219. $this->documents = new \Doctrine\Common\Collections\ArrayCollection();
  220. $this->attributes = new \Doctrine\Common\Collections\ArrayCollection();
  221. $this->categories = new \Doctrine\Common\Collections\ArrayCollection();
  222. $this->orders = new \Doctrine\Common\Collections\ArrayCollection();
  223. }



W jaki sposob moge zaktualizowac model, aby miec mozliwosc zarzadzania dodatkowymi polami (quantity, price) z tabeli products_orders?
Nie znam zbyt dobrze SF2, dlatgo prosze o wyrozumialosc.
Crozin
1. Temat w ogóle nie dotyczy Symfony, tylko Doctrine.
2. Powinieneś utworzyć relację jeden-do-wielu-do-jednego, czyli podwójne jeden-do-wielu. W momencie, gdy tabela łącząca zaczyna posiadać jakieś własne dane powinna posiadać własny obiekt reprezentujący te dane.
swiezak
Dokonalem aktualizacji encji Products oraz Orders, jak rowniez utworzylem nowa: ProductsOrders, ale podczas wykonywania polecenia w konsoli "php app/console doctrine:schema:validate" dostaje informacje o bledzie o nastepujacej tresci:
  1. "[Doctrine\DBAL\Schema\SchemaException] The table with name shop.products_orders already exists".


A wczesniej: "[Mapping] OK - The mapping files are correct".

Zawartosc poszczegolnych encji (wazniejsze fragmenty):

Products.php
  1. namespace Ml\FrontendBundle\Entity;
  2.  
  3. use Gedmo\Sluggable\Sluggable;
  4. use Gedmo\Mapping\Annotation as Gedmo;
  5. use Symfony\Component\Validator\Constraints as Assert;
  6. use Doctrine\ORM\Mapping as ORM;
  7.  
  8. /**
  9.  * Products
  10.  *
  11.  * @ORM\Table()
  12.  * @ORM\Entity(repositoryClass="Ml\FrontendBundle\Entity\ProductsRepository")
  13.  */
  14. class Products
  15. {
  16. /**
  17.   * @var integer
  18.   *
  19.   * @ORM\Column(name="id", type="integer")
  20.   * @ORM\Id
  21.   * @ORM\GeneratedValue(strategy="AUTO")
  22.   */
  23. private $id;
  24.  
  25. ...
  26.  
  27. /**
  28.   * @ORM\ManyToMany(targetEntity="Orders", inversedBy="products")
  29.   */
  30. protected $orders;
  31.  
  32. /**
  33.   * @ORM\OneToMany(targetEntity="ProductsOrders", mappedBy="products", cascade={"all"})
  34.   * */
  35. protected $productsOrders;
  36.  
  37. ...
  38. }



Orders.php
  1. namespace Ml\FrontendBundle\Entity;
  2.  
  3. use Ml\UserBundle\Entity\User;
  4. use Gedmo\Mapping\Annotation as Gedmo;
  5. use Symfony\Component\Validator\Constraints as Assert;
  6. use FOS\UserBundle\Model\User as BaseUser;
  7. use Doctrine\ORM\Mapping as ORM;
  8.  
  9. /**
  10.  * Orders
  11.  *
  12.  * @ORM\Table()
  13.  * @ORM\Entity
  14.  */
  15. class Orders
  16. {
  17. /**
  18.   * @var integer
  19.   *
  20.   * @ORM\Column(name="id", type="integer")
  21.   * @ORM\Id
  22.   * @ORM\GeneratedValue(strategy="AUTO")
  23.   */
  24. private $id;
  25.  
  26. ...
  27.  
  28. /**
  29.   * @ORM\ManyToMany(targetEntity="Products", mappedBy="orders")
  30.   */
  31. protected $products;
  32.  
  33. /**
  34.   * @ORM\OneToMany(targetEntity="ProductsOrders", mappedBy="orders", cascade={"all"})
  35.   * */
  36. protected $productsOrders;
  37.  
  38. ...
  39. }



ProductsOrders.php
  1. namespace Ml\FrontendBundle\Entity;
  2.  
  3. use Gedmo\Mapping\Annotation as Gedmo;
  4. use Symfony\Component\Validator\Constraints as Assert;
  5. use Doctrine\ORM\Mapping as ORM;
  6.  
  7. /**
  8.  * @ORM\Entity
  9.  * @ORM\Table(name="products_orders")
  10.  * @ORM\HasLifecycleCallbacks()
  11.  */
  12. class ProductsOrders
  13. {
  14. /**
  15.   * @var integer
  16.   *
  17.   * @ORM\Column(name="id", type="integer")
  18.   * @ORM\Id
  19.   * @ORM\GeneratedValue(strategy="AUTO")
  20.   */
  21. private $id;
  22.  
  23. /**
  24.   * @Assert\NotBlank
  25.   * @ORM\ManyToOne(targetEntity="Products", inversedBy="productsOrders")
  26.   * @ORM\JoinColumn(name="products_id", referencedColumnName="id", nullable=false)
  27.   * */
  28. protected $products;
  29.  
  30. /**
  31.   * @Assert\NotBlank
  32.   * @ORM\ManyToOne(targetEntity="Orders", inversedBy="productsOrders")
  33.   * @ORM\JoinColumn(name="orders_id", referencedColumnName="id", nullable=false)
  34.   * */
  35. protected $orders;
  36.  
  37. /**
  38.   * @var integer
  39.   *
  40.   * @Assert\NotBlank
  41.   * @ORM\Column(name="amount", type="integer")
  42.   */
  43. private $amount;
  44.  
  45. /**
  46.   * @var string
  47.   *
  48.   * @Assert\NotBlank()
  49.   * @ORM\Column(name="price_netto", type="decimal", precision=7, scale=2, options={"default":0.00})
  50.   */
  51. private $priceNetto;
  52.  
  53. /**
  54.   * @var string
  55.   *
  56.   * @Assert\NotBlank()
  57.   * @ORM\Column(name="price_brutto", type="decimal", precision=7, scale=2, options={"default":0.00})
  58.   */
  59. private $priceBrutto;
  60.  
  61. /**
  62.   * @var string
  63.   *
  64.   * @ORM\Column(name="vat_value", type="decimal", precision=3, scale=2, options={"default":0.23})
  65.   */
  66. private $vatValue;
  67. ...
  68. }



Gdzie zrobilem blad?

Tabela o nazwie "products_orders" byla wczesniej utworzona automatycznie na podstawie relacji n:m. W tej chwili zmodyfikowalem model, ale polecenie "php app/console doctrine:schema:drop --force" nie dziala. Gdy zmienie w pliku ProductsOrders.php fargment odpowiedzialny za nazwe tabeli w bazie danych na:
  1. /**
  2.  * @ORM\Entity
  3.  * @ORM\Table(name="product_order")
  4.  * @ORM\HasLifecycleCallbacks()
  5.  */
  6. class ProductsOrders
  7. {
  8. ...
  9. }


konsola nie "wypluwa" bledow, jednak sa tworzone dwie tabele laczace: products_orders oraz product_order. W jaki sposob zmodyfikowac wpisy w encjach Products i Orders, aby zniwelowac ten niepozadany efekt?
Crozin
Obiekt Zamówienie powinien mieć jedynie powiązanie do ZamówienieProdukt bez relacji do Produkt. Analogicznie z obiektem Produkt. Masz za dużo relacji.

A tak swoją drogą:
1. Zacznij poprawnie nadawać nazwy dla swoich klas/właściwości. Masz pojedyncze zamówienie, czyli Order nie Orders - analogicznie z pozostałymi.
2. Netto/brutto to po angielsku odpowiednio net/gross.
swiezak
Dziekuje serdecznie za poswiecony czas, pomoc i cenne wskazowki.
Zaktualizowalem model i teraz juz wszystko dziala, jak nalezy.


Pozdrawiam.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.