Jump to content

How to get the features of a product


Recommended Posts

Posted (edited)

Hi, 

I'm developping a module to display a tag on a product but only if the product has the "HOT" feature equals 1. 

Here's my code:


    public function hookDisplayProductPriceBlock($params)
    {
        $product = $params['product'];
        if ($product->HOT == 1) {
            return $this->display(__FILE__, 'views/templates/hook/hotproduct.tpl');
        }
    }

It doesn't show anything on a product with the HOT attribute at 1. If I remove the condition, it does show!

 

I also tried that:

    public function hookDisplayProductPriceBlock($params)
    {
        $product = $params['product'];
		
		
		// Obtener las características del producto
		$features = $product->getFrontFeatures($this->context->language->id);

		// Buscar la característica "HOT" entre las características del producto
		$hotValue = null;
		foreach ($features as $feature) {
			if ($feature['name'] === 'HOT') {
				return $this->display(__FILE__, 'views/templates/hook/hotproduct.tpl');
				break;
			}
		}
		
        //if ($product->HOT == 1) {
          //  return $this->display(__FILE__, 'views/templates/hook/hotproduct.tpl');
      //  }
    }

but give me this error: PHP Fatal error:  Uncaught Error: Call to undefined method PrestaShop\PrestaShop\Adapter\Presenter\Product\ProductLazyArray::getFrontFeatures()

 

Any idea?

Edited by Maria Gonzalez (see edit history)
Link to comment
Share on other sites

  • Maria Gonzalez changed the title to How to get the features of a product
1 hour ago, ZHSoft said:

It seems like you're encountering a couple of issues here. Let's address them:

1. **Accessing Product Features**: The method `getFrontFeatures()` is not available in the `ProductLazyArray` class, which is what `$product` is in your context. Instead, you should fetch product features using the `Feature` class.

2. **Checking for the "HOT" Feature**: Once you've fetched the product features, you need to check if the "HOT" feature is enabled for the product. This typically involves finding the feature ID for "HOT" and then checking if it's enabled for the product.

Here's how you can adjust your code to address these issues:

public function hookDisplayProductPriceBlock($params)
{
    $product = $params['product'];
    
    // Get the features for the product
    $features = Feature::getFeatures($this->context->language->id, $product->id);
    
    // Iterate through features to find "HOT" feature
    foreach ($features as $feature) {
        if ($feature['name'] === 'HOT') {
            // Check if the feature is enabled for the product
            $productHasHotFeature = FeatureProduct::isFeatureProductActive($product->id, $feature['id_feature']);
            if ($productHasHotFeature) {
                return $this->display(__FILE__, 'views/templates/hook/hotproduct.tpl');
            }
        }
    }
    
    // If "HOT" feature not found or not enabled, return null
    return null;
}

This code fetches the features for the product, iterates through them to find the "HOT" feature, and then checks if it's enabled for the product. If it is, it displays the `hotproduct.tpl` template. If not, it returns null, indicating that nothing should be displayed.

Make sure to replace `'HOT'` with the actual name of your feature if it's different, and adjust the logic accordingly if necessary.

Hi, thanks for your suggestion. With your code I get the following error:

PHP message: PHP Fatal error:  Uncaught Error: Class "FeatureProduct" not found in /var/www/html/xxxx.fr/modules/hotproduct/hotproduct.php:44
Stack trace:
#0 /var/www/html/xxxx.fr/classes/Hook.php(1043): HotProduct->hookDisplayProductPriceBlock()
#1 /var/www/html/xxxx.fr/classes/Hook.php(418): HookCore::coreCallHook()
#2 /var/www/html/xxxx.fr/classes/Hook.php(981): HookCore::callHookOn()
#3 /var/www/html/xxxx.fr/config/smarty.config.inc.php(198): HookCore::exec()
#4 /var/www/html/xxxx.fr/classes/Smarty/SmartyLazyRegister.php(81): smartyHook()
#5 /var/www/html/xxxx.fr/var/cache/prod/smarty/compile/classiclayouts_layout_full_width_tpl/f6/92/45/f69245805fd171a2ee2e24dea3052363e7eda826_2.file.product-prices.tpl.php(102): SmartyLazyRegister->__call()
#6 /var/www/html/xxxx.fr/vendor/smarty/smarty/libs/sysplugins/smarty_internal_runtime_inheritance.php(248): Block_156355770663dd0e09f6ce4_83936101->callBlock()
#7 /var/www/html/xxxx.fr/vendor/smarty/smarty/libs/" while reading response header from upstream, client: 192.168.0.25, server: www.xxxx.fr, request: "GET /xlus.html HTTP/1.1", upstream: "fastcgi://unix:/run/php/php8.2-fpm.sock:", host: "xxxx.fr", referrer: "https://xxxx.fr/1xxe"

 

Link to comment
Share on other sites

Hello,

If you try and print out the $params['product'] array, you will see that it has a 'features' key, which contains all the features.

