X-Cart: shopping cart software

X-Cart forums (https://forum.x-cart.com/index.php)
-   Dev Questions (X-Cart 5) (https://forum.x-cart.com/forumdisplay.php?f=56)
-   -   Relating entities from two models (ManyToMany). Can't make getter work (https://forum.x-cart.com/showthread.php?t=77082)

Ed B. 08-05-2019 08:41 AM

Relating entities from two models (ManyToMany). Can't make getter work
 
1 Attachment(s)
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?

Ed B. 08-06-2019 06:59 AM

Re: Relating entities from two models (ManyToMany). Can't make getter work
 
I got this one.


What I needed was a file

  • View/FormField/Select/Authors.php
which imitates Memberships.php...


All times are GMT -8. The time now is 10:00 PM.

Powered by vBulletin Version 3.5.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.