View Single Post
  #1  
Old 08-05-2019, 08:41 AM
 
Ed B. Ed B. is offline
 

X-Adept
  
Join Date: Apr 2016
Posts: 446
 

Default Relating entities from two models (ManyToMany). Can't make getter work

I am trying to write a module that relates entities from two models. Unfortunately dev docs don't give an example to follow, so I imitate what is done with the products and memberships. This is for X-Cart 5.3.6, Vendor name is EdB, module name is Librairie.



One of the models is "product" which already exist, the other is "author" that I created. So, aside from Main.php, I have following files

  • Model/Author.php
  • Model/Product.php
  • Model/DTO/Product/Info.php
  • View/FormModel/Product/Info.php
  • Model/Repo/Author.php
Mostly it was enough to change "M/membership" to "A/author", and change the path to the class as well as namespace. It turns out that I can save data (I looked directory at the database). However, I can't fetch the data.


Here are relevant part of codes. I wonder if anyone could tell me what I am doing wrong.


In Model/Author.php, to relate two models, we have
Code:
/** * Books * * @var \Doctrine\Common\Collections\ArrayCollection * // * @ManyToMany (targetEntity="XLite\Model\Product", mappedBy="authors", fe tch="LAZY") * @ManyToMany (targetEntity="XLite\Module\EdB\Librairie\Model\Product", map pedBy="authors", fetch="LAZY") */ protected $products;


By the way, should I use XLite\Model\Product, or XLite\Module\EdB\Librairie\Model\Product here?


A property
Code:
/** * Enabled status * * @var boolean * * @Column (type="boolean") */ protected $enabled = true;

And, getters,

Code:
/** * Returns author_id * * @return string */ public function getAuthorId() { return $this->author_id; } /** * Get enabled * * @return boolean */ public function getEnabled() { return $this->enabled; }


We also have a getter


Code:
/** * Get products * * @return \Doctrine\Common\Collections\Collection */ public function getProducts() { return $this->products; }


but presumably this is irrelevant for now.


In Model/Product.php to relate the two models, we have
Code:
/** * Authors * * @var \Doctrine\Common\Collections\ArrayCollection * * @ManyToMany (targetEntity="XLite\Module\EdB\Librairie\Model\Author", inve rsedBy="products") * @JoinTable (name="product_author_links", * joinColumns={@JoinColumn (name="product_id", referencedColumnName="p roduct_id", onDelete="CASCADE")}, * inverseJoinColumns={@JoinColumn (name="author_id", referencedColumnN ame="author_id", onDelete="CASCADE")} * ) */ protected $authors;
Getters and constructors, as well as some checking functions

Code:
public function __construct(array $data = array()) { parent::__construct($data); $this->authors = new \Doctrine\Common\Collections\ArrayCollection(); } /** * Get author Ids * * @return array */ public function getAuthorIds() { $result = array(); foreach ($this->getAuthors() as $author) { $result[] = $author->getAuthorId(); } return $result; } /** * Flag if the category and active profile have the same authors. (when cate gory is displayed or hidden) * * @return boolean */ public function hasAvailableAuthor() { return 0 === $this->getAuthors()->count() || in_array(\XLite\Core\Auth::g etInstance()->getAuthorId(), $this->getAuthorIds()); } ** * Get authors * * @return \Doctrine\Common\Collections\Collection */ public function getAuthors() { return $this->authors; } /** * @param \XLite\Module\EdB\Librairie\Model\Author $author * * @return boolean */ public function hasAuthorByAuthor($author) { return (boolean) $this->getAuthorByAuthor($author); } /** * @param \XLite\Model\Author $author * * @return mixed|null */ public function getAuthorByAuthor($author) { foreach ($this->getAuthors() as $authorObject) { if ((int) $author->getAuthorId() === (int) $authorObject->getAuthorI d()) { return $authorObject; } } return null; }
Form Model View/FormModel/Product/Info.php
Code:
protected function defineFields() { $authors = []; foreach (\XLite\Core\Database::getRepo('XLite\Module\EdB\Librairie\Model \Author')->findActiveAuthors() as $author) { $authors[$author->getAuthorId()] = $author->getName(); } $schema = parent::defineFields(); $schema['default']['authors'] = [ 'label' => static::t('Authors'), 'type' => 'XLite\View\FormModel\Type\Select2Type', 'multiple' => true, 'choices' => array_flip($authors), 'choices_as_values' => true, 'position' => 100, ];



And, codes to work with the database in Model/DTO/Product/Info.php
Code:
protected function init($object) { parent::init($object); $authors = []; foreach ($object->getAuthors() as $author) { $authors[] = $author->getAuthorId(); } $this->default->authors = $object->$authors; }
I am suspecting an error in this part, and I tried several different variants, but none works. By the way, for the setter, I have the following that works.
Code:
$authors = \XLite\Core\Database::getRepo('XLite\Module\EdB\Librairi e\Model\Author')->findByIds($this->default->authors); $object->replaceAuthorsByAuthors($authors) ;



Last but not least, we have Model/Repo/Author.php, which I attach because I don't know which part is relevant here, and it is very long. Just couple of things : I added 'm' in the definition of FindActiveAuthors, although there wasn't one in Model/Repo/Membership.php because otherwise I got errors. Another thing I changed was that the class extends

ARepo instead of I18n, because I don't have multilingual entities.


So, any ideas?
Attached Files
File Type: php Author.php (4.7 KB, 136 views)
__________________
X-cart 5.2.12, php 5.6
Ed from Grenoble, France
Reply With Quote