Codeigniter LIKE with wildcard(%) - mysql

I have simple database query in codeigniter, however I cannot get search to work with wildcard. This is my code:
$this->db->like('film.title',"%$query%");
$this->db->escape_like_str($query);
$res = $this->db->get('film');
If I remove wildcard(%) then search works fine. Also $query is just string with user input. Any help is appreciated.

$this->db->like() automatically adds the %s and escapes the string. So all you need is
$this->db->like('title', $query);
$res = $this->db->get('film');
See the CI documentation for reference: CI 2, CI 3, CI 4

$this->db->like('title', 'match', 'before');
// Produces: WHERE title LIKE '%match'
$this->db->like('title', 'match', 'after');
// Produces: WHERE title LIKE 'match%'
$this->db->like('title', 'match', 'both');
// Produces: WHERE title LIKE '%match%'

For Full like you can user :
$this->db->like('title',$query);
For %$query you can use
$this->db->like('title', $query, 'before');
and for $query% you can use
$this->db->like('title', $query, 'after');

$this->db->like()
This method enables you to generate LIKE clauses, useful for doing searches.
$this->db->like('title', 'match');
Produces: WHERE title LIKE '%match%'
If you want to control where the wildcard (%) is placed, you can use an optional third argument. Your options are ‘before’, ‘after’, ‘none’ and ‘both’ (which is the default).
$this->db->like('title', 'match', 'before');
Produces: WHERE title LIKE '%match'
$this->db->like('title', 'match', 'after');
Produces: WHERE title LIKE 'match%'
$this->db->like('title', 'match', 'none');
Produces: WHERE title LIKE 'match'
$this->db->like('title', 'match', 'both');
Produces: WHERE title LIKE '%match%'

If you do not want to use the wildcard (%) you can pass to the optional third argument the option 'none'.
$this->db->like('title', 'match', 'none');
// Produces: WHERE title LIKE 'match'

I'm using
$this->db->query("SELECT * FROM film WHERE film.title LIKE '%$query%'"); for such purposes

Searching multiple fields at once can be done like so...
function search($search)
{
$sql = "SELECT * FROM some_table
WHERE UPPER(a_name) LIKE ?
OR
UPPER(a_full_name) LIKE ?
OR
UPPER(a_city) LIKE ?
OR
UPPER(a_code) LIKE ?
";
$arr = array_map(array($this,"wrapLIKE"),array($search, $search, $search, $search));
$r = $this->db->query($sql, $arr);
return $r;
}
function wrapLIKE($string)
{
return strtoupper("%$string%");
}

Related

Search multiple words separated by space in laravel 6 doesn't work

I've read several similar posts and I tried them, but still it doesn't work for my site.
When I search a word "think" the search result shows "I think this is it".
However, when I search "I think" the result is "0 match found".
So to achieve multiple words search, I did below:
Controller.php
$keyword = "I think"
$words = explode(' ', $keyword);
$data = Post::where(function ($query) use ($words)
{
foreach($words as $word){
$query->where('example', 'LIKE', '%' . $word . '%');
}
})->get();
However, result is same. "think" shows results. "I think" doesn't hit any results.
also debugged with dd($data)
// $keyword = "think"
"select * from `posts` where (`example` LIKE ?)"
// $keyword = "I think"
"select * from `posts` where (`example` LIKE ? and `example` LIKE ?)"
So what would be wrong? Thank you.
[Additonal info (Edited)]
$bindings = $query->getBindings();
dd($bindings);
// array:2 [▼
0 => "%I%"
1 => "%think%"
]
I would suggest using Laravel scout for this. But alternatively, to do a fuzzy text search in sql.
Or... assuming we don't use MYSQL match features, and we were to use a laravel eloquent.
1) Split the string.
2) use query builder.
$words = explode(' ', $searchString);
$results = Post::where(($q) use ($words) {
$firstWord = array_shift($words);
$q->where('example', $firstCase);
foreach($words as $word) {
$q->orWhere('example', $word);
}
})->get();
SOLVED
It was my bad.
On my blade.php, there was a line
#if (preg_match("/^[0-9a-zA-Z]*$/",$keyword))
this regex didn't have space, that's why it didn't work.
so just changed to:
#if (preg_match("/^[0-9a-zA-Z ]*$/",$keyword))
then totally it worked.
Thank you for helping teachers.
$users = User::where(function ($query) use($userSearch) {
$searchWords = explode(' ', $userSearch);
$query->where('name', 'like', '%'.$searchWords[0].'%');
for($i=1;$i<count($searchWords);$i++) {
$query->where('name', 'like', '%'.$searchWords[$i].'%');
}
})->get();

