Prestashop Search only display exactly - prestashop

I am new to Prestahop 1.6 and I want to change the behaviour of the search form
Currently searching '2/05' will return '22/05', '20/5', '2/051'
Desired: '2/05' will return '2/05' ONLY if exists.

You need to overrride the find method of search class in override/classes/Search.php , here what i use on my shop :
class Search extends SearchCore {
public static function find($id_lang, $expr, $page_number = 1, $page_size = 1, $order_by = 'position', $order_way = 'desc', $ajax = false, $use_cookie = true, Context $context = null) {
if (! $context) {
$context = Context::getContext();
}
$db = Db::getInstance(_PS_USE_SQL_SLAVE_);
// TODO : smart page management
if ($page_number < 1) {
$page_number = 1;
}
if ($page_size < 1) {
$page_size = 1;
}
if (! Validate::isOrderBy($order_by) || ! Validate::isOrderWay($order_way)) {
return false;
}
$intersect_array = array();
$score_array = array();
$words = Search::extractKeyWords($expr, $id_lang, false, $context->language->iso_code);
foreach ($words as $key => $word) {
if (! empty($word) && strlen($word) >= (int) Configuration::get('PS_SEARCH_MINWORDLEN')) {
// $sql_param_search = self::getSearchParamFromWord($word);
$word = str_replace(array(
'%',
'_'
), array(
'\\%',
'\\_'
), $word);
$start_search = Configuration::get('PS_SEARCH_START') ? '%' : '';
$end_search = Configuration::get('PS_SEARCH_END') ? '' : '%';
$sql_param_search = ($word[0] == '-' ? ' \'' . $start_search . pSQL(Tools::substr($word, 1, PS_SEARCH_MAX_WORD_LENGTH)) . $end_search . '\'' : ' \'' . $start_search . pSQL(Tools::substr($word, 0, PS_SEARCH_MAX_WORD_LENGTH)) . $end_search . '\'');
$intersect_array[] = 'SELECT DISTINCT si.id_product
FROM ' . _DB_PREFIX_ . 'search_word sw
LEFT JOIN ' . _DB_PREFIX_ . 'search_index si ON sw.id_word = si.id_word
WHERE sw.id_lang = ' . (int) $id_lang . '
AND sw.id_shop = ' . $context->shop->id . '
AND sw.word LIKE ' . $sql_param_search;
if ($word[0] != '-') $score_array[] = 'sw.word LIKE \'' . $start_search . pSQL(Tools::substr($word, 0, PS_SEARCH_MAX_WORD_LENGTH)) . $end_search . '\'';
} else {
unset($words[$key]);
}
}
if (! count($words)) {
return $ajax ? array() : array(
'total' => 0,
'result' => array()
);
}
$score = '';
if (is_array($score_array) && ! empty($score_array)) {
$score = ',(
SELECT SUM(weight)
FROM ' . _DB_PREFIX_ . 'search_word sw
LEFT JOIN ' . _DB_PREFIX_ . 'search_index si ON sw.id_word = si.id_word
WHERE sw.id_lang = ' . (int) $id_lang . '
AND sw.id_shop = ' . $context->shop->id . '
AND si.id_product = p.id_product
AND (' . implode(' OR ', $score_array) . ')
) position';
}
$sql_groups = '';
if (Group::isFeatureActive()) {
$groups = FrontController::getCurrentCustomerGroups();
$sql_groups = 'AND cg.`id_group` ' . (count($groups) ? 'IN (' . implode(',', $groups) . ')' : '= 1');
}
$results = $db->executeS('
SELECT DISTINCT cp.`id_product`
FROM `' . _DB_PREFIX_ . 'category_product` cp
' . (Group::isFeatureActive() ? 'INNER JOIN `' . _DB_PREFIX_ . 'category_group` cg ON cp.`id_category` = cg.`id_category`' : '') . '
INNER JOIN `' . _DB_PREFIX_ . 'category` c ON cp.`id_category` = c.`id_category`
INNER JOIN `' . _DB_PREFIX_ . 'product` p ON cp.`id_product` = p.`id_product`
' . Shop::addSqlAssociation('product', 'p', false) . '
WHERE c.`active` = 1
AND product_shop.`active` = 1
AND product_shop.`visibility` IN ("both", "search")
AND product_shop.indexed = 1
' . $sql_groups, true, false);
$eligible_products = array();
foreach ($results as $row) {
$eligible_products[] = $row['id_product'];
}
// $eligible_products2 = array();//half OR
foreach ($intersect_array as $query) {
$eligible_products2 = array(); // full AND
foreach ($db->executeS($query, true, false) as $row) {
$eligible_products2[] = $row['id_product'];
}
$eligible_products = array_unique(array_intersect($eligible_products, array_unique($eligible_products2)));
if (! count($eligible_products)) {
return $ajax ? array() : array(
'total' => 0,
'result' => array()
);
}
}
$product_pool = '';
foreach ($eligible_products as $id_product) {
if ($id_product) {
$product_pool .= (int) $id_product . ',';
}
}
if (empty($product_pool)) {
return $ajax ? array() : array(
'total' => 0,
'result' => array()
);
}
$product_pool = ((strpos($product_pool, ',') === false) ? (' = ' . (int) $product_pool . ' ') : (' IN (' . rtrim($product_pool, ',') . ') '));
if ($ajax) {
$sql = 'SELECT DISTINCT p.id_product, pl.name pname, cl.name cname,
cl.link_rewrite crewrite, pl.link_rewrite prewrite ' . $score . '
FROM ' . _DB_PREFIX_ . 'product p
INNER JOIN `' . _DB_PREFIX_ . 'product_lang` pl ON (
p.`id_product` = pl.`id_product`
AND pl.`id_lang` = ' . (int) $id_lang . Shop::addSqlRestrictionOnLang('pl') . '
)
' . Shop::addSqlAssociation('product', 'p') . '
INNER 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') . '
)
WHERE p.`id_product` ' . $product_pool . '
ORDER BY position DESC LIMIT 10';
return $db->executeS($sql, true, false);
}
if (strpos($order_by, '.') > 0) {
$order_by = explode('.', $order_by);
$order_by = pSQL($order_by[0]) . '.`' . pSQL($order_by[1]) . '`';
}
$alias = '';
if ($order_by == 'price') {
$alias = 'product_shop.';
} elseif (in_array($order_by, array(
'date_upd',
'date_add'
))) {
$alias = 'p.';
}
$sql = 'SELECT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity,
pl.`description_short`, pl.`available_now`, pl.`available_later`, pl.`link_rewrite`, pl.`name`,
image_shop.`id_image` id_image, il.`legend`, m.`name` manufacturer_name ' . $score . ',
DATEDIFF(
p.`date_add`,
DATE_SUB(
"' . date('Y-m-d') . ' 00:00:00",
INTERVAL ' . (Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20) . ' DAY
)
) > 0 new' . (Combination::isFeatureActive() ? ', product_attribute_shop.minimal_quantity AS product_attribute_minimal_quantity, IFNULL(product_attribute_shop.`id_product_attribute`,0) id_product_attribute' : '') . '
FROM ' . _DB_PREFIX_ . 'product p
' . Shop::addSqlAssociation('product', 'p') . '
INNER JOIN `' . _DB_PREFIX_ . 'product_lang` pl ON (
p.`id_product` = pl.`id_product`
AND pl.`id_lang` = ' . (int) $id_lang . Shop::addSqlRestrictionOnLang('pl') . '
)
' . (Combination::isFeatureActive() ? 'LEFT JOIN `' . _DB_PREFIX_ . 'product_attribute_shop` product_attribute_shop FORCE INDEX (id_product)
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_ . 'manufacturer` m FORCE INDEX (PRIMARY)
ON m.`id_manufacturer` = p.`id_manufacturer`
LEFT JOIN `' . _DB_PREFIX_ . 'image_shop` image_shop FORCE INDEX (id_product)
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 . ')
WHERE p.`id_product` ' . $product_pool . '
GROUP BY product_shop.id_product
' . ($order_by ? 'ORDER BY ' . $alias . $order_by : '') . ($order_way ? ' ' . $order_way : '') . '
LIMIT ' . (int) (($page_number - 1) * $page_size) . ',' . (int) $page_size;
$result = $db->executeS($sql, true, false);
$sql = 'SELECT COUNT(*)
FROM ' . _DB_PREFIX_ . 'product p
' . Shop::addSqlAssociation('product', 'p') . '
INNER 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 `' . _DB_PREFIX_ . 'manufacturer` m ON m.`id_manufacturer` = p.`id_manufacturer`
WHERE p.`id_product` ' . $product_pool;
$total = $db->getValue($sql, false);
if (! $result) {
$result_properties = false;
} else {
$result_properties = Product::getProductsProperties((int) $id_lang, $result);
}
return array(
'total' => $total,
'result' => $result_properties
);
}
}

