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?