Jump to content

[SOLVED] Search for Tags vs. Search via Search input box


sakiri

Recommended Posts

Hi everybody,

 

I hope I did not post this in the wrong section - if I did I apologize and ask for moving this topic to its correct place.

 

Now, what I would like to ask:

 

The "normal" Search via the search box at the top of pages returns good results when only the beginning of a product name etc. is given - which is perfectly ok and works absolutely fine.

 

But for filtering (searching) products by their tags I would want Presta to perform an exact search instead of returning products as well which have tags that are parts of other tags.

 

(Example: "in" is part of "rain" which again is part of "train" which is included in "trainer", so selecting the tag "in" would return all products tagged "rain", "train" and "trainer". Stupid example I know, but it shows the dilemma...)

 

Could somebody please give me a hint where and how to alter the coding to perform an exact search for tags?

 

Thanks!

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

Sakiri,

Would you like to have the search co-exist NEXT TO each other (use the same box for tags only AND for general search like it is now) or cut the whole current search method and CHANGE TO this tag based system?

 

If next to each other, how would you make the distinction between general search/tag search?(check box or so??)

 

Just some questions, to find/set the 'borders' of the problem.

pascal

Link to comment
Share on other sites

Let me see whether I understood your question correctly:

 

I have a search input box in the header part of my pages. I want to keep that and the way it works just now (finding products with full or parts of description, item#, name etc.)

In the left column I have a "Tag box" (tag cloud) showing all existing/available tags. When clicking on one of these tags I would want to have Presta return those products ONLY which are tagged with exactly the same tag as which was clicked on. To return to the example given in my first post: when clicking on the tag "rain" I would wish to see only the one product come up in the result page which has been tagged "rain" and not those 2 other products with tags "train" and "trainer".

And I would not want to search for tags via the search input box.

 

So, yes, in some way I want those two search methods to co-exist, if this is what you meant.

As far as I understand, the program code IS different for "normal search" and "tag search", but I cannot figure out where to change the code to achieve exact search results for tags.

 

Forgot to say: I'm on PS 1.5.5 with native module blocktags 1.1

the development environment of my shop is http://zumtestvon155hierlang.olde-worlde-embroidery.com

 

Thank you for looking into the issue.

Sabine-Kirsten

Link to comment
Share on other sites

Hi ramtin,

thank you for your attempt to help me out!

Your override in fact does improve the search via the search input box (which was ok for me the way it worked), but does not solve my actual problem with the search / filtering for tags as described above.

So ... still looking for help towards a solution.

Link to comment
Share on other sites

Hi sakiri,

 

Try this:

edit  file: classes/Search.php (make a backup first! Just in case...)

 

find the function:

public static function searchTag($id_lang, $tag, $count = false, $pageNumber = 0, $pageSize = 10, $orderBy = false, $orderWay = false, $useCookie = true, Context $context = null)
 
there you see twice this line inside an SQL query: (the first one has an ending ; at the end. Keep it there)
AND t.`name` LIKE \'%'.pSQL($tag).'%\''
 
change into:
AND trim(t.`name`) = trim(\''.$tag.'\')
 

That should do the trick. It now checks the exact tag (trimmed spaces before/after) so, "ipo" != "ipod" != "ipod touch"

 

Hope this helps,

pascal

Link to comment
Share on other sites

To try out your solution I checked the search.php in classes/ : the line AND t.`name` LIKE \'%'.pSQL($tag).'%\'' appears only once, in line 662; when I change this one occurance, I of course get a blank page as search result.

 

Just to make sure we are talking about the same piece of coding, this is the complete searchTag function (original, unchanged 1.5.5 version):

	public static function searchTag($id_lang, $tag, $count = false, $pageNumber = 0, $pageSize = 10, $orderBy = false, $orderWay = false,
		$useCookie = true, Context $context = null)
	{
		if (!$context)
			$context = Context::getContext();

		// Only use cookie if id_customer is not present
		if ($useCookie)
			$id_customer = (int)$context->customer->id;
		else
			$id_customer = 0;

		if (!is_numeric($pageNumber) || !is_numeric($pageSize) || !Validate::isBool($count) || !Validate::isValidSearch($tag)
		|| $orderBy && !$orderWay || ($orderBy && !Validate::isOrderBy($orderBy)) || ($orderWay && !Validate::isOrderBy($orderWay)))
			return false;

		if ($pageNumber < 1) $pageNumber = 1;
		if ($pageSize < 1) $pageSize = 10;

		$id = Context::getContext()->shop->id;
		$id_shop = $id ? $id : Configuration::get('PS_SHOP_DEFAULT');
		if ($count)
		{
			$sql = 'SELECT COUNT(DISTINCT pt.`id_product`) nb
					FROM `'._DB_PREFIX_.'product` p
					'.Shop::addSqlAssociation('product', 'p').'
					LEFT JOIN `'._DB_PREFIX_.'product_tag` pt ON (p.`id_product` = pt.`id_product`)
					LEFT JOIN `'._DB_PREFIX_.'tag` t ON (pt.`id_tag` = t.`id_tag` AND t.`id_lang` = '.(int)$id_lang.')
					LEFT JOIN `'._DB_PREFIX_.'category_product` cp ON (cp.`id_product` = p.`id_product`)
					LEFT JOIN `'._DB_PREFIX_.'category_shop` cs ON (cp.`id_category` = cs.`id_category` AND cs.`id_shop` = '.(int)$id_shop.')
					LEFT JOIN `'._DB_PREFIX_.'category_group` cg ON (cg.`id_category` = cp.`id_category`)
					WHERE product_shop.`active` = 1
						AND cs.`id_shop` = '.(int)Context::getContext()->shop->id.'
						AND cg.`id_group` '.(!$id_customer ?  '= '.(int)Configuration::get('PS_UNIDENTIFIED_GROUP') : 'IN (
							SELECT id_group FROM '._DB_PREFIX_.'customer_group
							WHERE id_customer = '.(int)$id_customer.')').'
						AND t.`name` LIKE \'%'.pSQL($tag).'%\'';
			return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
		}

		$sql = 'SELECT DISTINCT p.*, product_shop.*, stock.out_of_stock, IFNULL(stock.quantity, 0) as quantity, pl.`description_short`, pl.`link_rewrite`, pl.`name`,
					MAX(image_shop.`id_image`) id_image, il.`legend`, m.`name` manufacturer_name, 1 position,
					DATEDIFF(
						p.`date_add`,
						DATE_SUB(
							NOW(),
							INTERVAL '.(Validate::isUnsignedInt(Configuration::get('PS_NB_DAYS_NEW_PRODUCT')) ? Configuration::get('PS_NB_DAYS_NEW_PRODUCT') : 20).' DAY
						)
					) > 0 new
				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', false).'
				LEFT JOIN `'._DB_PREFIX_.'image` i ON (i.`id_product` = p.`id_product`)'.
				Shop::addSqlAssociation('image', 'i', false, 'image_shop.cover=1').'		
				LEFT JOIN `'._DB_PREFIX_.'image_lang` il ON (i.`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`)
				LEFT JOIN `'._DB_PREFIX_.'product_tag` pt ON (p.`id_product` = pt.`id_product`)
				LEFT JOIN `'._DB_PREFIX_.'tag` t ON (pt.`id_tag` = t.`id_tag` AND t.`id_lang` = '.(int)$id_lang.')
				LEFT JOIN `'._DB_PREFIX_.'category_product` cp ON (cp.`id_product` = p.`id_product`)
				LEFT JOIN `'._DB_PREFIX_.'category_group` cg ON (cg.`id_category` = cp.`id_category`)
				LEFT JOIN `'._DB_PREFIX_.'category_shop` cs ON (cg.`id_category` = cs.`id_category` AND cs.`id_shop` = '.(int)$id_shop.')
				'.Product::sqlStock('p', 0).'
				WHERE product_shop.`active` = 1
					AND cs.`id_shop` = '.(int)Context::getContext()->shop->id.'
					AND cg.`id_group` '.(!$id_customer ?  '= '.(int)Configuration::get('PS_UNIDENTIFIED_GROUP') : 'IN (
						SELECT id_group FROM '._DB_PREFIX_.'customer_group
						WHERE id_customer = '.(int)$id_customer.')').'
					AND t.`name` LIKE \'%'.pSQL($tag).'%\'
					GROUP BY product_shop.id_product
				ORDER BY position DESC'.($orderBy ? ', '.$orderBy : '').($orderWay ? ' '.$orderWay : '').'
				LIMIT '.(int)(($pageNumber - 1) * $pageSize).','.(int)$pageSize;
		if (!$result = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql))
			return false;

		return Product::getProductsProperties((int)$id_lang, $result);
	}
Link to comment
Share on other sites

Hi sakiri,

If you look carefully, there are 2 lines with the t.`name` LIKE:

line 662 and 696.

 

Line 662, change into:

AND trim(t.`name`) = trim(\''.$tag.'\')';     // <-- don't forget ';
 
line 696, change into:
AND trim(t.`name`) = trim(\''.$tag.'\')
 
 
That should do the trick...
pascal

 

EDIT: Thanks Sakiri for mentioning the ' just before the ; giving ->  ';

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

Thank you very, very much! It works now! :) Together with ramtin's override I now have some super-duper search options to offer to my future customers!

 

I must have been blind as a bat not to have found the second line...

 

Hint for everyone wishing to repeat the correction: don't only leave the finishing semicolon, but also the last apostrophe (next to the semicolon) when substituting the string in the first occurence:

new line 662:

     AND trim(t.`name`) = trim(\''.$tag.'\')';

new line 696:

     AND trim(t.`name`) = trim(\''.$tag.'\')

 

Thank you again, Pascal! I'm really happy with the solution! (Maybe you could help me with my other problem posted in this very section today too?)

Link to comment
Share on other sites

Hint for everyone wishing to repeat the correction: don't only leave the finishing semicolon, but also the last apostrophe (next to the semicolon) when substituting the string in the first occurence:

new line 662:

     AND trim(t.`name`) = trim(\''.$tag.'\')';

 

 

Thanks Sakiri, you're right about the last '

pascal

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...