Related

Prestashop 1.7.6 category update with simple query lang table

what's wrong with the code?
i have a custom module which is handling additional fields in category.
Get, and update data is working good, but not for another language.
Check this out:
public function hookCategoryAddition($params)
{
Db::getInstance()->update('category_lang', array('top_h1_desc' => pSQL(Tools::getValue('top_h1_desc'))), 'id_category = ' . $params['category']->id);
Db::getInstance()->update('category_lang', array('top_p_desc' => pSQL(Tools::getValue('top_p_desc'))), 'id_category = ' . $params['category']->id);
Db::getInstance()->update('category_lang', array('top_h1_desc' => pSQL(Tools::getValue('top_h1_desc_en'))), 'id_category = ' . $params['category']->id.' id_lang = 2');
Db::getInstance()->update('category_lang', array('top_p_desc' => pSQL(Tools::getValue('top_p_desc_en'))), 'id_category = ' . $params['category']->id.' id_lang = 2');
}
The first 2 lines are updating correctly, but others are not working. Can anyone give my a hint?
Checkout my complete code:
class displayBoCategoryTut extends Module
{
protected $_errors = array();
protected $_html = '';
public function __construct()
{
$this->name = 'displaybocategorytut';
$this->tab = 'front_office_features';
$this->version = '1.1';
$this->author = 'KS';
$this->need_instance = 0;
$this->bootstrap = true;
parent::__construct();
$this->displayName = $this->l('Dodatkowe pola w kategorii');
$this->description = $this->l('Pokazuje dodatkowe pola w kategorii');
}
public function install()
{
if (!parent::install() OR
!$this->alterTable() OR
!$this->registerHook('displayBackOfficeCategory') OR
!$this->registerHook('categoryAddition') OR
!$this->registerHook('categoryUpdate')
)
return false;
return true;
}
/*public function uninstall()
{
if (!parent::uninstall() OR
!$this->alterTable('remove'))
return false;
return true;
}
public function alterTable($method = 'add')
{
if($method == 'add')
$sql = 'ALTER TABLE ' . _DB_PREFIX_ . 'category_lang ADD `top_h1_desc` VARCHAR (512) NOT NULL';
$sql = 'ALTER TABLE ' . _DB_PREFIX_ . 'category_lang ADD `top_p_desc` TEXT NOT NULL';
else
$sql = 'ALTER TABLE ' . _DB_PREFIX_ . 'category_lang DROP COLUMN `top_h1_desc`';
$sql = 'ALTER TABLE ' . _DB_PREFIX_ . 'category_lang DROP COLUMN `top_p_desc`';
if(!Db::getInstance()->Execute($sql))
return false;
return true;
}*/
public function top_h1_desc($id_category)
{
return Db::getInstance()->getValue('SELECT top_h1_desc FROM '._DB_PREFIX_.'category_lang WHERE id_category = '. (int)$id_category);
}
public function top_h1_desc_en($id_category)
{
return Db::getInstance()->getValue('SELECT top_h1_desc FROM '._DB_PREFIX_.'category_lang WHERE id_category = '. (int)$id_category.' AND id_lang = 2');
}
public function top_p_desc($id_category)
{
return Db::getInstance()->getValue('SELECT top_p_desc FROM '._DB_PREFIX_.'category_lang WHERE id_category = '. (int)$id_category);
}
public function top_p_desc_en($id_category)
{
return Db::getInstance()->getValue('SELECT top_p_desc FROM '._DB_PREFIX_.'category_lang WHERE id_category = '. (int)$id_category.' AND id_lang = 2');
}
public function hookCategoryAddition($params)
{
Db::getInstance()->update('category_lang', array('top_h1_desc' => pSQL(Tools::getValue('top_h1_desc'))), 'id_category = ' . $params['category']->id);
Db::getInstance()->update('category_lang', array('top_p_desc' => pSQL(Tools::getValue('top_p_desc'))), 'id_category = ' . $params['category']->id);
Db::getInstance()->update('category_lang', array('top_h1_desc' => pSQL(Tools::getValue('top_h1_desc_en'))), 'id_category = ' . $params['category']->id.' id_lang = 2');
Db::getInstance()->update('category_lang', array('top_p_desc' => pSQL(Tools::getValue('top_p_desc_en'))), 'id_category = ' . $params['category']->id.' id_lang = 2');
}
public function hookCategoryUpdate($params)
{
$this->hookCategoryAddition($params);
}
public function hookDisplayBackOfficeCategory($params)
{
// we need an actual id, otherwise if we are just adding the category this field can be left empty
if(Tools::getValue('id_category'))
$top_h1_desc = $this->top_h1_desc(Tools::getValue('id_category'));
else $top_h1_desc = '';
if(Tools::getValue('id_category'))
$top_p_desc = $this->top_p_desc(Tools::getValue('id_category'));
else $top_p_desc = '';
if(Tools::getValue('id_category'))
$top_h1_desc_en = $this->top_h1_desc_en(Tools::getValue('id_category'));
else $top_h1_desc_en = '';
if(Tools::getValue('id_category'))
$top_p_desc_en = $this->top_p_desc_en(Tools::getValue('id_category'));
else $top_p_desc_en = '';
$this->context->smarty->assign(array(
'top_h1_desc'=> $top_h1_desc,
'top_p_desc'=> $top_p_desc,
'top_h1_desc_en'=> $top_h1_desc_en,
'top_p_desc_en'=> $top_p_desc_en
));
return $this->display(__FILE__, 'backoffice.tpl');
}
}
The last part is the WHERE part.
By simply add an AND to the last parameter of the method, it should work.
This should be fine:
public function hookCategoryAddition($params)
{
Db::getInstance()->update('category_lang', array('top_h1_desc' => pSQL(Tools::getValue('top_h1_desc'))), 'id_category = ' . $params['category']->id);
Db::getInstance()->update('category_lang', array('top_p_desc' => pSQL(Tools::getValue('top_p_desc'))), 'id_category = ' . $params['category']->id);
Db::getInstance()->update('category_lang', array('top_h1_desc' => pSQL(Tools::getValue('top_h1_desc_en'))), 'id_category = ' . $params['category']->id.' AND id_lang = 2');
Db::getInstance()->update('category_lang', array('top_p_desc' => pSQL(Tools::getValue('top_p_desc_en'))), 'id_category = ' . $params['category']->id.' AND id_lang = 2');
}

