I have issues with OR conditions in cake php query builder. This will return 0 result.
$results = $this->paginate('Did', array('Did.ivr_id LIKE ' => $number . "%",'OR'=>array('Did.did LIKE ' => $number . "%")));
$result = $this->paginate = array(array('Did.did LIKE' => $number . "%"));
$this->set('dids', $results);
When i apply condition on simple column it gives accurate result
$results = $this->paginate('Did', array('Did.ivr_id LIKE' => $number . "%"));
$result = $this->paginate = array(array('Did.did LIKE' => $number . "%"));
$this->set('dids', $results);
You need to put all the conditions that you want to OR inside the OR array.
$results = $this->paginate(
'Did',
array(
'OR'=>array(
'Did.ivr_id LIKE ' => $number . "%",
'Did.did LIKE ' => $number . "%"
)
)
);
Related
At first , I apologize for my poor English.
environmental information
language: PHP 7.4.13
framework: CakePHP 4.2.6
At the SQL DB table, there are 6 colmuns.
(columnA , columnB , columnC , columnD , columnE , columnF)
I want to search from the concatnated columns.
I want to "OR search" with 4 conditions.
Whether '${columnA}.${columnC}' matches $str
or
Whether '${columnB}.${columnC}' matches $str
or
Whether '${columnD}.${columnF}' matches $str
or
Whether '${columnE}.${columnF}' matches $str
Now , I write as this to search with one condition .
$query->where(function ($exp, $q) use($str) {
$concat = $q->func()->concat([
'columnA' => 'identifier',
'columnC' => 'identifier'
]);
return $exp->like($concat, '%' . $str . '%' );
});
If I search from "not concatnated columns" , I write this .
$query->where([
0 => [
'or' => [
'${columnA} LIKE' => '%' . $str . '%' ,
'${columnB} LIKE' => '%' . $str . '%' ,
'${columnC} LIKE' => '%' . $str . '%' ,
'${columnD} LIKE' => '%' . $str . '%' ,
]
],
]);
Finally , I want to do something like this.(Ofcourse , this throws a syntax error )
$query->where([
0 => [
'or' => [
'${columnA}.${columnC} LIKE' => '%' . $str . '%' ,
'${columnB}.${columnC} LIKE' => '%' . $str . '%' ,
'${columnD}.${columnF} LIKE' => '%' . $str . '%' ,
'${columnE}.${columnF} LIKE' => '%' . $str . '%' ,
]
],
]);
Can someone help me?
The query expression object has an or() method that you can use, it either takes an array of conditions that are combined using OR, or a callable that receives a new query expression object that uses the OR operator.
In any case you need to be aware that QueryExpression::like() will not return a new expression object, but it will add a new like expression to the current query expression object's stack instead.
That being said, the callback variant would look something like this:
$query->where(function (
\Cake\Database\Expression\QueryExpression $exp,
\Cake\ORM\Query $q
) use (
$str
) {
return $exp->or(function ($exp) use ($q, $str) {
$concatAC = $q->func()->concat([
'columnA' => 'identifier',
'columnC' => 'identifier'
]);
$concatBC = $q->func()->concat([
'columnB' => 'identifier',
'columnC' => 'identifier'
]);
return $exp
->like($concatAC, '%' . $str . '%')
->like($concatBC, '%' . $str . '%')
// ...
});
});
The former variant can be used by passing an empty array, that way you receive an empty query expression object that you can then fill with your conditions:
$query->where(function (
\Cake\Database\Expression\QueryExpression $exp,
\Cake\ORM\Query $q
) use (
$str
) {
// ...
return $exp
->or([])
->like($concatAC, '%' . $str . '%')
->like($concatBC, '%' . $str . '%')
// ...
});
Lastly you can also at any point change the string used for concatenating the expressions by any query expression object using QueryExpression::setConjunction():
$query->where(function (
\Cake\Database\Expression\QueryExpression $exp,
\Cake\ORM\Query $q
) use (
$str
) {
// ...
return $exp
->setConjunction('OR')
->like($concatAC, '%' . $str . '%')
->like($concatBC, '%' . $str . '%')
// ...
});
All three variants will result in the same SQL, that is:
WHERE (
CONCAT(columnA, columnC) LIKE %...% OR
CONCAT(columnB, columnC) LIKE %...% OR
...
)
See also
Cookbook > Database Access & ORM > Query Builder > Advanced Conditions
How can I write the follow sql query in MeDoo???
SELECT * FROM lockers WHERE Active = 1 AND GymID = " . $gimid . " AND ForMale = " . $male .
($filter ? " AND Locker LIKE '%" . $filter . "%'" : "")
The problem for me is the conditional LIKE.
$total = $this->db->count('lockers',
['AND' => [
'Active' => 1,
'GymID' => $gimid,
'ForMale' => $male
]]
);
Some suggestion????
Thanks a lot!!!
Finally, I solved it in the follow way:
// getting locker's total
$total = $this->db->debug()->count('lockers', [
'AND' => [
'Active' => 1,
'GymID' => $gimid,
'ForMale' => $male,
'Locker[~]' => $filter ? $filter : '' //<- LIKE with empty string shows all
]
]);
Here is my table like below.
Id Firstname Lastname
1 Akhil Mokariya
2 Harshit joshi
When i search the result "Akhil Mokariya" it's give me null record but i need result like below.
1 Akhil Mokariya
My Query is like below.
$searcharray = array(
'students.firstname' => $searchterm,
'students.lastname' => $searchterm,
'students.guardian_name' => $searchterm,
'students.adhar_no' => $searchterm,
'students.samagra_id' => $searchterm,
'students.roll_no' => $searchterm,
'students.admission_no' => $searchterm,
);
$this->db->select('classes.id AS `class_id`,students.id,classes.class,sections.id AS `section_id`,sections.section,students.id,students.admission_no , students.roll_no,students.admission_date,students.firstname, students.lastname,students.image, students.mobileno, students.email ,students.state , students.city , students.pincode , students.religion, students.dob ,students.current_address, students.permanent_address,IFNULL(students.category_id, 0) as `category_id`,IFNULL(categories.category, "") as `category`, students.adhar_no,students.samagra_id,students.bank_account_no,students.bank_name, students.ifsc_code ,students.father_name , students.guardian_name , students.guardian_relation,students.guardian_phone,students.guardian_address,students.is_active ,students.created_at ,students.updated_at,students.gender,students.rte,student_session.session_id')->from('students');
$this->db->join('student_session', 'student_session.student_id = students.id');
$this->db->join('classes', 'student_session.class_id = classes.id');
$this->db->join('sections', 'sections.id = student_session.section_id');
$this->db->join('categories', 'students.category_id = categories.id', 'left');
$this->db->where('student_session.session_id', $this->current_session);
$this->db->group_start();
$this->db->or_like($searcharray);
$this->db->group_end();
$this->db->order_by('students.id');
// $this->db->limit('100');
$query = $this->db->get();
I find in my own searches that I will check to see if the search is for a string that has a space, so I can split it and use it for first and last name:
if( strpos( $searchterm, ' ' ) !== FALSE )
$search_parts = explode(' ', $searchterm);
Then, you may want to make sure that there are two parts:
if( count( $search_parts ) == 2 ){
// you know you have two parts
}
So then you'd be able to use the parts in your array:
'students.firstname' => $search_parts[0],
'students.lastname' => $search_parts[1],
And if they may be out of order:
'students.firstname' => $search_parts[1],
'students.lastname' => $search_parts[0],
I am using a different way of creating a query, but to show you an example, I do this:
if( strpos( $search, ' ' ) !== FALSE )
{
$search_parts = explode(' ', $search);
$sql .= '
OR (
first_name LIKE "%' . $this->db->escape_like_str( current($search_parts) ) . '%" ESCAPE "!" AND
last_name LIKE "%' . $this->db->escape_like_str( end($search_parts) ). '%" ESCAPE "!"
) ';
reset($search_parts);
$sql .= '
OR (
last_name LIKE "%' . $this->db->escape_like_str( current($search_parts) ) . '%" ESCAPE "!" AND
first_name LIKE "%' . $this->db->escape_like_str( end($search_parts) ). '%" ESCAPE "!"
)
';
}
Also, if you don't care about code portability, you should see this answer with CONCAT: Mysql Concat two columns while searching with LIKE
That ends up looking something like this:
// Check if search was input as full name
if( strpos( $search, ' ' ) !== FALSE )
{
$sql .= '
OR ( CONCAT( first_name, " ", last_name ) LIKE "%' . $this->db->escape_like_str( $search ) . '%" ESCAPE "!" )
OR ( CONCAT( last_name, " ", first_name ) LIKE "%' . $this->db->escape_like_str( $search ) . '%" ESCAPE "!" ) ';
}
So, in your case, I think you should be able to do this:
$searcharray = array(
'students.firstname' => $searchterm,
'students.lastname' => $searchterm,
'students.guardian_name' => $searchterm,
'students.adhar_no' => $searchterm,
'students.samagra_id' => $searchterm,
'students.roll_no' => $searchterm,
'students.admission_no' => $searchterm,
'CONCAT(students.firstname, " ", students.lastname)' => $searchterm,
'CONCAT(students.lastname, " ", students.firstname)' => $searchterm
);
I'm only using a small part of this function actually but I wanted to post it all to provide the big picture. There is a part of the query in this function that finds recent attachments a user has posted to the forums. The block is on the user profile. IT works but the problem is ... it's VERY slow!! Core attachments locks up for 30+ seconds and makes my site unusable.
Any one who could help it would be much appreciated.
private function getAttImages($limit, $forumIds = 0, $fidsReverse = false, $topicIds = 0, $membersIds = 0, $order = 'attach_date', $sort = 'desc', $group = null)
{
$fids = '';
if ($forumIds)
{
$r = '';
if ($fidsReverse)
{
$r = ' NOT ';
}
if (is_array($forumIds))
{
$forumIds = implode(',', $forumIds);
}
$fids = ' AND forums_topics.forum_id ' . $r . ' IN (' . $forumIds . ')';
}
$tids = '';
if ($topicIds)
{
$tids = ' AND forums_topics.tid IN (' . $topicIds . ')';
}
$mids = '';
if ($membersIds)
{
$mids = ' AND core_attachments.attach_member_id IN (' . $membersIds . ')';
}
$whereT = array();
$joinsT = array();
$findInPosts = ' AND ' . \IPS\Db::i()->findInSet('queued', array('0'));
$joinsT[] = array(
'select' => 'forums_posts.*',
'from' => 'forums_posts',
'where' => array("forums_posts.pid=core_attachments_map.id2" . $findInPosts),
);
$findInTopics = ' AND ' . \IPS\Db::i()->findInSet('approved', array('1'));
$joinsT[] = array(
'select' => 'forums_topics.*',
'from' => 'forums_topics',
'where' => array("forums_topics.tid=forums_posts.topic_id" . $findInTopics . $fids . $tids),
);
$select = 'core_attachments.attach_id AS custom_data, core_attachments.*';
if ($group)
{
$select = 'core_attachments.attach_id AS custom_data, COUNT(attach_is_image) as cnt_images, SUM(attach_hits) as summ_attach_hits, core_attachments.*';
}
$joinsT[] = array(
'select' => $select,
'from' => 'core_attachments',
'where' => array('core_attachments.attach_is_image=1 AND core_attachments.attach_is_archived=0 AND core_attachments.attach_id=core_attachments_map.attachment_id' . $mids),
);
$joinsT[] = array( 'select' => 'core_members.member_id, core_members.member_group_id, core_members.mgroup_others, core_members.name, core_members.members_seo_name',
'from' => 'core_members',
'where' => array('core_attachments.attach_member_id=core_members.member_id' . $mids),
);
$joinsT[] = array( 'select' => 'core_permission_index.perm_id',
'from' => 'core_permission_index',
'where' => array("core_permission_index.app='forums' AND core_permission_index.perm_type='forum' AND core_permission_index.perm_type_id=forums_topics.forum_id"),
);
$groupT = $group;
$whereT[] = array(
"core_attachments_map.location_key='forums_Forums' AND " .
\IPS\Db::i()->findInSet('perm_view', array_merge(array(\IPS\Member::loggedIn()->member_group_id), array_filter(explode(',', \IPS\Member::loggedIn()->mgroup_others)))) . " OR perm_view='*'" .
$fids . $tids . $mids
);
$table = new \IPS\Helpers\Table\Db(
'core_attachments_map',
\IPS\Http\Url::internal('app=core&module=system&controller=nbattachpictures', 'front', 'nbattachpictures'),
$whereT,
$groupT
);
$table->joins = $joinsT;
$table->limit = $limit;
$table->sortBy = $order;
$table->sortDirection = $sort;
$table->rowsTemplate = array(\IPS\Theme::i()->getTemplate('plugins', 'core', 'global'), 'nbAttachmentsBlocksRows');
$table->parsers = array(
'custom_data' => function( $val, $row )
{
return array(
'topic_data' => \IPS\Http\Url::internal("app=forums&module=forums&controller=topic&id={$row['tid']}", 'front', 'forums_topic', array($row['title_seo'])),
'summ_attach_hits' => $row['summ_attach_hits'],
'jewel' => $this->attachJewel($row['summ_attach_hits']),
);
},
);
return $table;
}
I'm running Laravel 5 and have built a small search function:
$q = Input::get('q');
$search_terms = explode(' ', $q);
$user_query = User::select();
$news_query = Article::select();
foreach ($search_terms as $term) {
$user_query->where('username', 'like', '%' . $term . '%');
$news_query->where('title', 'like', '%' . $term . '%');
}
$user_results = $user_query->get();
$news_results = $news_query->get();
return view('search', ['q' => $q, 'user_results' => $user_results, 'news_results' => $news_results]);
It works for one search term, but doesn't quite work with multiple words.
Example:
"boss" returns users and news items that contain "boss"
"boss man" returns users and news items that contain "boss"
"man boss" returns users and news items that contain "man"
How can I make adjustments so it will return users and news items that contain "boss" or "man" ?
Right now, your query is executed using and statements, so MySQL is looking for usernames consisting of both boss and man.
You can change to orWhere() and it should work right away. Here's a quick experiment I did in Tinker using your code:
$terms = explode(' ', 'c a');
$user_query = User::select();
foreach ($terms as $term) {
$user_query->orWhere('username', 'like', '%' . $term . '%');
}
$user_results = $user_query->get();
$user_results->toArray();
// array(
// 0 => array(
// 'id' => 2,
// 'username' => 'christopher',
// 'created_at' => '2014-04-27 18:41:56',
// 'updated_at' => '2014-11-07 13:42:58',
// 'remember_token' => NULL
// ),
// 1 => array(
// 'id' => 4,
// 'username' => 'Kalle',
// 'created_at' => '2014-11-07 13:42:55',
// 'updated_at' => '2014-11-07 13:42:55',
// 'remember_token' => NULL
// )
// )