New system to add option/attribute values to product class for addons.

Open to all! Ask other shopowners for help.
Post Reply
raiwa
Certified Developer
Posts: 1640
Joined: Sat Dec 21, 2019 8:08 am
Phoenix Version: 1.1.0.6
Has thanked: 70 times
Been thanked: 152 times

New system to add option/attribute values to product class for addons.

Post by raiwa »

Hi,

With Matt’s help, I’ve developed a new system to add custom option/attribute values to the product class.

This system eliminates the need to override the entire product_loader class just to add custom values within the load_attributes method, located here:
includes/system/versioned/1.0.7.other/1.0.7.12/product_loader.php

Instead, it uses a system hook that overrides the load_attributes method. It performs a liberalized option/attribute query to retrieve all existing table columns, and includes a hook call that allows you to extend the attributes array with additional custom option/attribute values.

Here is the system hook file:
includes/hooks/shop/system/_09_loadAttributesRaiwa.php

Code: Select all

<?php
/*
* $Id: _09_loadAttributesRaiwa.php
* $Loc: /includes/hooks/shop/system/
*
* Name: OptionsImages
* Version: 3.2
* Release Date: 2025-04-14
* Author: Rainer Schmied
* 	 phoenixcartaddonsaddons.com / raiwa@phoenixcartaddons.com
*
* License: Released under the GNU General Public License
*
* Comments: Author: [Rainer Schmied @raiwa]
* Author URI: [www.phoenixcartaddons.com]
* 
* CE Phoenix, E-Commerce made Easy
* https://phoenixcart.org
* 
* Copyright (c) 2021 Phoenix Cart
* 
* 
*/

class hook_shop_system__09_loadAttributesRaiwa {

  protected static $saved_attribute_loader = null;

  public function listen_productCapabilities($parameters) {
      self::$saved_attribute_loader = $parameters['capabilities']['attributes'];
      $parameters['capabilities']['attributes'] = __CLASS__ . '::add_image_to_attributes';
  }

  public static function add_image_to_attributes($product) {
    $attributes = call_user_func(self::$saved_attribute_loader, $product);
    
    $attributes_query_raw = sprintf(<<<'EOSQL'
SELECT po.*, pov.*, pa.*,
       pad.products_attributes_filename, pad.products_attributes_maxdays, pad.products_attributes_maxcount
 FROM products_options po
  INNER JOIN products_attributes pa ON po.products_options_id = pa.options_id
  LEFT JOIN products_options_values pov ON pa.options_values_id = pov.products_options_values_id AND po.language_id = pov.language_id
  LEFT JOIN products_attributes_download pad ON pa.products_attributes_id = pad.products_attributes_id
 WHERE po.language_id = %d AND pa.products_id = %d
EOSQL
    , (int)($language_id ?? $_SESSION['languages_id']), (int)$product->get('id'));

    if (defined('AM_DEFAULT_TEMPLATE_ORDER')) {
    $attributes_query_raw .= <<<'EOSQL'
 ORDER BY pa.sort_order, po.sort_order, po.products_options_name, pov.sort_order, pov.products_options_values_name
EOSQL
;
    } else {
    $attributes_query_raw .= <<<'EOSQL'
 ORDER BY po.sort_order, po.products_options_name, pov.sort_order, pov.products_options_values_name
EOSQL
;
    }

    $attributes_query = $GLOBALS['db']->query($attributes_query_raw);

    $attributes = [];
    while ($attribute = $attributes_query->fetch_assoc()) {
      if (!isset($attributes[$attribute['options_id']])) {
        $attributes[$attribute['options_id']] = [
          'name' => $attribute['products_options_name'],
          'values' => [],
        ];
      }
      $attributes[$attribute['options_id']]['values'][$attribute['options_values_id']] = [
        'name' => $attribute['products_options_values_name'],
        'prefix' => $attribute['price_prefix'],
        'price' => $attribute['options_values_price'],
        'filename' => $attribute['products_attributes_filename'],
        'maxdays' => $attribute['products_attributes_maxdays'],
        'maxcount' => $attribute['products_attributes_maxcount'],
      ];
    }

    $parameters = [
      'attributes' => &$attributes,
      'attributes_query' => $attributes_query,
    ];

    $GLOBALS['all_hooks']->cat('load_attributes', $parameters);

    $product->set('has_attributes', (count($attributes) > 0) ? '1' : '0');
    $product->set('attributes', $attributes);
    
    return $attributes;

  }



}
To add values, a siteWide hook can be used. Here’s an example I made for Option Images:

Code: Select all

<?php
/*
* $Id: optImages.php
* $Loc: /includes/hooks/shop/siteWide/
*
* Name: OptionsImages
* Version: 3.2
* Release Date: 2025-04-14
* Author: Rainer Schmied
* 	 phoenixcartaddonsaddons.com / raiwa@phoenixcartaddons.com
*
* License: Released under the GNU General Public License
*
* Comments: Author: [Rainer Schmied @raiwa]
* Author URI: [www.phoenixcartaddons.com]
* 
* CE Phoenix, E-Commerce made Easy
* https://phoenixcart.org
* 
* Copyright (c) 2021 Phoenix Cart
* 
* 
*/

class hook_shop_siteWide_optImages {


  public function listen_load_attributes($parameters) {
    $attributes = &$parameters['attributes'];
    $attributes_query = $parameters['attributes_query'];
    $attribute = $attributes_query->data_seek(0);

    while ($attribute = $attributes_query->fetch_assoc()) {

      if ( isset($attribute['option_image']) || isset($attribute['products_options_values_image']) ) {
        $attributes[$attribute['options_id']]['values'][$attribute['options_values_id']]['image'] = $attribute['option_image'] ?: $attribute['products_options_values_image'] ?: '';
      }
      
    }
  }

}
Advantages:

Only the load_attributes method is overridden, instead of the entire product_loader class.

Multiple addons can add custom option/attribute values independently, without the need to manually merge or combine the product_loader class.

I’ve already refactored the following addons to use this new system:
Ajax Attributes Manager 4.0+
Attributes Weight 2.1+
Option Images 3.2+
Option Types 2.1+
QtPro 8.0+
Wholesale Lite 5.1+
Wholesale Pro 5.1+

For developers who want to use this system:

Include the hook file with your addon:
includes/hooks/shop/system/_09_loadAttributesRaiwa.php
(Include the Note: This file may already exist if any of the above addons are installed.)

Copy the second hook as a template:
includes/hooks/shop/siteWide/optImages.php
Rename and modify it according to your addon’s requirements.

Here both hooks packed:
options_attributes_hooks.zip

Enjoy!
Rainer
You do not have the required permissions to view the files attached to this post.
Public Phoenix Change Log Cheat Set on Google Sheets
https://docs.google.com/spreadsheets/d/ ... sp=sharing

Need Help?viewtopic.php?f=10&t=27

Tags:


Join The Code Co-op to get access to your library in the Code Co-op Forum
Post Reply