Query Builder using the like operator and dynamic values

CakePHP Version 3.5.5
What I've got:
I've got search functionality on my index pages which allows a user to search by column and value. The user selects the column from a select list and adds text into an input. I pick up this data with the following which works:
$query = $Users->find()
->where(function ($exp, $q) {
return $exp->like($this->request->getData('column'), $this->request->getData('input') . '%');
})
->andWhere([
'status' => $filter,
'cid_1' => $c1
]);
When using the debugKit it reveals the sql as: (Extract only to help explain)
FROM users Users WHERE (role LIKE :c0 AND status = :c1 AND cid_1 = :c2)',
What I'm trying to do is the following:
$testColumn = $this->request->getData('column');
$testInput = $this->request->getData('input');
$query = $Users->find()
->where(function ($exp, $q) {
return $exp->like($testColumn, $testInput . '%');
})
->andWhere([
'status' => $filter,
'cid_1' => $c1
]);
The $testColumn variable is undefined.
Whe using the debugKit it reveals the sql as: (Extract only to help explain)
FROM users Users WHERE ( LIKE :c0 AND status = :c1 AND cid_1 = :c2)',
IE: The role is not being declared before the LIKE.
What I've tried:
1. return $exp->like("$testColumn", "$testInput" . '%');
Result: Exactly the same - Variable is still undefined.
DebugKit: FROM users Users WHERE ( LIKE :c0 AND status = :c1 AND cid_1 = :c2)',
2. return $exp->like("'$testColumn'", "'$testInput'" . '%');
Result: It added '' before LIKE as can be seen below but I still can't get that variable defined.
DebugKit: FROM users Users WHERE ('' LIKE :c0 AND status = :c1 AND cid_1 = :c2)',
My Question:
Is there a way to use a dynamic value to select the search data.
Update:
Is it that I can't assign getData to a variable in this context.
You can't do this:
$testColumn = $this->request->getData('column');
return $exp->like($testColumn, $testInput . '%');
But you can do this:
$testColumn = $this->request->getData('column');
echo 'testColumn is ' . $testColumn . '<br />';
if ($testColumn === 'role') {
echo 'in column passed ' . '<br />';
}
else {
echo 'in column failed ' . '<br />';
}
Thanks. Z.
////////////////////////////////////////////////////////////////////////////////
Alimon Karim as requested.
I'm using post and my url is: https://localhost/app/users/search
Thanks Alimon, it works.
Replace
->where(function ($exp, $q) {
with
->where(function ($exp, $q) use ($testColumn,$testInput) {

Laravel adding parameter with raw queries using Like operators and '%"

I did some ways to assign parameter but it's not working
Here is my code:
$sqlDefault = "Select * from histories as h where h.status like % :status %";
return DB::select(DB::raw($sqlDefault), ['status' => $status]);
It's not working so I try another ways to assign:
'%:status%' or '%':status'%'
But it's not work
Now I don't use parameter and it's worked perfectlly
$sqlDefault = "Select * from histories as h where h.status like '%$status%'";
The question is how I can use parameter when using like operator with "%" ?
Replace $status with '%'.$status.'%'
$sqlDefault = "Select * from histories as h where h.status like :status ";
return DB::select(DB::raw($sqlDefault,['status' => '%'.$status.'%']));
or just use select only:
return = DB::select(sqlDefault , ['status' => '%'.$status.'%']);
Prepared statement's placeholder doesn't work within '%...%' because it then considered as a string value instead of placeholder. You've to put placeholder directly and then pass the value including "%{$variable}%".
Try this
$sql = "SELECT * FROM `histories` AS h WHERE `h`.`status` LIKE :status";
return DB::select($sql, [ 'status' => "%{$status}%" ]);
If you want to check what queries were run, you may use dd(DB::getQueryLog()).
Try this:
$result = DB::table('histories')->where('status', 'like', '%' . $status . '%')->get();
Try this without assign parameters
DB::table('histories')
->where('status' , 'like', '%'. $status .%' )
->get();
Or you can use direct histories app class like this
Add use App/Histories; on the top
And use query like this
Histories::where('status' , 'like', '%'. $status .%' )->get();

Yii2 add LIKE condition with "%" wildcard on the one side

I want to add like condition with % wildcard on the one side, like:
where name like 'value%'
My code:
Table::find()->filterWhere(['like', 'name' , $_GET['q'].'%' ])
->all();
But query result is:
where name like '%value\%%'
You need set the fourth operand to false in order to use custom where like conditions:
Table::find()->where(['like', 'name', $_GET['q'] . '%', false]);
From the docs:
Sometimes, you may want to add the percentage characters to the
matching value by yourself, you may supply a third operand false to do
so. For example, ['like', 'name', '%tester', false] will generate name LIKE '%tester'.
You can use:
Table::find()->where(new \yii\db\Expression('name LIKE :term', [':term' => $_GET['q'] . '%']));
or
Table::find()->where(['like', 'name', $_GET['q'] . '%', false]);
or
$likeCondition = new \yii\db\conditions\LikeCondition('name', 'LIKE', $_GET['q'] . '%');
$likeCondition->setEscapingReplacements(false);
Table::find()->where($likeCondition);
More info at https://www.yiiframework.com/doc/api/2.0/yii-db-conditions-likecondition

How to display a row count result in twig file

I am fetching a row count inside a repository and that query is returning an array as a result. How do i fetch the number count and display the result in my twig file?
This is the query fetching row count:
public function getTrailCount(){
$sql = "SELECT count(`id`) FROM `article` where `publish`='1' AND `catForFilter` like '%trail%' ";
$stmt = $this->connection->prepare($sql);
$stmt->execute();
$trailCount = $stmt->fetchAll(PDO::FETCH_ASSOC);
//$trailCount->getSingleScalarResult();
//echo '<pre>'; print_r($trailCount); exit;
return $trailCount;
}
In controller i am trying to fetch it like this, i know its a wrong procedure though:
foreach($trailCount as $trail){
$data['trailCount'] = $trail->count; //throughing an error
}
How to mend this code, any help is much appreciated. Thanks
In that case, using PDO::FETCH_NUM would be much simpler:
$trailCount = $stmt->fetchAll(PDO::FETCH_ASSOC);
...
foreach($trailCount as $trail){
$data['trailCount'] = $trail[0]; // Using "0" instead of named key
}
But if you still really want to use FETCH_ASSOC you would need:
$sql = "SELECT count(`id`) as cnt FROM `article ...... "
.....
foreach($trailCount as $trail){
$data['trailCount'] = $trail['cnt'];
}
Notice that I'm not using ->cnt but ['cnt'] since data returned from PDO is not object-based but array-bases instead.
Hope this helps a bit...
EDIT:
Given the lack of Twig part, I can only assume what you're trying to do:
/**
* #Route("/foo")
* #Template()
*/
public function fooAction(){
...
... The code above
...
return array('data' => $data);
}
And then, in your twig:
{{ data.trailCount }}
I got the solution with some help of Jovan Perovic, i did like this:
The query Part:
public function getTrailCount(){
$sql = "SELECT count(`id`) as cnt FROM `article` where `publish`='1' AND `catForFilter` like '%trail%' ";
$stmt = $this->connection->prepare($sql);
$stmt->execute();
$trailCount = $stmt->fetchAll(PDO::FETCH_ASSOC);
return $trailCount[0]['cnt']; //instead of an array i passed the single value
}
in controller:
$trailCount = $clicknblog->getTrailCount();
return $this->render('AdventureBiddingBundle:Organiser:editProfileOrganiser.html.twig', array(
'trails' => $trailCount
));
in twig file i displayed the value directly:
<p>{{ trails }}</p>
Hope this helps to someone with same problem