How do I query a relation database in Laravel? - laravel

I have this search query for Post model in Laravel:
return $q ->where('title', 'like', '%'.$keyword.'%')
Which works totally fine. In my Post model I also have a relation database categories. This is available as an object in my returned post object.
Is there a way I can query the category -> name?
I have tried:
return $q ->where('category->name', 'like', '%'.$keyword.'%')

I believe what you are looking for can be found here: https://laravel.com/docs/5.6/eloquent-relationships#querying-relations
For your use case you need to make sure you have the relationship established in your Post model. If that is set your query should look similar to the following:
return $q->where('title', 'like', '%'.$keyword.'%')->whereHas('category',
function ($query) use ($keyword) {
$query->where('name', 'like', '%'.$keyword.'%');
})->get();
Hope this helps!

If you're db is well structured - then will want to use Laravel's ORM for this stuff.
https://laravel.com/docs/5.6/eloquent#introduction

I assume that you have Models:
Post
Category
Also that you have category_id as a foreign key in Post model.
This is basic structure.
I assume that you want to search Posts and Categories same time so you can do something like this:
return Post::leftJoin('categories', 'posts.category_id', '=', 'categories.id)
->where('categories.name', 'like', '%' . $keyword . '%')
->orWhere('posts.title', 'like', '%' . $keyword . '%')
->get();

Related

Search with multiple tables

I have 3 tables that are connected/have relation.
Posts table have many tag and one Category
Category table have many Posts
Tag table have many Posts
i want a search feature, i know how to search only use Posts (based on title).
I tried to search each tables with Where in my controller but still no luck.
public function Search(Request $request)
{
$search = $request->search;
$posts = post::where('title', 'like', "%{$search}%")->paginate(5);
return view('search', compact('posts'))->with('result', $search);
}
For example
i have a post Titled 'Test' and with Category 'Tost' and with Tags 'Tast and Tust'
so if i type either the title, category or tags i want it to show up. how can i achieve it?
Try use whereHas method (for further info check https://laravel.com/docs/5.8/eloquent-relationships#querying-relations)
So would become something like:
Post::query()
->where('title', 'like', "%$search%")
->orWhereHas('categories', function ($query) use ($search) {
$query->where('name', 'like', "%$search%");
})
You must use like this.
Post::where('title', 'like', '%' . Input::get('search') . '%')->get();

Sort a result of search in Laravel Eloquent model with relations

I did a search for a Model (Startup), next step is to order results of the search by DESC or ASC (it doesn't matter now)
My current code is:
$startups = Startup::whereHas('category', function ($query) use ($search, $sort_type) {
$query
->where('name', 'like', "%$search%")
->orderBy('name', $sort_type);
})
->orWhere('description', 'LIKE', "%$search%")
->orWhere('url', 'LIKE', "%$search%")
->get();
return StartupResource::collection($startups);
Explanation of the code:
as you see at the beginning I'm using "whereHas" to search also for coincidences in related model - "Category".
then inside of "whereHas" I'm trying to apply 'orderBy('name', $sort_type)' but it doesn't work properly (it doesn't sort by categories)
I know that we can create method in Startup model and sort it inside of the method, but the problem is that I have to pass variables to the method ( $sort_type, $search) and I don't know how to do this
So how to sort Startups model including related Category model by ASC or DESC in my case ?
Thank you guys a lot for any ideas and help!
That's not possible with whereHas(). You can use a JOIN:
$startups = Startup::select('startups.*')
->join('category', 'category.id', '=', 'startups.category_id')
->where('category.name', 'LIKE', "%$search%")
->orWhere('startups.description', 'LIKE', "%$search%")
->orWhere('startups.url', 'LIKE', "%$search%")
->orderBy('category.name', $sort_type)
->get();

Laravel Eloquent query OR WHERE

How to write a Laravel Eloquent Query for a Model/table named Country/countries where If I search from any variable and get result according to and the query will search from 3 different column as similar in SQL in given Image.
How to write a similar query in Laravel in Laravel 5.6 /5.7
What you are looking for is where() and orWhere() functions in Query Builder in laravel
$countries = Country::where('name', 'like', '%af%')
->orWhere('alpha-2', 'like', '%af%)
->orWhere('alpha-3', 'like', '%af%')
->get();
and if you want to dynamically pass values to where() functions.
$value = 'af';
$countries = Country::where('name', 'like', "%$value%")
->orWhere('alpha-2', 'like', "%$value%")
->orWhere('alpha-3', 'like', "%$value%")
->get();
Note 'Double Quotation' in variable passing.
use your model query like this
Model::where(function($query)
{
$query->where('column1', 'like', 'keyword');
$query->orWhere('column2', 'like', 'keyword');
$query->orWhere('column3', 'like', 'keyword');
})->get();

Laravel: searching related data

I have models: Student, Tutor, Country.
Main model is Student with code:
public function studentTutors()
{
return $this->morphedByMany(Tutor::class, 'studentable')
->with('tutorAddresses');
}
Then relations.
Tutor:
public function tutorAddresses()
{
return $this->hasMany(TutorAddress::class, 'tutor_id', 'id')
->with('tutorCountry');
}
TutorAddress:
public function tutorCountry()
{
return $this->hasOne(Country::class, 'country_id', 'country_id')
->where('user_lang', 'en');
}
How do I use it:
$paginator = $student->studentFavouriteTutors()
->getQuery() //for paginate
->where(function ($query) use ($searchPhraze) {
if (strlen(trim($searchPhraze))) {
return $query
->where('username', 'like', '%' . $searchPhraze . '%')
->orWhere('firstname', 'like', '%' . $searchPhraze . '%')
->orWhere('lastname', 'like', '%' . $searchPhraze . '%');
}
})
->paginate($pages, $columns, $pageName, $page);
Question:
I am searching in tutors table (Tutor) for user/first/last names.
Is there are way to search for country name from countries table (Country: tutorCountry)? Lets say, table has 'name' column with country names.
If yes, how should $paginator code look like, to get data from countries table?
Same question goes for relation tutorAddresses. Lets say, table has 'city' column with city names.
Is this possible?
Now, I do not use relations for search, and just do joins.
BTW: I tried hasManyThrough relation, but it does not seem to pass data from that 'through' table, so this is not going to work for me. Also, my 'through' relations go a bit too deep for it (unless I do not understand something as far as this relation is concerned).
EDIT:
Answer by jedrzej.kurylo is perfect!
I just want to add, for all these, who look for a way to search within relation of a relation, like in my case:
studentTutors / tutorAddresses / tutorCountry
... where within model Student, I also want to look for country name inside of Country model, that is deeper in chain of relations and is not directly related to Tutor, but to TutorAddress, which is related to Tutor.
It is just a question of nesting queries:
$searchPhraze = 'France';
$res = $student->studentFavouriteTutors()
//first relation level
->whereHas('tutorAddresses', function($query) use ($searchPhraze) {
//deeper relation
$query->whereHas('tutorCountry', function($query) use ($searchPhraze) {
$query->where('country', 'like', '%' . $searchPhraze . '%');
});
})->get();
Or you can even combine of searches of parent and child relations:
$searchPhraze = 'Hodkiewiczville';
$res = $student->studentFavouriteTutors()
//first relation level
->whereHas('tutorAddresses', function($query) use ($searchPhraze) {
$query
//first level relation search
->where('city', 'like', '%' . $searchPhraze . '%')
//deeper relation
->orWhereHas('tutorCountry', function($query) use ($searchPhraze) {
$query->where('country_label', 'like', '%' . $searchPhraze . '%'));
});
})->get();
Above code found related datasets as expected.
Thou, I am not sure as to benchmark of this.
You can search data in related tables using whereHas() function, e.g.:
$student->studentFavouriteTutors()
->whereHas('tutorAddresses', function($query) use ($searchPhraze) {
$query->where('city', 'like', '%' . $searchPhraze . '%');
})->get();
This will get you all student's favourite tutors that have an address where city column contains given phrase.

How to force a where clause on a collection in laravel 5

I have a table that I am running a search on. Foo. I want to check if the search term is like a bunch of different fields in the table. But I want the results to be forced to be "active".
I am using Laravel 5.0
$foos = DB::table('foo')
->where('name', 'LIKE', '%' . $query . '%')
->orWhere('description', 'LIKE', '%' . $query . '%')
->orWhere('address_city', 'LIKE', '%' . $query . '%')
->orWhere('short_description', 'LIKE', '%' . $query . '%')
->orWhere('interview', 'LIKE', '%' . $query . '%')
->get();
$foos = $foos->where('active', true)->get();
Collection has a where method similar to query builder.
$activeFoos = $foos->where('active', true);
https://laravel.com/docs/5.4/collections#method-where
Edit :
I understand what you need from the comments now. Try the code below, and also note that i changed your original $query to $find. So keep that in mind.
$foos = DB::table('foo')
->where('active', true)
->where(function ($query) use ($find) {
$query->where('name', 'LIKE', "%{$find}%")
->orWhere('description', 'LIKE', "%{$find}%")
->orWhere('address_city', 'LIKE', "%{$find}%")
->orWhere('short_description', 'LIKE', "%{$find}%")
->orWhere('interview', 'LIKE', "%{$find}%");
})
->get();
Is the value of active actually true or just truthy (such as an integer of 1)?
For loose comparisons then you'll need to use whereLoose('active', true), otherwise Laravel's method where() on Collections will perform strict type comparisons.
Like Sandeesh said, you'll need to remove the get() since get() is a query builder method, Collections where() methods return a new collection not a builder instance.

Resources