Eloquent WHERE LIKE clause with more than two columns - php

I've been trying to do a query in Laravel that in raw SQL will be like this
"SELECT * FROM students WHERE (((students.user_id)=$id) AND (((students.name) Like '%$q%') OR ((students.last_name) Like '%$q%') OR ((students.email) Like '%$q%')))")
I follow this thread (Eloquent WHERE LIKE clause with multiple columns) and it worked fine, but only with two columns Ej:
$students = student::where(user_id, Auth::id())
->whereRaw('concat(name," ",last_name) like ?', "%{$q}%")
->paginate(9);
But if I add more than two columns then the resultant variable is always empty, no matter if what is in the variable $q match with one or more columns:
$students = student::where(user_id, Auth::id())
->whereRaw('concat(name," ",last_name," ",email) like ?', "%{$q}%")
->paginate(9)
I am pretty sure I am missing something but i can't find what it is. Thanks in advance.

You can do something like this:
$students = student::where('user_id', Auth::id())->where(function($query) use ($q) {
$query->where('name', 'LIKE', '%'.$q.'%')
->orWhere('last_name', 'LIKE', '%'.$q.'%')
->orWhere('email', 'LIKE', '%'.$q.'%');
})->paginate(9);
The above Eloquent will output SQL similar to
"SELECT * FROM students WHERE students.user_id = $id AND (students.name like '%$q%' OR students.last_name Like '%$q%' OR students.email Like '%$q%')"

Related

MySQL query to Laravel 5.5

