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

X-Adept
  
Join Date: Apr 2016
Posts: 446
 

Default How to show all products related to an entity in another model

First of all, here is what I would like to achieve. The module I am working on is for X-cart 5.3.6.0. We sell books, and we would like
to have a page of an author, where we have the name, photo, description of the author
(this part has been done), and all his books underneath. As I wrote in the thread,

https://forum.x-cart.com/showthread.php?t=77082 I made a model for entities "Author" in ManyToMany relationship with the model Product.


I have following files to output the page


Controller file Controller/Customer/Author.php with
Code:
class Author extends \XLite\Controller\Customer\ACustomer { protected $params = array('target', 'author_id'); public function getAuthorId() { return \XLite\Core\Request::getInstance()->author_id ?: 0; } }
so that the page can be called with author_id,
page viewer file View/Page/Customer/Author.php (basically a modification of

View/Page/Customer/Category.php )

Code:
<?php namespace XLite\Module\EdB\Librairie\View\Page\Customer; use \XLite\Core\Database; use \Model\Catalog\Base; /** * Category widget * * @ListChild (list="center", zone="customer") */ class Author extends \XLite\View\AView { /** * Return list of targets allowed for this widget * * @return array */ public static function getAllowedTargets() { $result = parent::getAllowedTargets(); $result[] = 'author'; return $result; } public function findAuthor() { $author_id = $this->getAuthorId(); $author = \XLite\Core\Database::getRepo('XLite\Module\EdB\Librairie\Model\Au thor')->find($author_id); return $author; } public function describeAuthor() { $author = $this->findAuthor(); $value = $author->getDescription(); $value = \XLite\Model\Base\Catalog::getPreprocessedValue($value); echo $value; } protected function getDefaultTemplate() { return 'modules/EdB/Librairie/aut1.twig'; } }
with the twig file skins/customer/modules/EdB/Librairie/aut1.twig
Code:
{{widget('\\XLite\\View\\Image', image=this.findAuthor().getImage(), className=' photo product-thumbnail', verticalAlign='top', id='product_image_' ~ this.findAu thor().author_id, maxWidth=600, maxHeight=600, alt='') }} {{this.findAuthor().name}} <br> <br> {{this.describeAuthor()}}

This part is working. Now, to output the list of books by the author, I have another widget Librairie/View/ItemsList/Product/Customer/BooksBy.php with the following
content (below, I removed the part that "should" define which products to show, so
with this we get all products).

Code:
<?php namespace XLite\Module\EdB\Librairie\View\ItemsList\Product\Customer; /** * * @ListChild (list="center.bottom", zone="customer", weight="300") */ class BooksBy extends \XLite\View\ItemsList\Product\Customer\ACustomer { protected $BooksbyAuthor = null; protected static function getWidgetTarget() { return 'author'; } public static function getAllowedTargets() { $result = parent::getAllowedTargets(); $result[] = self::getWidgetTarget(); return $result; } protected function getData(\XLite\Core\CommonCell $cnd, $countOnly = false) { return \XLite\Core\Database::getRepo('\XLite\Model\Product')->search( $cnd, $countOnly); } protected function getPagerClass() { return 'XLite\Module\EdB\Librairie\View\Pager\Customer\Product\Product'; } }


Of course, I could join the xc_products table with xc_product_author_links table and create a query condition, write a function in Repo class, and this might take less time to finish writing up. However, as I already have pulled the author entity with all properties, including getProducts() which gives an array of products, I would rather use this array to "feed" the getData function.



Now, I encounter two problems.
  1. How to pass an array or even a function from viewer widget to the itemlists widget?
  2. How to transform an array to the return of the getData function?
For the first point, most of my trials ended up with " Using $this when not in object context" or "call to undefined function", so for now I have reproduced the function in ItemsList file, that is

Code:
public function findBooks() { $author_id = \XLite\Core\Request::getInstance()->author_id; $author = \XLite\Core\Database::getRepo('XLite\Module\EdB\Librairie\Model\Au thor')->find($author_id); $products = $author->getProducts(); return $products; }
This is already in Model class and Viewer class, so I really would like to remove these lines, but for now, it works. As to the second issue, the closest thing
I have seen is
https://forum.x-cart.com/showthread.php?t=70741


so I tried the following (among others)
Code:
protected $BooksbyAuthor = null; protected function getData(\XLite\Core\CommonCell $cnd, $countOnly = false) { if(!isset($this->BooksbyAuthor)) { $this->BooksbyAuthor = $this->findBooks(); } return true == $countOnly ?count($this->BooksbyAuthor) : $this->BooksbyAuthor; }
but this leads to
Code:
ERROR: "0" (code N/A) Argument 2 passed to XLite\Core\Model\EntityVersion\BulkEntityVersionFetcher::__construct() must be of the type array, null given, called in /srv/http/newbtq72/xcart-53/var/run/classes/XLite/View/ItemsList/Product/Customer/ACustomerAbstract.php on line 918


and in the log, I find,
Code:
XLite [warning] Warning: array_map(): Argument #2 should be an array in /srv/http/newbtq72/xcart-53/var/run/classes/XLite/View/ItemsList/Product/Customer/ACustomerAbstract.php on line 916



So, would anyone have any advice on this?
__________________
X-cart 5.2.12, php 5.6
Ed from Grenoble, France

Last edited by Ed B. : 08-11-2019 at 09:11 AM. Reason: Corrected a dead link as well as gave the version number.
Reply With Quote