Special characters in a search field

Hello everyone,

I have a small problem in my search field when the user searches for a word with an apostrophe " ’ ": which is common in French, since I use h(), when I redisplay the user’s query on the search page, it displays in raw ' and it searches the database with ' rather than ’

How can I handle this? thx !

If they search for “Quebec”, should it match instances of “Québec” in the database? What about vice versa?

Not clear on why you pass the input through h() when doing the database search, instead of just when doing the user output.

If I search for something like " l’armée ":

The query will be:

Posts.name LIKE ‘%army%’
OR Posts.description LIKE ‘%the army%’

and find nothing.

But the user is looking for: " armée " then the request is

Posts.name LIKE ‘%army%’
OR Posts.description LIKE ‘%army%’

And I have several results.

I suppose one solution is to remove all the little words with apostrophes " ’ " to send a simpler request but I would still like to find something simpler?

In my view, I displayed in the value of the form like this:

<?php 
echo $this->Form->control('q',[
'class'=>'form-control',
'value'=> h($this->request->getQuery('q')),
"placeholder"=>"Search ...",
'label'=>false,
]);

but i removed the h() function

Sorry, still confused. If their search term is “armée”, how does that get translated into “army” in your query? And what if they search for “armee” with no accent?

Sorry ! I used Google Translate and it translated what’s not

I found my problem. I wasn’t using bind to do my search (which is not good). So in the first version of my code I was using h() on my query.

It was useless and it was causing me problems with special characters.

I used bind and removed h(). Everything seems to be working correctly.

<?php

$GetSearch = $this->request->getQuery('q');
if ($GetSearch != null){	

	$currentwords = ['au','aux','et','en','du','à','sur','dans','l\'',''];

	$SearchArray = explode(" ", strtolower(trim($GetSearch)));
	foreach ($SearchArray as $k => $word) {
		$SearchArray[$k] = $word = str_replace($currentwords,'',$word);

		if (in_array($word, $currentwords)) {
			unset($SearchArray[$k]);
		}
	}

	$SearchArray = array_filter($SearchArray, fn($value) => !is_null($value) && $value !== '');
	foreach ($SearchArray as $k => $v)
	{
		$conditions[] = [
			'OR' => [
				["Posts.name LIKE :querysearch" ],
				["Posts.description LIKE :querysearch" ],
			],
		];
	
	}

	$videos->bind(':querysearch', "%".$v."%", 'string');

}

The only problem that I have elsewhere in my code is that I can’t pass an array here to bind.

Are you sure you need to bind? Seems that eliminating h() should be sufficient.

The ORM should take care of ensuring that all the parameters are correctly quoted to avoid injection attacks.

That’s what I did at the beginning but the docs indicate that you have to bind everywhere to protect yourself… No?

This document? The references to bind in there all appear to be very specifically about scenarios where you’re writing “raw SQL snippets” and the like. What you’ve got here are standard where clauses with keys and values, and to my understanding those values are all going to be properly escaped and quoted by the ORM. If you are using ["Posts.name LIKE '%$v%'"], that’s a different story, but by separating the value out, the ORM has got your back.

1 Like

If I have several conditions to pass to my find query from a search form including categories that are in an array, what is the best way to do it?

$conditions[] = ['Videos.category_id IN'=>$cat];

That should work fine, yes.