SELECT * FROM table WHERE age = 10 AND (first_name like %name% OR last_name like %name%);
How do you do this in Laravel 5.5?
Using query builder:
$results = DB::table('table')
->where('age', 10)
->where(function ($query) {
$query
->where('first_name', 'like', '%name%')
->orWhere('last_name', 'like', '%name%');
})
->get();
Check the official documentation (5.5) for Query Builder
You can do something like this to query
$data= DB::table('table')
->whereRaw('age'= ? AND (first_name like ? OR last_name like ?)', [10,'%'.name.'%','%'.name.'%' ])
->get();'
Official documentation to select https://laravel.com/docs/5.6/queries#selects
I don't know how many field do you use in your view.. but if you have firstname field and lastname field, then your code should be like this:
$results = DB::table('table')
->where('age', 10)
->where(function ($query) use ($request) {
$query
->where('first_name', 'LIKE', '%' . $request->first_name .'%')
->orWhere('last_name', 'LIKE', '%' . $request->last_name .'%');
})
->get();

How can I pass parameters to the query?

I use Laravel. As you know, Laravel doesn't support UNION clause for the query. So I have to write it as raw when I want to paging the whole results. Something like this:
$results = DB::select('SELECT id, title, description, imgPath
FROM news n
WHERE n.title LIKE %$q OR n.description LIKE %$q
UNION ALL
SELECT id, title, description, imgPath
FROM productions p
WHERE p.title LIKE %$q OR p.description LIKE %$q
');
As I said, I use Laravel, So how can I pass $q to the query in Laravel? All I'm trying to do is making the query safe against SQL injections. That's why I'm trying to pass the parameters to the query rather that using them directly in the query.
In pure PHP I can do that like this:
$st = $dbh->prepare('SELECT ... WHRER col LIKE %:q');
$st->bindParam(':q', $q, PDO::PARAM_INT);
I want something like this ^ in Laravel.
Yes, there is union: https://laravel.com/docs/5.3/queries#unions
I didn't test it out, but it should looks something like this:
$first = DB::table('news')
->select(['id', 'title', 'description', 'imgPath'])
->where(function($query) use ($q) {
$query->where('title', 'like', "%$q")
->orWhere('description', 'like', "%$q");
});
$result = DB::table('productions')
->select(['id', 'title', 'description', 'imgPath'])
->where(function($query) use ($q) {
$query->where('title', 'like', "%$q")
->orWhere('description', 'like', "%$q");
})
->unionAll($first)
->get();
NOTE:
With union you won't be able to do paginate out of the box. You will need to create the paginator object by yourself as shown here: Laravel - Union + Paginate at the same time?
Your "pure PHP code" won't work either. You have to respect SQL and PDO syntax
$st = $dbh->prepare('SELECT ... WHRER col LIKE :q');
$st->bindParam(':q', "%$q");
will do.
The same with Laravel: you have to define a placeholder in the query and then send it as a parameter
$sql = 'SELECT * FROM news WHERE title LIKE :q OR description LIKE :q';
$results = DB::select($sql, ['q' => "%$q"]);

Eloquent grouped orWhere

Currently have an Eloquent statement:
$contacts = Contacts::where('lname','LIKE',$searchquery.'%')
->orWhere('fname','LIKE',$searchquery.'%')
->orWhere('phone','LIKE','%'.$searchquery)
->where('active','=',1)->get();
It is treating it as
select
*
from
contacts
where
lname like $searchquery+'%'
or lname like $searchquery+'%'
or lname like $searchquery+'%'
and active = 1
what I am needing is
select
*
from
contacts
where
(lname like $searchquery+'%'
or lname like $searchquery+'%'
or lname like $searchquery+'%')
and active = 1
How do I go about grouping in Eloquent? I have found a couple examples such as:
DB::table('users')
->where('name', '=', 'John')
->orWhere(function ($query) {
$query->where('votes', '>', 100)
->where('title', '<>', 'Admin');
})
->get();
But I am only used to Eloquent, not Laravels DB Query builder. I tried adapting the Eloquent form to this
$contacts = Contacts::->where('active', '=', '1')
->where(function ($query) {
$query->orWhere('lname', 'LIKE', $searchquery.'%')
->orWhere('lname', 'LIKE', $searchquery.'%')
->orWhere('phone', 'LIKE', '%'.$searchquery);
})
->get();
No success as it does not recognize the $searchquery inside the function.
What am I missing?
So, this is what you have to do:
DB::table('users')->where(function($query) use ($searchQuery){
$query->where('lname', 'LIKE', $searchQuery . '%')
->orWhere('fname', 'LIKE', $searchQuery . '%')
->orWhere('phone','LIKE', '%' . $searchquery);
})
->get();
Note that I've put use ($searchQuery) so it can be used inside the closure
When you use orWhere with multiple where clauses, you need to be careful!
Where clauses after orWhere doesn't effected to sibling where clauses before orWhere clauses such as where, whereHas, whereDoesntHave, orWhereHas
also you have to pass $searchquery variable inside to function in where clause using use ($searchquery)
Contacts::->where(function ($query) use ($searchquery) {
$query->orWhere('lname', 'LIKE', $searchquery.'%')
->orWhere('lname', 'LIKE', $searchquery.'%')
->orWhere('phone', 'LIKE', '%'.$searchquery);
})
->where('active', '=', '1')
->get();

Search in multiple tables by eloquent query

I have two tables: posts and pages. Based on the keyword, I want to search different columns of the two tables for the occurrence of keyword. The two tables do not have related content.
I have written two queries one for each table. Following are the queries:
$result1 = Post::where('title_en', 'LIKE', '%' . $keyword . '%')
->or_where('title_np', 'LIKE', '%' . $keyword . '%')
->order_by('id', 'desc')
->paginate(10);
$result2 = Page::where('title', 'LIKE', '%' . $keyword . '%')
->or_where('content', 'LIKE', '%' . $keyword . '%')
->order_by('id', 'desc')
->paginate(10);
The above queries return two different Laravel\Paginator object. But I want a single Laravel\Paginator object so that a single pagination is displayed on the page which works for both the queries or on a single query which achieves the functionality of both the above queries. How would I be able to do that?
Since they are unrelated tables, you need to do some trickery that's simply too complex for Eloquent to handle, you need to do something similar to the following to join the two queries together, and still be able to do your limit / ordering on the combined queries:
$results = DB::query('SELECT id, title FROM (
SELECT id, title FROM `post` where `title_np` LIKE "%'.$keyword.'%" OR `title_en` LIKE "%'.$keyword.'%"
UNION ALL
SELECT id, title FROM `page` where `title` LIKE "%'.$keyword.'%" OR `content` LIKE "%'.$keyword.'%"
) temp_table
ORDER BY `id` desc
LIMIT 0, 10
')
NB the above is untested, purely an example of the approach you'll need to take, not sure this will actually work.
I know this question has been answered ages ago but If someone ends up here like me, I had a very similar issue, and here is how I did it using the eloquent way :
$users = User::where('active', 1)
->where(function ($subQuery) use ($searchKeyword) {
$subQuery->where('pseudo', 'LIKE', "%$searchKeyword%")
->orWhere('first_name', 'LIKE', "%$searchKeyword%")
->orWhere('last_name', 'LIKE', "%$searchKeyword%")
->orWhere('email', 'LIKE', "%$searchKeyword%");
})
->whereHas('addressPrincipal')
->select(array_merge(['id', 'pseudo', DB::raw("CONCAT(users.first_name,' ',users.last_name) as name")],
[DB::raw('"user" as source')]));
$usersAll = Subsidiary::where('active', 1)
->where(function ($subQuery) use ($searchKeyword) {
$subQuery->where('slug', 'LIKE', "%$searchKeyword%")
->orWhere('name', 'LIKE', "%$searchKeyword%")
->orWhere('email_principal', 'LIKE', "%$searchKeyword%");
})
->unionAll($users)
->select(array_merge(['id', 'slug as pseduo', 'name'],
[DB::raw('"subsidiary" as source')]))
->paginate(10);
You must have noticed that I have used array_merge in the select statement, I have done this as I needed to know from which table respective records were getting fetched.

Kohana 3 ORM - grouping where conditions with parentheses

I'm trying to run a query through the ORM like this:
SELECT * from table where (fname like 'string%' or lname like 'string%')
AND (fname like 'string2%' or lname like 'string2%');
Here's what i have so far:
$results = ORM::factory('profiles');
foreach ($strings as $string) {
$result->where('fname', 'like', "$string%");
$result->or_where('lname', 'like', "$string%");
}
But this doesn't account for the parentheses. Any ideas?
Found the answer.
It's done with Kohana's where_open() and where_close() methods.
It works fine for me .
ORM code sample
$musicslist = ORM::factory('user_music')
->where_open()
->where('title', 'like', '%' . $search . '%')
->or_where('album', 'like', '%' . $search . '%')
->or_where('artist', 'like', '%' . $search . '%')
->where_close()
->and_where('app_userid','=', $userid)
->find_all();
it will create SQL query
SELECT `user_musics`.* FROM `user_musics` WHERE (`title` LIKE '%as%' OR `album` LIKE '%as%' OR `artist` LIKE '%as%') AND `app_userid` = '21'
Couldn't get code formatting to work in the comment - just thought I'd add a simple example to the answer in case anyone else comes across it:
$query = DB::select()
->from('some_table')
->where_open()
->where('column_one', '=', 1)
->or_where('column_two', '=', 2)
->where_close();
would produce the following SQL:
SELECT * FROM some_table
WHERE (column_one = 1 OR column_two = 2);

Categories