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)
-   -   How to display products with a particular attribute (https://forum.x-cart.com/showthread.php?t=70741)

juancho 12-10-2014 05:43 AM

How to display products with a particular attribute
 
Hi,

I would like to create a tab in the top menu to display products with a particular attribute.

For instance:
The site has these products: Bags (red and blue), wallets (red and green), shoes (red, green, blue) and pants (green and blue). I want to display only the products that have the attribute color='red' but I don't want to create a category 'red'. The tab in the top menu would be "RED PRODUCTS".

Any idea how can I do it?
Thanks!

tony_sologubov 12-11-2014 05:41 AM

Re: How to display products with a particular attribute
 
This thread is about kind of what you need:
http://forum.x-cart.com/showthread.php?t=70512

Anyway, here is couple more things to consider:

1) If you want to pull products with attribute Color having value Red and these attributes are product-specific, you would call it like this:

PHP Code:

$name 'Color';
$value 'Red';

$products = \XLite\Core\Database::getRepo('\XLite\Model\Product')
    ->
createQueryBuilder('p')
    ->
linkInner('p.attributes')
    ->
linkInner('attributes.translations''atranslations')
    ->
linkInner('attributes.attribute_options')
    ->
linkInner('attribute_options.translations''aotranslations')
    ->
andWhere('atranslations.name = :name AND aotranslations.name = :value')
    ->
setParameter('name'$name)
    ->
setParameter('value'$value)
    ->
getResult();

foreach (
$products as $product) {
    echo 
$product->getName();



2) If you need the same but for global attributes you would call it like this:
PHP Code:

$name 'Manufacturer';
$value 'Toyty';

$a = \XLite\Core\Database::getRepo('\XLite\Model\AttributeValue\AttributeValueSelect')
    ->
createQueryBuilder('avs')
    ->
linkInner('avs.attribute''a')
    ->
linkInner('a.translations''at')
    ->
linkInner('avs.attribute_option''ao')
    ->
linkInner('ao.translations''aot')
    ->
andWhere('at.name = :attributename AND aot.name = :optionvalue')
    ->
setParameter('attributename'$name)
    ->
setParameter('optionvalue'$value)
    ->
getResult();

foreach (
$a as $av) {
    echo 
$av->getProduct()->getName() . ' ';



Please, let me know if it helps.

juancho 12-14-2014 07:49 PM

Re: How to display products with a particular attribute
 
Hi Tony,

This is what I have done, however it does not work. It doesn't crash but renders a page with no products selected.

My site has products which have a global attribute called "Vintage" with 2 possible options: "Yes" and "No", to describe if the particular product is considered vintage or not.

What I am trying to do is to create a tab menu "VINTAGE" (target=vintage) to display all products that are Vintage.

1) I followed this tutorial http://kb.x-cart.com/display/XDD/Creating+new+page
and created this file in <X-Cart>/classes/XLite/Module/MyID/MyModule/Controller/Customer/Vintage.php

PHP Code:

<?php

namespace XLite\Module\MyID\MyModule\Controller\Customer;

class 
Vintage extends \XLite\Controller\Customer\ACustomer {
    
}


2) I created XLite\Module\MyID\MyModule\Model\Repo\Product.php

PHP Code:

<?php
namespace XLite\Module\MyID\MyModule\Model\Repo;

class 
Product extends \XLite\Model\Repo\Product implements \XLite\Base\IDecorator {

protected 
$name 'Vintage';
protected 
$value 'Yes';

    public function 
findAllVintage() {

    return \
XLite\Core\Database::getRepo('\XLite\Model\AttributeValue\AttributeValueSelect')
    ->
createQueryBuilder('avs')
    ->
linkInner('avs.attribute''a')
    ->
linkInner('a.translations''at')
    ->
linkInner('avs.attribute_option''ao')
    ->
linkInner('ao.translations''aot')
    ->
andWhere('at.name = :attributename AND aot.name = :optionvalue')
    ->
setParameter('attributename'$name)
    ->
setParameter('optionvalue'$value)
    ->
getResult();
    }
}


