I have created a search filter. Basically I'm getting records from single table so it works fine. But when i try to get data from another table, it is not correct. This is my drivers_table (driver_id is PK)
I'm using this query..
$drivers = Drivers::where('city', 'like', "$keywords[0]%")
->Where('first_name', 'like', "$keywords[1]%")
->get();
I have two dropdowns, Lets suppose I have 50 drivers, When i select City "DOHA" from first dropdown, Using ajax it gets me records of 20 drivers out of 50, and then i select first_name "ASFAND" from 2nd dropdown, it gets me records of people whose first name is Asfand from that list of 20 drivers. There was 5 people whose name was Asfand and also they were from DOHA City ( because i have selected both DOHA as city from first dropdown and first_name as Asfand from second drop down.
Everything works perfect. But now my question is I have a 3rd dropdown from which i will select Bank name, but bank name is not in the Drivers table, There is another table.
Banks (id, driver_id, bank_name)..
How can i get records now?
$drivers = DB::table('drivers')
->join('bank','bank.driver_id','=','drivers.driver_id')
->where('city', 'like', "$keywords[0]%")
->Where('first_name', 'like', "$keywords[1]%")
->orWhere('bank.bank_name', 'like', "$keywords[3]%")
->get();
Now if i select doha from first dropdown it doesnot show me any record.. if i select bank name from 3rd dropdown then it shows me record.. I want dropdowns to be independent..
If i don't select anything from 3rd dropdown, it should still show what i selected from first two dropdowns.
You can use joins only when it is required.
$drivers = DB::table('drivers')
->where('city', 'like', "$keywords[0]%")
->where('first_name', 'like', "$keywords[1]%")
->when(!empty($keywords[3]), function ($query) use ($keywords) {
$query->join('bank','bank.driver_id','=','drivers.driver_id')
$query->where('bank.bank_name', 'like', $keywords[3].'%');
})
Try like this,
$drivers = DB::table('drivers')
->join('bank','bank.driver_id','=','drivers.driver_id')
->where(function($query) use ($keywords) {
$query->where('drivers.city', 'like', "$keywords[0]%")
->orWhere('drivers.first_name', 'like', "$keywords[1]%")
->orWhere('bank.bank_name', 'like', "$keywords[3]%");
})
->toSql();
echo "<pre>";
print_r($drivers);
die();
Check with this it prints your query, try it in sql, if it working in that with your criteria then its perfect.
Try this -
$query = Drivers::query();
$query->leftjoin('bank','bank.driver_id','=','drivers.driver_id');
$query->where(function ($query) use($keywords){
$query->where('city', 'LIKE', "$keywords[0]%")
->orwhere('first_name', 'LIKE', "$keywords[1]%")
->orwhere('bank.bank_name', 'LIKE', "%$keywords[3]%");
});
$query->get();
Related
I'm using Laravel 8 and I have a table with a combined column of first_name and last_name the problem is I can only search it by either the first_name only or last_name only, not with the full name, would be better if I can have an option to orderBy it by full name also. I'm trying to avoid the whereRaw as much as possible as I've researched to have very hard performance especially in large tables.
This is my search function (How to search using combined first_name and last_name)
public function scopeSearch($query, $term)
{
$term = "%$term%";
$query->where(function ($query) use ($term) {
$query->where('type', 'LIKE', $term)
->orWhere('name', 'LIKE', $term)
->orWhereHas('level', function($query) use ($term) {
$query->where('name', 'LIKE', $term);
})
->orWhereHas('employee', function($query) use ($term) {
$query->where('first_name', 'LIKE', $term);
$query->orWhere('last_name', 'LIKE', $term);
$query->orWhere('employee_number', 'LIKE', $term);
})
->orWhereHas('status', function($query) use ($term) {
$query->where('name', 'LIKE', $term);
})
});
}
And this is my table query (How to orderBy combined first_name and last_name)
$models = Model::where('company_id', Auth::user()->company_id)
->search(trim($this->search))
->orderBy($this->column, $this->order)
->paginate($this->size);
Use a FULLTEXT index across all the columns. It will be much faster.
You can add
SELECT CONCAT(`first_name`, ' ', `last_name`) as full_name FROM `users`;
However, you must make it in the subquery so that laravel can know what is full_name
Or you can append full_name attribute to you model and search it in the front end,
I have assigned search method for my application and i have made relationship between two tables "users " table and "posts" table both of them have same field name "created_at" and when i want to fetch data that when this post has been created it will bring the date in users table created_at field not in posts table created_at field.
All i want is how to tell the system make difference between which table field name i mean .
This date comes from created_at field in users table
I wand to come date in this created_at field in posts table
ListingController.php
public function search(Request $request){
$posts = Post::with(['comments','category','creator'])
->join('users', 'posts.created_by', '=', 'users.id')
->where('slug', 'LIKE', '%'.$request->search. '%')
->orWhere('users.name', 'LIKE', '%'.$request->search. '%')
->where('status',1)->orderBy('posts.id','DESC')->paginate(5);
return view('front.listing',compact('posts'));
}
listing.blade.php
<div class="article_date">
by: {{ $post->creator->name }} , {{$post->created_at->diffForHumans()}}
</div>
You are calling your relationship improperly. You should not use a join there. Use constrained eager loading instead
There will be no conflict in the created_at date since there will be no join.
While still keeping your search query inside the closure of the relationship.
$posts = Post::with(['comments', 'category'])
->with(['creator' => function ($query) use ($request) {
$query->where('name', 'LIKE', '%' . $request->search . '%');
}])
->where('slug', 'LIKE', '%' . $request->search . '%')
->where('status', 1)
->orderBy('id', 'DESC')
->paginate(5);
In my application, there are article and news tables. I know I can search for matching title in news table or article,
just by doing something like:
$query = $request['search'];
$searchResult= DB::table('article')->where('title', 'LIKE', '%$query%')
->orderBy('created_at', 'desc')->paginate(10);
or
$searchResult= DB::table('news')->where('title', 'LIKE', '%$query%')
->orderBy('created_at', 'desc')->paginate(10);
but what I want to do is to search both of them and return some information about them alongside what the reuslt type is, in terms of news and article. And than orther them by created_at as if they were in the same table.
Laravel 5.4
You can do that if getting 10 news and 10 articles per page is what you want. But in this case, you'll need to manually create paginator.
Load the data:
$articles = DB::table('article')
->where('title', 'like', '%$query%')
->latest()
->skip(0)
->take(10)
->get();
$news = DB::table('news')
->where('title', 'like', '%$query%')
->latest()
->skip(0)
->take(10)
->get();
Then merge the results:
$merged = $articles->merge($news);
Then order by date if you need to:
$merged = $merge->sortByDesc('created_at');
I have a table named records with a user_id column which links to a users table to set ownership.
I can correctly filter the records by title with a search string:
$records->where('title', 'LIKE', '%'.$search.'%');
But I'd like to return also the results containing the users.firstname and users.lastname, this is my (awful) join attempt:
$records->join('users', 'users.id', '=', 'records.user_id')
->where('users.firstname', 'LIKE', '%'.$search.'%')
->orWhere('users.lastname', 'LIKE', '%'.$search.'%')
->orWhere('title', 'LIKE', '%'.$search.'%');
// SQLSTATE[23000]: Integrity constraint violation: 1052 Column 'id' in order clause is ambiguous
While I wait for a better answer I found a solution which works but it's not optimal since it involves one extra query to gather the author user_id and use it subsequently to query the records:
// Get the author ID
$author = DB::table('users')
->select(DB::raw('CONCAT_WS(" ",`firstname`,`lastname`) as `fullname`,id'))
->having('fullname', 'LIKE', '%'.$search.'%')
->first();
// $author output:
stdClass Object
(
[fullname] => John Doe
[id] => 35
)
// Query the records using the gathered ID
$records->where('user_id', $author->id)
->orWhere('title', 'LIKE', '%'.$search.'%');
Problems with this solution: Apart from the extra query, if somebody searches for John Doe or Some Title the results are correct. But if searching for John Doe Some Title, nothing is shown because the author and the title can't be found.
You need to set that also use the search parameter in your inner query:
$records->join('users', function($join) use ($search)
{
$join->on('users.id', '=', 'records.user_id')
->where('users.firstname', 'LIKE', '%'.$search.'%')
->orWhere('users.lastname', 'LIKE', '%'.$search.'%');
});
If I understand you want to return result from Records by filtering with $search and also want to show users info for this records.
You can use Eloquent.
Your model must be:
In User model:
public function records()
{
return $this->hasMany(Record::class);
}
In Record model:
public function user()
{
return $this->belongsTo(User::class);
}
And in Controller:
Record::where('title', 'LIKE', '%'.$search.'%')
->with('user')
->first();
I have a table customers and a table orders.
And I want to make an ajax call to get a list of all customers with name x and their orders.
I got the ajax function and my function to retrieve the customer looks like this:
$customers = Customer::where('first_name', 'LIKE', '%'.$name.'%')
->orWhere('last_name', 'LIKE', '%'.$name.'%')
->where('user_id', Auth::user()->id)
->get()
->toJson();
return $customers;
With this I can only get all customers, can I modify this to get also their orders?
I think I could do it with join or is there any magic function?
Thanks
You can use relationship: follow the link and create one to many relationship and use the relationship in your query.
http://laravel.com/docs/eloquent#relationships
$customers = Customer::with('orders')
->where('first_name', 'LIKE', '%'.$name.'%')
->orWhere('last_name', 'LIKE', '%'.$name.'%')
->where('user_id', Auth::user()->id)
->get();
return $customers->toJson();