Create product combinations in prestashop 1.7 programmatically duplicate id issue

I am trying to add products with combinations with php code. What when running the script duplicate primary ID error occured in ps_product_attribute_combination table. I am using multiple attributes from the color and size group. This code is placed after $product->save() call.
$combinationAttributes[] = array(1,2);
$combinationAttributes[] = array(5,6,7);
if(!$product->productAttributeExists($combinationAttributes,false, null, true, true)){
$price = $price;
$weight = '';
$ecotax = '';
$unit_price_impact="";
$quantity = 100;
$reference = $reference;
$supplier_reference = "";
$ean13 = "";
$default = '0';
$idProductAttribute = $product->addProductAttribute((float)$price, (float)$weight, $unit_price_impact, (float)$ecotax, (int)$quantity, "", strval($reference), strval($supplier_reference), strval($ean13), $default, NULL, NULL,'','','','');
$product->addAttributeCombinaison($idProductAttribute, $combinationAttributes);
Inserting product programmatically can be a pain. I have written my own code using a part of Prestashop default values and a part inserting values using sql.
Hope this code helps you in your progress. You can add this file to your adminfolder and run it.
Standalone PHP file
<?php
if ( !defined( '_PS_ADMIN_DIR_' ) ) {
define( '_PS_ADMIN_DIR_', getcwd() );
}
include( _PS_ADMIN_DIR_ . '/../config/config.inc.php' );
addProduct(
'1234567891234', // Product EAN13
'Stackoverflow', // Product reference
'Crezzur', // Product name
5, // Product quantity
'Code by Crezzur (https://crezzur.com)', // Product description
array( // Product features (array)
array( "name" => "Color", "value" => "Red" ),
array( "name" => "Height", "value" => "200cm" ),
),
'999.95', // Product price
'https://i.imgur.com/yOp1xt3.jpg', // Product image
1, // Product default category
array(1, 5) // All categorys for product (array)
);
function addProduct( $ean13, $ref, $name, $qty, $text, $features, $price, $imgUrl, $catDef, $catAll ) {
$product = new Product(); // Create new product in prestashop
$product->ean13 = $ean13;
$product->reference = $ref;
$product->name = createMultiLangField( $name );
$product->description = htmlspecialchars($text);
//$product->link_rewrite = createMultiLangField($linkrewrite);
$product->id_category_default = $catDef;
$product->redirect_type = '301';
$product->price = $price;
$product->quantity = $qty;
$product->minimal_quantity = 1;
$product->show_price = 1;
$product->on_sale = 0;
$product->online_only = 0;
$product->meta_description = '';
$product->add();
$product->addToCategories($catAll);
// Insert "feature name" and "feature value"
if ( is_array( $features ) ) {
foreach ( $features as $feature ) {
$attributeName = $feature[ 'name' ];
$attributeValue = $feature[ 'value' ];
// 1. Check if 'feature name' exist already in database
$FeatureNameId = Db::getInstance()->getValue( 'SELECT id_feature FROM ' . _DB_PREFIX_ . 'feature_lang WHERE name = "' . pSQL( $attributeName ) . '"' );
// If 'feature name' does not exist, insert new.
if ( empty( $getFeatureName ) ) {
Db::getInstance()->execute( 'INSERT INTO `' . _DB_PREFIX_ . 'feature` (`id_feature`,`position`) VALUES (0, 0)' );
$FeatureNameId = Db::getInstance()->Insert_ID(); // Get id of "feature name" for insert in product
Db::getInstance()->execute( 'INSERT INTO `' . _DB_PREFIX_ . 'feature_shop` (`id_feature`,`id_shop`) VALUES (' . $FeatureNameId . ', 1)' );
Db::getInstance()->execute( 'INSERT INTO `' . _DB_PREFIX_ . 'feature_lang` (`id_feature`,`id_lang`, `name`) VALUES (' . $FeatureNameId . ', ' . Context::getContext()->language->id . ', "' . pSQL( $attributeName ) . '")' );
}
// 1. Check if 'feature value name' exist already in database
$FeatureValueId = Db::getInstance()->getValue( 'SELECT id_feature_value FROM webshop_feature_value WHERE id_feature_value IN (SELECT id_feature_value FROM webshop_feature_value_lang WHERE value = "' . pSQL( $attributeValue ) . '") AND id_feature = ' . $FeatureNameId );
// If 'feature value name' does not exist, insert new.
if ( empty( $FeatureValueId ) ) {
Db::getInstance()->execute( 'INSERT INTO `' . _DB_PREFIX_ . 'feature_value` (`id_feature_value`,`id_feature`,`custom`) VALUES (0, ' . $FeatureNameId . ', 0)' );
$FeatureValueId = Db::getInstance()->Insert_ID();
Db::getInstance()->execute( 'INSERT INTO `' . _DB_PREFIX_ . 'feature_value_lang` (`id_feature_value`,`id_lang`,`value`) VALUES (' . $FeatureValueId . ', ' . Context::getContext()->language->id . ', "' . pSQL( $attributeValue ) . '")' );
}
Db::getInstance()->execute( 'INSERT INTO `' . _DB_PREFIX_ . 'feature_product` (`id_feature`, `id_product`, `id_feature_value`) VALUES (' . $FeatureNameId . ', ' . $product->id . ', ' . $FeatureValueId . ')' );
}
}
$shops = Shop::getShops( true, null, true );
$image = new Image();
$image->id_product = $product->id;
$image->position = Image::getHighestPosition( $product->id ) + 1;
$image->cover = true;
if ( ( $image->validateFields( false, true ) ) === true && ( $image->validateFieldsLang( false, true ) ) === true && $image->add() ) {
$image->associateTo( $shops );
if ( !uploadImage( $product->id, $image->id, $imgUrl ) ) {
$image->delete();
}
}
echo 'Product added successfully (ID: ' . $product->id . ')';
}
function uploadImage( $id_entity, $id_image = null, $imgUrl ) {
$tmpfile = tempnam( _PS_TMP_IMG_DIR_, 'ps_import' );
$watermark_types = explode( ',', Configuration::get( 'WATERMARK_TYPES' ) );
$image_obj = new Image( $id_image );
$path = $image_obj->getPathForCreation();
$imgUrl = str_replace( ' ', '%20', trim( $imgUrl ) );
// Evaluate the memory required to resize the image: if it's too much, you can't resize it.
if ( !ImageManager::checkImageMemoryLimit( $imgUrl ) )
return false;
if ( #copy( $imgUrl, $tmpfile ) ) {
ImageManager::resize( $tmpfile, $path . '.jpg' );
$images_types = ImageType::getImagesTypes( 'products' );
foreach ( $images_types as $image_type ) {
ImageManager::resize( $tmpfile, $path . '-' . stripslashes( $image_type[ 'name' ] ) . '.jpg', $image_type[ 'width' ], $image_type[ 'height' ] );
if ( in_array( $image_type[ 'id_image_type' ], $watermark_types ) ) {
Hook::exec( 'actionWatermark', array( 'id_image' => $id_image, 'id_product' => $id_entity ) );
}
}
} else {
unlink( $tmpfile );
return false;
}
unlink( $tmpfile );
return true;
}
function createMultiLangField( $field ) {
$res = array();
foreach ( Language::getIDs( false ) as $id_lang ) {
$res[ $id_lang ] = $field;
}
return $res;
}
There were some mistakes in code section part product feature insertion Crezzur suggested like checking if getfeaturename variable exists must be featurenameid and query for Check if 'feature value name' exist already in database is little incorrect.
This is my fix
// Insert "feature name" and "feature value"
if (is_array($features)) {
foreach ($features as $feature) {
$attributeName = $feature['name'];
$attributeValue = $feature['value'];
// 1. Check if 'feature name' exist already in database
$FeatureNameId = Db::getInstance()->getValue('SELECT id_feature FROM ' . _DB_PREFIX_ . 'feature_lang WHERE name = "' . pSQL($attributeName) . '"');
// If 'feature name' does not exist, insert new.
if (empty($FeatureNameId)) {
Db::getInstance()->execute('INSERT INTO `' . _DB_PREFIX_ . 'feature` (`id_feature`,`position`) VALUES (0, 0)');
$FeatureNameId = Db::getInstance()->Insert_ID(); // Get id of "feature name" for insert in product
Db::getInstance()->execute('INSERT INTO `' . _DB_PREFIX_ . 'feature_shop` (`id_feature`,`id_shop`) VALUES (' . $FeatureNameId . ', 1)');
Db::getInstance()->execute('INSERT INTO `' . _DB_PREFIX_ . 'feature_lang` (`id_feature`,`id_lang`, `name`) VALUES (' . $FeatureNameId . ', ' . Context::getContext()->language->id . ', "' . pSQL($attributeName) . '")');
}
// 1. Check if 'feature value name' exist already in database
$FeatureValueId = Db::getInstance()->getValue('SELECT id_feature_value FROM ' . _DB_PREFIX_ . 'feature_value WHERE id_feature_value IN (SELECT id_feature_value FROM ' . _DB_PREFIX_ . 'feature_value_lang WHERE value = "' . pSQL($attributeValue) . '") AND id_feature = ' . $FeatureNameId);
//var_dump($FeatureValueId);
// If 'feature value name' does not exist, insert new.
if (empty($FeatureValueId)) {
Db::getInstance()->execute('INSERT INTO `' . _DB_PREFIX_ . 'feature_value` (`id_feature_value`,`id_feature`,`custom`) VALUES (0, ' . $FeatureNameId . ', 0)');
$FeatureValueId = Db::getInstance()->Insert_ID();
Db::getInstance()->execute('INSERT INTO `' . _DB_PREFIX_ . 'feature_value_lang` (`id_feature_value`,`id_lang`,`value`) VALUES (' . $FeatureValueId . ', ' . Context::getContext()->language->id . ', "' . pSQL($attributeValue) . '")');
}
Db::getInstance()->execute('INSERT INTO `' . _DB_PREFIX_ . 'feature_product` (`id_feature`, `id_product`, `id_feature_value`) VALUES (' . $FeatureNameId . ', ' . $product->id . ', ' . $FeatureValueId . ')');
}
}
The other part of the code provided by Crezzur is working and tested 10x Crezzur

Open Cart SEO URL for category/manufacturer

OC 1.5.6
I've installed a module to filter products in categories based on manufacturer.
I'm able to reach every "search result page" at an url like:
example.com/index.php?route=product/category&path=X&manufacturer=Y
I'd like to create a SEO url like:
example.com/alias-for-category/alias-for-manufacturer
(ex. /bikes/honda or /cars/bmw)
but I can't figure out how to do it.
I've tried for testing and simplifying to convert just a single url:
product/category&path=1&manufacturer=1
so I added to url_alias a record with this query and keyword
cat1-man1
then I modified catalog/common/seo_url.php
function Index
if (isset($this->request->get['product_id'])) {
$this->request->get['route'] = 'product/product';
} elseif (isset($this->request->get['path'])) {
$this->request->get['route'] = 'product/category';
} elseif (isset($this->request->get['manufacturer_id'])) {
$this->request->get['route'] = 'product/manufacturer/info';
} elseif (isset($this->request->get['information_id'])) {
$this->request->get['route'] = 'information/information';
}
//ADDED BELOW CODE TO ROUTE ALL URL
else {
$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "url_alias WHERE keyword = '" . $this->db->escape($this->request->get['_route_']) . "'");
if ($query->num_rows) {
$this->request->get['route'] = $query->row['query'];
}
}
and function rewrite
if (($data['route'] == 'product/product' && $key == 'product_id') || (($data['route'] == 'product/manufacturer/info' || $data['route'] == 'product/product') && $key == 'manufacturer_id') || ($data['route'] == 'information/information' && $key == 'information_id')) {
$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "url_alias WHERE `query` = '" . $this->db->escape($key . '=' . (int)$value) . "'");
if ($query->num_rows) {
$url .= '/' . $query->row['keyword'];
unset($data[$key]);
}
} elseif ($key == 'path') {
$categories = explode('_', $value);
foreach ($categories as $category) {
$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "url_alias WHERE `query` = 'category_id=" . (int)$category . "'");
if ($query->num_rows) {
$url .= '/' . $query->row['keyword'];
}
}
unset($data[$key]);
}
//ADDED CODE BELOW TO CONVERT ALL URL
else {
$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "url_alias WHERE `query` = '" . $this->db->escape($data['route']) . "'");
if ($query->num_rows) {
$url .= '/' . $query->row['keyword'];
unset($data[$key]);
}
}
but also this simplified version doesn't work at all, page not found is shown.
What I'm doing wrong? Any tip will be really appreciated
First of all the custom module I've installed expects the parameter for manufacturer as "manufacturer" instead of "manufacturer_id" so a converted URL like :
example.com/index.php?route=product/category&path=X&manufacturer_id=Y
isn't handled correctly by the module.
So the answer to my question is : OC does already convert alias-cat/alias-manufacturer to a correct internal URL
On the other hand OC does not convert URL of the type
example.com/index.php?route=product/category&path=X&manufacturer_id=Y
into SEO friendly URL like:
example.com/alias-for-category/alias-for-manufacturer
in the menus or links, to do this, modify catalog/common/seo_url.php like this:
public function rewrite($link) {
$url_info = parse_url(str_replace('&', '&', $link));
$url = '';
$data = array();
parse_str($url_info['query'], $data);
foreach ($data as $key => $value) {
if (isset($data['route'])) {
if (($data['route'] == 'product/product' && $key == 'product_id') || (($data['route'] == 'product/manufacturer/info' || $data['route'] == 'product/product') && $key == 'manufacturer_id') || ($data['route'] == 'information/information' && $key == 'information_id')) {
$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "url_alias WHERE `query` = '" . $this->db->escape($key . '=' . (int)$value) . "'");
if ($query->num_rows) {
$url .= '/' . $query->row['keyword'];
unset($data[$key]);
}
} elseif ($key == 'path') {
$categories = explode('_', $value);
foreach ($categories as $category) {
$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "url_alias WHERE `query` = 'category_id=" . (int)$category . "'");
if ($query->num_rows) {
$url .= '/' . $query->row['keyword'];
}
}
unset($data[$key]);
}
// ADD THIS CODE
elseif ($key == 'manufacturer_id') {
$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "url_alias WHERE `query` = 'manufacturer_id=" . (int)$value . "'");
if ($query->num_rows) {
$url .= '/' . $query->row['keyword'];
}
unset($data[$key]);
}
// END ADDED CODE----------------
else {
.....

Opencart sort by manufacturer in Category pages

Ok, I would like to add one more sort variable on category pages, that is to sort by Manufacturer.
Running on 1.5.3.1 and have tried this:
1. catalog/controller/product/category.php
added the following:
$this->data['sorts'][] = array(
'text' => $this->language->get('text_manufacturer_asc'),
'value' => 'manufacturer-ASC',
'href' => $this->url->link('product/category', 'path=' . $this->request->get['path'] . '&sort=manufacturer&order=ASC' . $url)
);
$this->data['sorts'][] = array(
'text' => $this->language->get('text_manufacturer_desc'),
'value' => 'manufacturer-DESC',
'href' => $this->url->link('product/category', 'path=' . $this->request->get['path'] . '&sort=manufacturer&order=DESC' . $url)
);
catalog/language/*/product/category.php
added:
$_['text_manufacturer_asc'] = '▲ -Proizvođaču- ▲';
$_['text_manufacturer_desc'] = '▼ -Proizvođaču- ▼';
catalog/model/catalog/product.php
before: 'p.date_added' I inserted a line:
'manufacturer'
and few lines below I changed the block with the following one:
if (isset($data['sort']) && in_array($data['sort'], $sort_data)) {
if ($data['sort'] == 'pd.name' || $data['sort'] == 'p.model') {
$sql .= " ORDER BY LCASE(" . $data['sort'] . ")";
} elseif ($data['sort'] == 'p.price') {
$sql .= " ORDER BY (CASE WHEN special IS NOT NULL THEN special WHEN discount IS NOT NULL THEN discount ELSE p.price END)";
} elseif ($data['sort'] == 'manufacturer') {
$sql .= " SELECT * FROM". DB_PREFIX . "product p ORDER BY manufacturer";
} else {
$sql .= " ORDER BY " . $data['sort'];
}
} else {
$sql .= " ORDER BY p.sort_order";
}
But it is not working.
Error says:
PHP Notice: Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT * FROMproduct p ORDER BY manufacturer ASC,...
and another one I have found:
PHP Notice: Error: Unknown column 'special' in 'order clause'<br />Error No: 1054<br />SELECT p.product_id, (SELECT AVG(rating) AS total FROM review r1 WHERE r1.product_id = p.product_id AND r1.status = '1' GROUP BY r1.product_id)...
Can anybody help?
You are almost there but You will have to modify it a little bit more.
First, You really do not want to order by manufacturer ID stored in product.manufacturer_id but by manufacturer name. In this case we need to modify the query in catalog\model\catalog\product.php model in getProducts method - find this line:
$sql .= " LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id) LEFT JOIN " . DB_PREFIX . "product_to_store p2s ON (p.product_id = p2s.product_id) WHERE pd.language_id = '" . (int)$this->config->get('config_language_id') . "' AND p.status = '1' AND p.date_available <= NOW() AND p2s.store_id = '" . (int)$this->config->get('config_store_id') . "'";
(should be line 89 in OC 1.5.5.1) and before it add:
$sql .= " LEFT JOIN " . DB_PREFIX . "manufacturer m ON p.manufacturer_id = m.manufacturer_id";
Also You'll need to allow manufacturer as a sorting option:
$sort_data = array(
'pd.name',
'p.model',
'p.quantity',
'p.price',
'rating',
'p.sort_order',
'p.date_added',
'manufacturer', // <== this is added
);
Now in the sorting section add sorting by manufacturer name:
if (isset($data['sort']) && in_array($data['sort'], $sort_data)) {
if ($data['sort'] == 'pd.name' || $data['sort'] == 'p.model') {
$sql .= " ORDER BY LCASE(" . $data['sort'] . ")";
} elseif ($data['sort'] == 'p.price') {
$sql .= " ORDER BY (CASE WHEN special IS NOT NULL THEN special WHEN discount IS NOT NULL THEN discount ELSE p.price END)";
} elseif ($data['sort'] == 'manufacturer') { // <== this is added
$sql .= " ORDER BY m.name"; // <== this is added
} else {
$sql .= " ORDER BY " . $data['sort'];
}
} else {
$sql .= " ORDER BY p.sort_order";
}
And that's it.

Yii How to optimize a sum() query

I want to skip the foreach loop;
How can I get the sum by using a yii query?
$sql = 'select size_kb from comp_arch_stats where company_id = ' . ($model->company_id) . ' and arch_month = ' . $month . ' and arch_year = ' . $year . ';';
$val = Yii::app()->db->createCommand($sql)->queryAll();
$sum = 0;
foreach ($val AS $result) {
$sum += $result['size_kb'];
}
"'select sum(size_kb) as size_kb from comp_arch_stats where company_id = ' . ($model->company_id)"
Try this
$criteria=new CDbCriteria;
$criteria->select = 'sum(size_kb) AS KbCount';
$criteria->condition ="company_id = :company_id AND arch_month =:arch_month AND arch_year=:arch_year "
$criteria->params = array (
':company_id '=> $model->company_id,
':arch_month' => $month,
':arch_year' => $year,
);
comp_arch_stats::model()->findAll($criteria);