3) I created the viewer class: <X-Cart>/classes/XLite/Module/MyID/MyModule/View/Page/Customer/Vintage.php

PHP Code:

<?php

namespace XLite\Module\MyID/MyModule\View\Page\Customer;
 
/**
 * @ListChild (list="center.bottom", zone="customer", weight="300")
 */

class Vintage extends \XLite\View\ItemsList\Product\Customer\Category\ACategory {

protected 
$allVintageProducts null;

protected function 
getHead() { 
      return 
'Vintage'


public static function 
getAllowedTargets() {

     return 
array_merge(parent::getAllowedTargets(), array('vintage'));
}

protected function 
getPagerClass() { 
        return 
'\XLite\View\Pager\Infinity'



protected function 
getData(\XLite\Core\CommonCell $cnd$countOnly false) { 

     if (!isset(
$this->allVintageProducts)) {
            
$this->allVintageProducts = \XLite\Core\Database::getRepo('XLite\Model\Product')->findAllVintage();
        }

    return 
true == $countOnly
        
count($this->allVintageProducts)
        : 
$this->allVintageProducts;

 } 

// disabling ability to sort products and switch between display modes 
    
protected function defineWidgetParams() 
    { 
     
parent::defineWidgetParams(); 
     
$this->widgetParams[self::PARAM_SHOW_SORT_BY_SELECTOR]->setValue(false)
    } 

}


Any idea what am I doing wrong?
Thanks

tony_sologubov 12-16-2014 05:39 AM

Re: How to display products with a particular attribute
 
Could you please send me your mod packed? I will try to find what is wrong.

tony_sologubov 12-17-2014 12:26 PM

Re: How to display products with a particular attribute
 
I feel there is a problem with decorated version of \XLite\Model\Repo\Product class. It should be as follows:
PHP Code:

<?php

namespace XLite\Module\Astur\SirtoliSkin\Model\Repo;

abstract class 
Product extends \XLite\Model\Repo\Product implements \XLite\Base\IDecorator {

    public function 
findAllVintage() {

        
$name 'Vintage';
        
$value 'Yes';

        
$result = \XLite\Core\Database::getRepo('\XLite\Model\AttributeValue\AttributeValueSelect')
            ->
createQueryBuilder('avs')
            ->
linkInner('avs.attribute''a')
            ->
linkInner('a.translations''at')
            ->
linkInner('avs.attribute_option''ao')
            ->
linkInner('ao.translations''aot')
            ->
andWhere('at.name = :attributename AND aot.name = :optionvalue')
            ->
setParameter('attributename'$name)
            ->
setParameter('optionvalue'$value)
            ->
getResult();

        
$return = array();

        foreach (
$result as $attribute) {
            
$return[] = $attribute->getProduct();
        }

        return 
$return;
    }
}


instead of yours:

PHP Code:

<?php
namespace XLite\Module\Astur\SirtoliSkin\Model\Repo;

class 
Product extends \XLite\Model\Repo\Product implements \XLite\Base\IDecorator {

protected 
$name 'Vintage';
protected 
$value 'Yes';

    public function 
findAllVintage() {

    return \
XLite\Core\Database::getRepo('\XLite\Model\AttributeValue\AttributeValueSelect')
    ->
createQueryBuilder('avs')
    ->
linkInner('avs.attribute''a')
    ->
linkInner('a.translations''at')
    ->
linkInner('avs.attribute_option''ao')
    ->
linkInner('ao.translations''aot')
    ->
andWhere('at.name = :attributename AND aot.name = :optionvalue')
    ->
setParameter('attributename'$name)
    ->
setParameter('optionvalue'$value)
    ->
getResult();
    }
}


As you can see, there are couple of changes:
1) I foreach $result and call getProduct() of each $attribute returned from the database. If you do not do this, your findAllVintage() method will return AttributeValue objects instead of products.
2) I moved constants $name and $value into a method instead of them being a part of class properties.