public function hookDisplayProductPriceBlock($params)
{
    if ($this->isDisplayed) {
        return;
    }

    foreach ($params['product']['features'] as $feature) {
        if ($feature['name'] === 'HOT') {
            echo '<p>This is a hot feature</p>';
            $this->isDisplayed = true;
        }
    }
}

You will also need to add a property in the class called $isDisplayed and initially set it to false. This is because this hook is called multiple times, thus printing that line in each call. This will prevent it displaying the content more than once.
 

Link to comment
Share on other sites

40 minutes ago, Andrei H said:

Hello,

If you try and print out the $params['product'] array, you will see that it has a 'features' key, which contains all the features.

public function hookDisplayProductPriceBlock($params)
{
    if ($this->isDisplayed) {
        return;
    }

    foreach ($params['product']['features'] as $feature) {
        if ($feature['name'] === 'HOT') {
            echo '<p>This is a hot feature</p>';
            $this->isDisplayed = true;
        }
    }
}

You will also need to add a property in the class called $isDisplayed and initially set it to false. This is because this hook is called multiple times, thus printing that line in each call. This will prevent it displaying the content more than once.
 

Thanks Andrei! It works!! However a scrange issue is happening with that code. It gives me error 502 : Bad Gateway on the category page....
 

Link to comment
Share on other sites

use echo '<p>This is a hot feature</p>'; this is not a recommended practice depending on the context in which it is applied and may generate errors when rendering content.

  • Like 1
Link to comment
Share on other sites

6 minutes ago, ventura said:

use echo '<p>This is a hot feature</p>'; this is not a recommended practice depending on the context in which it is applied and may generate errors when rendering content.

Hello,

Yes, that's true. I was just trying to highlight how this can be achieved. That line should be replaced with

return $this->display(__FILE__, 'views/templates/hook/hotproduct.tpl');

 and the

$this->isDisplayed = true; 

added above it.

However, I am not sure if that is causing the 502.

If you remove the code, does it clear the 502?

Link to comment
Share on other sites

Posted (edited)
1 hour ago, Andrei H said:

Hello,

Yes, that's true. I was just trying to highlight how this can be achieved. That line should be replaced with

return $this->display(__FILE__, 'views/templates/hook/hotproduct.tpl');

 and the

$this->isDisplayed = true; 

added above it.

However, I am not sure if that is causing the 502.

If you remove the code, does it clear the 502?

Yes, I have done those changes and the 502 on category page still happens! If I remove the code, the error clears

 

The nginx error I'm having is: 

PHP message: PHP Warning:  Undefined property: HotProduct::$isDisplayed   (on the if)

Edited by Maria Gonzalez (see edit history)
Link to comment
Share on other sites

1 hour ago, Maria Gonzalez said:

Yes, I have done those changes and the 502 on category page still happens! If I remove the code, the error clears

 

The nginx error I'm having is: 

PHP message: PHP Warning:  Undefined property: HotProduct::$isDisplayed   (on the if)

SOLVED, forget to initialize at the class construct!

  • Like 1
Link to comment
Share on other sites

Hello,

Yes, I just noticed that as well. It looks like the if is stopping the display.You can rewrite the hook as follows:

public function hookDisplayProductPriceBlock($params)
{
    $productId = $params['product']['id_product'];
    if (!empty($this->isDisplayed[$productId])) {
        return;
    }

    foreach ($params['product']['features'] as $feature) {
        if ($feature['name'] === 'HOT') {
            $this->isDisplayed[$productId] = true;
            return $this->display(__FILE__, 'views/templates/hook/hotproduct.tpl');
        }
    }
}

You will also need to change the isDisplayed property in your constructor. It should be an empty array now.

This way, it should be displayed for all the products. The only downside is that if the same product is displayed multiple times in a page, only the first one will have the text.

Link to comment
Share on other sites

2 hours ago, Andrei H said:

Hello,

Yes, I just noticed that as well. It looks like the if is stopping the display.You can rewrite the hook as follows:

public function hookDisplayProductPriceBlock($params)
{
    $productId = $params['product']['id_product'];
    if (!empty($this->isDisplayed[$productId])) {
        return;
    }

    foreach ($params['product']['features'] as $feature) {
        if ($feature['name'] === 'HOT') {
            $this->isDisplayed[$productId] = true;
            return $this->display(__FILE__, 'views/templates/hook/hotproduct.tpl');
        }
    }
}

You will also need to change the isDisplayed property in your constructor. It should be an empty array now.

This way, it should be displayed for all the products. The only downside is that if the same product is displayed multiple times in a page, only the first one will have the text.

I see that it should work now! but it's not, still only shown on the first product!!

Link to comment
Share on other sites

Hello,

Have you also tried to clear the cache from Admin -> Advanced Parameters -> Performance?

It looks like the product data is cached for some pages.

If this still not works, you will need to do some local debugging. For me, it is working as expected.
 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...