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();
Related
Explaining my problem, I have two tables in my database called order and order_details.
On my dashboard, I display the three best-selling items (currently work!). However, I would like to display only the best selling items THAT have the status = delivered.
Today, it works like this:
$top_sell_items = OrderDetails::with(['product'])
->select('product_id', DB::raw('SUM(quantity) as count'))
->groupBy('product_id')
->orderBy("count", 'desc')
->take(3)
->get();
The problem is that the order status is stored in another table, called orders, column order_status.
How can I create this rule and include it in my $top_sell_items?
if you relationship is done between this table already, you can use this code, if not you have to go to the OrderDetails Model and add new method orders
$top_sell_items = OrderDetails::with(['product', 'orders'])
->whereHas('orders', function($query) {
$query->where('status', 'delivered');
})
->select('product_id', DB::raw('SUM(quantity) as count'))
->groupBy('product_id')
->orderBy('count', 'desc')
->take(3)
->get();
You could either define a relationship between Orders and OrderDetails or use a join like so...
<?php
$top_sell_items = OrderDetails::with(['product'])
->join('orders', 'orders.id', '=', 'order_details.order_id')
->select('product_id', DB::raw('SUM(quantity) as count'))
->where('orders.order_status', 'delivered');
->groupBy('product_id')
->orderBy("count", 'desc')
->take(3)
->get();
More info here: https://laravel.com/docs/8.x/queries#joins
Depending if you desire this, the following solution might be the most efficient:
$products = Product
::whereHas('orderDetails.order', function ($query) {
$query->where('orders.order_status', 'delivered');
})
->withSum('orderDetails', 'quantity')
->orderBy('order_details_sum_quantity', 'desc')
->take(3)
->get();
It will directly return instances of Product. In addition it puts everything in a single query instead of the two that with produces.
I have two table (users and messages) .. I wrote a query to get all messages that users sent to me or I sent, using JOIN .. to get all the users I have contacted or they did.
as in the code below:
$users = Message::join('users', function ($join) {
$join->on('messages.sender_id', '=', 'users.id')
->orOn('messages.receiver_id', '=', 'users.id');
})
->where(function ($q) {
$q->where('messages.sender_id', Auth::user()->id)
->orWhere('messages.receiver_id', Auth::user()->id);
})
->orderBy('messages.created', 'desc')
->groupBy('users.id')
->paginate();
The problem here is when records grouped, I'm getting the old message not the new one according to its created_at .. So, I want to get the last record of the grouped records.
It seems like it would make more sense to make use of Eloquent's relationships here so that you can eager load the relationships instead of having to use join and group by:
$messages = Message::with('sender', 'receiver')
->where(function ($query) {
$query->where('sender_id', auth()->id())
->orWhere('receiver_id', auth()->id())
})
->orderByDesc('created') // is this meant to be 'created_at'?
->paginate();
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();