Please, try my code and let me know if it works for you. If it does not, please give me a snapshot of how you set up a vintage attribute for a product.

juancho 12-17-2014 09:00 PM

Re: How to display products with a particular attribute
 
Hi Tony,

It works perfectly now. Many thanks, you are a genius.

just one small detail: where it says :
PHP Code:

abstract class Product extends \XLite\Model\Repo\ProductAbstract implements \XLite\Base\IDecorator 


should be saying:
PHP Code:

abstract class Product extends \XLite\Model\Repo\Product implements \XLite\Base\IDecorator 


tony_sologubov 12-18-2014 03:48 AM

Re: How to display products with a particular attribute
 
Oh, yes, sure. You are right. Corrected my code.

Eyeglasses Expert 06-10-2015 01:57 PM

Re: How to display products with a particular attribute
 
how to let x-cart gold 4.7.2 have this function?

lakin1 09-04-2018 03:42 AM

Re: How to display products with a particular attribute
 
Quote:

Originally Posted by tony_sologubov
I feel there is a problem with decorated version of \XLite\Model\Repo\Product class. It should be as follows:
PHP Code:

<?php

namespace XLite\Module\Astur\SirtoliSkin\Model\Repo;

abstract class 
Product extends \XLite\Model\Repo\Product implements \XLite\Base\IDecorator {

    public function 
findAllVintage() {

        
$name 'Vintage';
        
$value 'Yes';

        
$result = \XLite\Core\Database::getRepo('\XLite\Model\AttributeValue\AttributeValueSelect')
            ->
createQueryBuilder('avs')
            ->
linkInner('avs.attribute''a')
            ->
linkInner('a.translations''at')
            ->
linkInner('avs.attribute_option''ao')
            ->
linkInner('ao.translations''aot')
            ->
andWhere('at.name = :attributename AND aot.name = :optionvalue')
            ->
setParameter('attributename'$name)
            ->
setParameter('optionvalue'$value)
            ->
getResult();

        
$return = array();

        foreach (
$result as $attribute) {
            
$return[] = $attribute->getProduct();
        }

        return 
$return;
    }
}


instead of yours:

PHP Code:

<?php
namespace XLite\Module\Astur\SirtoliSkin\Model\Repo;

class 
Product extends \XLite\Model\Repo\Product implements \XLite\Base\IDecorator {

protected 
$name 'Vintage';
protected 
$value 'Yes';

    public function 
findAllVintage() {

    return \
XLite\Core\Database::getRepo('\XLite\Model\AttributeValue\AttributeValueSelect')
    ->
createQueryBuilder('avs')
    ->
linkInner('avs.attribute''a')
    ->
linkInner('a.translations''at')
    ->
linkInner('avs.attribute_option''ao')
    ->
linkInner('ao.translations''aot')
    ->
andWhere('at.name = :attributename AND aot.name = :optionvalue')
    ->
setParameter('attributename'$name)
    ->
setParameter('optionvalue'$value)
    ->
getResult();
    }
}


As you can see, there are couple of changes:
1) I foreach $result and call getProduct() of each $attribute returned from the database. If you do not do this, your findAllVintage() method will return AttributeValue objects instead of products.
2) I moved constants $name and $value into a method instead of them being a part of class properties.

Please, try my code and let me know if it works for you. If it does not, please give me a snapshot of how you set up a vintage attribute for a product.



Suppose i need attribute value of current product.
How can i add condition here ? Please advise.

jameshouston135 09-06-2018 03:31 AM

Re: How to display products with a particular attribute
 
Hi my website is homebrandsusa will you please set it's products structure or tell me what should i have to do. For searching the solution on it i recently got an article that how to find the best selling products but really not know about products structure.


All times are GMT -8. The time now is 11:31 PM.

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