Hola
Espero puedan ayudarme.
Estoy haciendo actualizando mi instalación de prestashop para que el listado de productos se por atributo, en mi caso sea por color.
- He logrado que se listen los productos por color en la pagina de inicio (productos destacados)
- Pero al ingresar a la página de categorías, ya sea por Todos los Productos o el menú de categorías, me da error:
(1/1) ContextErrorException
Warning: htmlspecialchars() expects parameter 1 to be string, array given
- Para lograr que se listen los productos por color en la pagina de inicio (productos destacados), he creado en Override/Classes, los archivos product.php y category.php (los cuales he adjuntado).
- Dentro de los archivos modifico las funciones
getProductProperties(), en product.php
getProducts(), en category.php
lo que modifico en ellas son las consultas sql de recuperación de lista y datos del producto
Quedo pendiente de su ayuda, espero puedan hacerlo.
- Pego el código de las funciones modificadas:
product.php
class Product extends ProductCore
{
public static function getProductProperties($id_lang, $row, Context $context = null)
{
Hook::exec('actionGetProductPropertiesBefore', [
'id_lang' => $id_lang,
'product' => &$row,
'context' => $context,
]);
if (!$row['id_product']) {
return false;
}
if ($context == null) {
$context = Context::getContext();
}
$id_product_attribute = $row['id_product_attribute'] = (!empty($row['id_product_attribute']) ? (int) $row['id_product_attribute'] : null);
// Product::getDefaultAttribute is only called if id_product_attribute is missing from the SQL query at the origin of it:
// consider adding it in order to avoid unnecessary queries
$row['allow_oosp'] = Product::isAvailableWhenOutOfStock($row['out_of_stock']);
if (Combination::isFeatureActive() && $id_product_attribute === null
&& ((isset($row['cache_default_attribute']) && ($ipa_default = $row['cache_default_attribute']) !== null)
|| ($ipa_default = Product::getDefaultAttribute($row['id_product'], !$row['allow_oosp'])))) {
$id_product_attribute = $row['id_product_attribute'] = $ipa_default;
}
if (!Combination::isFeatureActive() || !isset($row['id_product_attribute'])) {
$id_product_attribute = $row['id_product_attribute'] = 0;
}
// Tax
$usetax = !Tax::excludeTaxeOption();
$cache_key = $row['id_product'] . '-' . $id_product_attribute . '-' . $id_lang . '-' . (int) $usetax;
if (isset($row['id_product_pack'])) {
$cache_key .= '-pack' . $row['id_product_pack'];
}
if(empty($row['image_id']))
{
if (!isset($row['cover_image_id']))
{
$cover = static::getCover($row['id_product']);
if (isset($cover['id_image']))
{
$row['cover_image_id'] = $cover['id_image'];
}
}
}
else
{
//$row['cover_image_id'] = 20;
$row['cover_image_id'] = $row['image_id'];
}
if (isset($row['cover_image_id'])) {
$cache_key .= '-cover' . (int) $row['cover_image_id'];
}
if (isset(self::$productPropertiesCache[$cache_key])) {
return array_merge($row, self::$productPropertiesCache[$cache_key]);
}
// Datas
$row['category'] = Category::getLinkRewrite((int) $row['id_category_default'], (int) $id_lang);
$row['category_name'] = Db::getInstance()->getValue('SELECT name FROM ' . _DB_PREFIX_ . 'category_lang WHERE id_shop = ' . (int) $context->shop->id . ' AND id_lang = ' . (int) $id_lang . ' AND id_category = ' . (int) $row['id_category_default']);
$row['link'] = $context->link->getProductLink((int) $row['id_product'], $row['link_rewrite'], $row['category'], $row['ean13']);
$row['attribute_price'] = 0;
if ($id_product_attribute) {
$row['attribute_price'] = (float) Combination::getPrice($id_product_attribute);
}
if (isset($row['quantity_wanted'])) {
// 'quantity_wanted' may very well be zero even if set
$quantity = max((int) $row['minimal_quantity'], (int) $row['quantity_wanted']);
} elseif (isset($row['cart_quantity'])) {
$quantity = max((int) $row['minimal_quantity'], (int) $row['cart_quantity']);
} else {
$quantity = (int) $row['minimal_quantity'];
}
$row['price_tax_exc'] = Product::getPriceStatic(
(int) $row['id_product'],
false,
$id_product_attribute,
(self::$_taxCalculationMethod == PS_TAX_EXC ? 2 : 6),
null,
false,
true,
$quantity
);
if (self::$_taxCalculationMethod == PS_TAX_EXC) {
$row['price_tax_exc'] = Tools::ps_round($row['price_tax_exc'], Context::getContext()->getComputingPrecision());
$row['price'] = Product::getPriceStatic(
(int) $row['id_product'],
true,
$id_product_attribute,
6,
null,
false,
true,
$quantity
);
$row['price_without_reduction'] =
$row['price_without_reduction_without_tax'] = Product::getPriceStatic(
(int) $row['id_product'],
false,
$id_product_attribute,
2,
null,
false,
false,
$quantity
);
} else {
$row['price'] = Tools::ps_round(
Product::getPriceStatic(
(int) $row['id_product'],
true,
$id_product_attribute,
6,
null,
false,
true,
$quantity
),
Context::getContext()->getComputingPrecision()
);
$row['price_without_reduction'] = Product::getPriceStatic(
(int) $row['id_product'],
true,
$id_product_attribute,
6,
null,
false,
false,
$quantity
);
$row['price_without_reduction_without_tax'] = Product::getPriceStatic(
(int) $row['id_product'],
false,
$id_product_attribute,
6,
null,
false,
false,
$quantity
);
}
$row['reduction'] = Product::getPriceStatic(
(int) $row['id_product'],
(bool) $usetax,
$id_product_attribute,
6,
null,
true,
true,
$quantity,
true,
null,
null,
null,
$specific_prices
);
$row['reduction_without_tax'] = Product::getPriceStatic(
(int) $row['id_product'],
false,
$id_product_attribute,
6,
null,
true,
true,
$quantity,
true,
null,
null,
null,
$specific_prices
);
$row['specific_prices'] = $specific_prices;
$row['quantity'] = Product::getQuantity(
(int) $row['id_product'],
0,
isset($row['cache_is_pack']) ? $row['cache_is_pack'] : null,
$context->cart
);
$row['quantity_all_versions'] = $row['quantity'];
if ($row['id_product_attribute']) {
$row['quantity'] = Product::getQuantity(
(int) $row['id_product'],
$id_product_attribute,
isset($row['cache_is_pack']) ? $row['cache_is_pack'] : null,
$context->cart
);
$row['available_date'] = Product::getAvailableDate(
(int) $row['id_product'],
$id_product_attribute
);
}
$row['id_image'] = Product::defineProductImage($row, $id_lang);
$row['features'] = Product::getFrontFeaturesStatic((int) $id_lang, $row['id_product']);
$row['attachments'] = [];
if (!isset($row['cache_has_attachments']) || $row['cache_has_attachments']) {
$row['attachments'] = Product::getAttachmentsStatic((int) $id_lang, $row['id_product']);
}
$row['virtual'] = ((!isset($row['is_virtual']) || $row['is_virtual']) ? 1 : 0);
// Pack management
$row['pack'] = (!isset($row['cache_is_pack']) ? Pack::isPack($row['id_product']) : (int) $row['cache_is_pack']);
$row['packItems'] = $row['pack'] ? Pack::getItemTable($row['id_product'], $id_lang) : [];
$row['nopackprice'] = $row['pack'] ? Pack::noPackPrice($row['id_product']) : 0;
if ($row['pack'] && !Pack::isInStock($row['id_product'], $quantity, $context->cart)) {
$row['quantity'] = 0;
}
$row['customization_required'] = false;
if (isset($row['customizable']) && $row['customizable'] && Customization::isFeatureActive()) {
if (count(Product::getRequiredCustomizableFieldsStatic((int) $row['id_product']))) {
$row['customization_required'] = true;
}
}
$attributes = Product::getAttributesParams($row['id_product'], $row['id_product_attribute']);
foreach ($attributes as $attribute) {
$row['attributes'][$attribute['id_attribute_group']] = $attribute;
}
$row = Product::getTaxesInformations($row, $context);
$row['ecotax_rate'] = (float) Tax::getProductEcotaxRate($context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')});
Hook::exec('actionGetProductPropertiesAfter', [
'id_lang' => $id_lang,
'product' => &$row,
'context' => $context,
]);
$combination = new Combination($id_product_attribute);
if (0 != $combination->unit_price_impact && 0 != $row['unit_price_ratio']) {
$unitPrice = ($row['price_tax_exc'] / $row['unit_price_ratio']) + $combination->unit_price_impact;
$row['unit_price_ratio'] = $row['price_tax_exc'] / $unitPrice;
}
$row['unit_price'] = ($row['unit_price_ratio'] != 0 ? $row['price'] / $row['unit_price_ratio'] : 0);
self::$productPropertiesCache[$cache_key] = $row;
return self::$productPropertiesCache[$cache_key];
}
}
=================================================================================================
category.php
class Category extends CategoryCore
{
public function getProducts($id_lang,
$p,
$n,
$order_by = null,
$order_way = null,
$get_total = false,
$active = true,
$random = false,
$random_number_products = 1,
$check_access = true,
Context $context = null)
{
if (!$context) {
$context = Context::getContext();
}
if ($check_access && !$this->checkAccess($context->customer->id)) {
return false;
}
$front = in_array($context->controller->controller_type, array('front', 'modulefront'));
$id_supplier = (int)Tools::getValue('id_supplier');
/** Return only the number of products */
if ($get_total) {
/*$sql = 'SELECT COUNT(cp.`id_product`) AS total
FROM `'._DB_PREFIX_.'product` p
'.Shop::addSqlAssociation('product', 'p').'
LEFT JOIN `'._DB_PREFIX_.'category_product` cp ON p.`id_product` = cp.`id_product`
LEFT JOIN `'._DB_PREFIX_.'product_attribute` pa ON pa.`id_product` = p.`id_product`
WHERE cp.`id_category` = '.(int)$this->id.
($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '').
($active ? ' AND product_shop.`active` = 1' : '').
($id_supplier ? 'AND p.id_supplier = '.(int)$id_supplier : '');*/
$sql = 'SELECT COUNT(cp.`id_product`) AS total
FROM `'._DB_PREFIX_.'product` p
'.Shop::addSqlAssociation('product', 'p').'
LEFT JOIN '._DB_PREFIX_.'product_lang pl on pl.id_product=p.id_product
LEFT JOIN `'._DB_PREFIX_.'category_product` cp ON p.`id_product` = cp.`id_product`
LEFT JOIN (select a.id_attribute,
a.id_attribute_group,
a.color,
al.id_lang,
al.name,
pac.id_product_attribute,
pa.id_product,
pa.reference
from '._DB_PREFIX_.'attribute a
inner JOIN '._DB_PREFIX_.'attribute_lang al on al.id_attribute=a.id_attribute
INNER JOIN '._DB_PREFIX_.'product_attribute_combination pac on pac.id_attribute=a.id_attribute
inner join '._DB_PREFIX_.'product_attribute pa ON pa.`id_product_attribute` = pac.`id_product_attribute`
WHERE a.id_attribute_group=2
GROUP BY pa.id_product,a.id_attribute) sa on sa.id_product=p.id_product
WHERE cp.`id_category` = '.(int)$this->id.
($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '').
($active ? ' AND product_shop.`active` = 1' : '').
($id_supplier ? 'AND p.id_supplier = '.(int)$id_supplier : '').
' GROUP BY p.id_product,sa.id_attribute';
return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
}
if ($p < 1) {
$p = 1;
}
/** Tools::strtolower is a fix for all modules which are now using lowercase values for 'orderBy' parameter */
$order_by = Validate::isOrderBy($order_by) ? Tools::strtolower($order_by) : 'position';
$order_way = Validate::isOrderWay($order_way) ? Tools::strtoupper($order_way) : 'ASC';
$order_by_prefix = false;
if ($order_by == 'id_product' || $order_by == 'date_add' || $order_by == 'date_upd') {
$order_by_prefix = 'p';
} elseif ($order_by == 'name') {
$order_by_prefix = 'pl';
} elseif ($order_by == 'manufacturer' || $order_by == 'manufacturer_name') {
$order_by_prefix = 'm';
$order_by = 'name';
} elseif ($order_by == 'position') {
$order_by_prefix = 'cp';
}
if ($order_by == 'price') {
$order_by = 'orderprice';
}
$nb_days_new_product = Configuration::get('PS_NB_DAYS_NEW_PRODUCT');
if (!Validate::isUnsignedInt($nb_days_new_product)) {
$nb_days_new_product = 20;
}
$sql = 'SELECT p.*,
product_shop.*,
stock.out_of_stock,
IFNULL(stock.quantity, 0) AS quantity'.(Combination::isFeatureActive() ? ',
IFNULL(product_attribute_shop.id_product_attribute, 0) AS id_product_attribute,
product_attribute_shop.minimal_quantity AS product_attribute_minimal_quantity' : '').',
pl.`description`,
pl.`description_short`,
pl.`available_now`,
pl.`available_later`,
pl.`link_rewrite`,
pl.`meta_description`,
pl.`meta_keywords`,
pl.`meta_title`,
pl.`name`,
image_shop.`id_image` id_image,
il.`legend` as legend,
m.`name` AS manufacturer_name,
cl.`name` AS category_default,
DATEDIFF(product_shop.`date_add`,
DATE_SUB("'.date('Y-m-d').' 00:00:00",
INTERVAL '.(int)$nb_days_new_product.' DAY)) > 0 AS new,
product_shop.price AS orderprice,
sa.id_product_attribute,
sa.id_attribute,
sa.nombre_color,
sa.`id_image` image_id
FROM `'._DB_PREFIX_.'category_product` cp
LEFT JOIN `'._DB_PREFIX_.'product` p ON p.`id_product` = cp.`id_product`
'.Shop::addSqlAssociation('product', 'p').
(Combination::isFeatureActive() ? ' LEFT JOIN `'._DB_PREFIX_.'product_attribute_shop` product_attribute_shop
ON (p.`id_product` = product_attribute_shop.`id_product` AND product_attribute_shop.`default_on` = 1 AND product_attribute_shop.id_shop='.(int)$context->shop->id.')':'').'
'.Product::sqlStock('p', 0).'
LEFT JOIN `'._DB_PREFIX_.'category_lang` cl ON (product_shop.`id_category_default` = cl.`id_category` AND cl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('cl').')
LEFT JOIN `'._DB_PREFIX_.'product_lang` pl ON (p.`id_product` = pl.`id_product` AND pl.`id_lang` = '.(int)$id_lang.Shop::addSqlRestrictionOnLang('pl').')
LEFT JOIN (select a.id_attribute,
a.id_attribute_group,
a.color,
al.id_lang,
al.name as nombre_color,
pac.id_product_attribute,
pa.id_product,
pa.reference,
pai.id_image
from '._DB_PREFIX_.'attribute a
inner JOIN '._DB_PREFIX_.'attribute_lang al on al.id_attribute=a.id_attribute and al.id_lang='.(int)$id_lang.'
INNER JOIN '._DB_PREFIX_.'product_attribute_combination pac on pac.id_attribute=a.id_attribute
inner join '._DB_PREFIX_.'product_attribute pa ON pa.`id_product_attribute` = pac.`id_product_attribute`
inner join ps_product_attribute_image pai ON pai.`id_product_attribute` = pa.`id_product_attribute`
WHERE a.id_attribute_group=2
GROUP BY pa.id_product,a.id_attribute) sa on sa.id_product=p.id_product
LEFT JOIN `'._DB_PREFIX_.'image_shop` image_shop ON (image_shop.`id_product` = p.`id_product` AND image_shop.cover=1 AND image_shop.id_shop='.(int)$context->shop->id.')
LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (image_shop.`id_image` = il.`id_image` AND il.`id_lang` = '.(int)$id_lang.')
LEFT JOIN `'._DB_PREFIX_.'manufacturer` m ON m.`id_manufacturer` = p.`id_manufacturer`
WHERE product_shop.`id_shop` = '.(int)$context->shop->id.'
AND cp.`id_category` = '.(int)$this->id
.($active ? ' AND product_shop.`active` = 1' : '')
.($front ? ' AND product_shop.`visibility` IN ("both", "catalog")' : '')
.($id_supplier ? ' AND p.id_supplier = '.(int)$id_supplier : '');
if ($random === true)
{
$sql .= ' ORDER BY RAND() LIMIT '.(int)$random_number_products;
}
else
{
$sql .= ' ORDER BY '.(!empty($order_by_prefix) ? $order_by_prefix.'.' : '').'`'.bqSQL($order_by).'` '.pSQL($order_way).'
LIMIT '.(((int)$p - 1) * (int)$n).','.(int)$n;
}
$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql, true, false);
if (!$result)
{
return array();
}
if ($order_by == 'orderprice') {
Tools::orderbyPrice($result, $order_way);
}
/* Extended name */
foreach ($result as &$p)
{
$attributes = Db::getInstance()->ExecuteS('
SELECT al.name
FROM '._DB_PREFIX_.'attribute_lang al
WHERE al.id_attribute IN (SELECT pac.id_attribute
FROM '._DB_PREFIX_.'product_attribute_combination pac
WHERE pac.id_product_attribute = '.(int)$p['id_product_attribute'].')
AND al.id_lang = '.(int)$id_lang);
$extended_name = $p['name'].' (';
foreach ($attributes as $a)
$extended_name .= $a['name'].', ';
$p['name'] = rtrim($extended_name, ', ').')';
}
/** Modify SQL result */
return Product::getProductsProperties($id_lang, $result);
}
}
Product.php
Category.php