I am trying to make a Laravel Eloquent query which will find me orders by order number and product name.
I have 3 tables orders, order_details & products.
orders table
id | user_id | order_id | order_cart_id
---------------------------------------------------------
1 | 1 | 123-456-7890 | 1
2 | 1 | 789-456-3210 | 2
order_details table
id | order_id | cart_id | p_id
---------------------------------------------------------
1 | 1 | 1 | 22
2 | 1 | 1 | 42
3 | 1 | 1 | 2
4 | 1 | 1 | 32
5 | 1 | 1 | 423
6 | 2 | 2 | 432
products table
id | p_name
--------------------
1 | ABC
2 | CAD
42 | PRO
22 | XYZ
32 | IND
423 | MP
432 | ETC
Orders Model
public function order_cart_products()
{
return $this->hasManyThrough(\App\Models\Products\Product::class,
\App\Models\Orders\OrderDetail::class,
'cart_id',
'id',
'cart_id','p_id');
}
Order Controller
$orders = Order::where('user_id', auth()->user()->id)
->where('order_id', 'LIKE', '%'.$search.'%')
->with('order_cart_products', function ($query) use ($search) {
$query->orWhere('p_name', 'LIKE', '%'.$search.'%');
})
->get()->toArray();
What I am trying to do is by searching order_id(123-456-7890) I need to get all its details with products in it and if I search via p_name(ABC). I need to get all orders in which ABC has been listed. But I don't understand where am I going wrong am not getting desired output.
Try something like below:
$orders = Order::with('order_cart_products')
->where('user_id',auth()->user()->id)
->where(function ($query) use ($search) {
$query->where('order_id', 'LIKE', '%'.$search.'%')
->orWhereHas('order_cart_products', function ($query) use ($search) {
$query->where('p_name', 'LIKE', '%'.$search.'%')
})
})
->get();
Related
I have two related tables:
projects:
| id | name |
| 1 | Test |
| 2 | Example |
project_dates:
| id | project_id | date |
| 1 | 1 | 2020-02-01 |
| 2 | 1 | 2020-02-10 |
| 3 | 1 | 2020-01-25 |
| 4 | 2 | 2020-01-10 |
| 5 | 2 | 2019-12-15 |
Now for example I would like to get all projects where the first date of project_dates is equal to 2020-01-25. So I tried the following:
$projects = Project::whereHas('dates', function($query) {
$query->whereRaw("MIN(date) = '2020-01-25'");
});
But this returns the following error:
SQLSTATE[HY000]: General error: 1111 Invalid use of group function
which revers to MIN(date). So my question remains how can I get all projects with the first date being equal to 2020-01-25 or any other specific date. From the example above I would expect to get the project with id 1 since the first date of 2 is 2019-12-15
I know that is possible to use a subqueryjoin however I feel like doing 2 queries shouldn't be required.
$firstDates = ProjectDate::groupBy('project_id')
->selectRaw('project_id, MIN(date) as first_date');
Project::joinSub($firstDates, 'first_dates', function($join){
$join->on('first_dates.project_id', '=', 'project.id')
->where('first_date', '=','2020-01-25');
})->get();
You cannot use where aggregate function with groupBy, try to use havingRaw instead:
$projects = Project::whereHas('dates', function($query) {
$query->havingRaw("MIN(date) = ?", ['2020-01-25']);
});
// Or
$projects = Project::whereHas('dates', function($query) {
$query->having(DB::raw("MIN(date)"), '2020-01-25');
});
$projects = Project::whereHas('dates', function($query) {
$query->having(DB::raw("MIN(date)"), '2020-01-25')
->groupBy( 'project_dates.id' ); // For sql_mode=only_full_group_by
});
Currently having trouble of using groupBy in nested relation on laravel. I have 3 Tables and I want to group the result base on the CountryTbl value. Here are the tables.
UserTbl
----------------------------------
id | name | branch_id |
----------------------------------
1 | Joseph | 1 |
2 | Manuel | 1 |
3 | Margaret | 3 |
----------------------------------
BranchTbl
----------------------------------
id | branch_name | country_id |
----------------------------------
1 | Pampanga | 1 |
2 | Manila | 1 |
3 | California | 2 |
----------------------------------
CountryTbl
------------------------
id | country_name |
------------------------
1 | Philippines |
2 | United States |
------------------------
This is my Model
UserModel
public function branch()
{
return $this->belongsTo('App\Branch');
}
BranchModel
public function country()
{
return $this->belongsTo('App\Country');
}
CountryModel
Now, In the table shown above, I want to get all the users and group them by country.
Here is what I've tried.
public function getAllUsers(){
$users = User::with('branch')
->with(['branch.country' => function($q){
return $q->groupBy('country_name');
}])
->get();
return $users;
}
My code doesn't work. It always returns me an error saying:
Syntax Error or Access Violation
Try this:
User::with(['branch', 'branch.country' => function($q) {
return $q->groupBy('CountryTbl.country_name');
}])
or
User::with(['branch', 'branch.country'])
->get()
->groupBy('branch.country.country_name');
You may try the below code
$data = DB::table('country')
->join('branch', 'country_id', '=', 'country.id')
->join('user', 'branch_id', '=', 'branch.id')
->select('country.country_name','user.name','branch.branch_name')
->groupBy('country.country_name')
->orderBy('country.country_name','ASC')
->get();
MAIN TABLE
id | parent_id | form_id | is_approved | fruit_id
------------------------------------------------------
1 | 0 | 1 | 1 | 1
2 | 1 | 2 | 1 | 2
3 | 0 | 1 | 1 | 3
4 | 3 | 2 | 0 | 4
FRUIT TABLE
id | name
------------
1 | cherry
2 | guava
3 | apple
4 | grapes
by referencing on the Main Table, i need to output all fruit names from the Fruit Table for rows that has a:
1.) parent_id != 0
2.) is_approved=1
how to do this? please help!
Assuming you have a fruit model, with a main relation you could do this which would give you a collection of Fruit models meeting your criteria.
$fruits = Fruit::whereHas('main', function ($query) {
$query->where('parent_id', '!=', 0)
->where('is_approved', 1);
})->get();
$fruitNames = DB::table('main')->where([['parent_id', '>=', 1],['is_approved', '=', 1]])->join('fruit_names')->get(['fruit_names.name']);
I made it work!
$fruitNames = main::select('main.id', 'b.name')
->join('fruit_names as b', 'b.id', '=', 'main.fruit_id')
->join('main as c', 'c.id', '=', 'main.parent_id')
->where('main.parent_id', '!=', 0)
->where('c.is_approved', 1)
->get();
I wonder if this query can be improved.
I got a problem, When try to use whereHas in this case
Table users.
----------------
| id | name |
----------------
| 1 | AAA |
| 2 | BBB |
| 3 | CCC |
----------------
Table subjects.
------------------
| id | title |
------------------
| 1 | Subject 1 |
| 2 | Subject 2 |
------------------
Table subject_user.
------------------------
| user_id | subject_id |
------------------------
| 1 | 1 |
| 2 | 1 |
| 1 | 2 |
| 3 | 2 |
------------------------
in Subject Model
...
public function User()
{
return $this->belongsToMany(User::class, 'subject_user');
}
...
When I want to find subject by user_id with this query.
In this case Auth::id() == 1 and $request->user_id == 3
$subject = Subject::whereHas('User', function ($query) use ($request) {
$query->whereIn('user_id', [Auth::id(), $request->user_id]);
})->get();
With this query, I got subjects 1 and 2. That was a wrong result. That must got only subject 2.
Then I try this.
$subject = Subject::whereHas('User', function ($query) use ($request) {
$query->where('user_id', Auth::id())->where('user_id', $request->user_id);
})->get();
It would not get any subjects.
What query do I use in this case to get only subject 2.
#Lloople from your answer, I got an idea.
$subject = Auth::user()->Subject()->whereHas('User', function ($query) use ($request) {
$query->where('user_id', $request->id);
})->first();
Why not doing it backwards? You already have the logged in user, so if you define the relationship in the User model you can do
$subjects = auth()->user()->subjects;
Anyway, you don't need to check double the Auth::id()and $request->user_id. In fact, I'm not sure you can do this last one.
Edit after comments
$subjects = Subject::whereBetween(auth()->user()->id, $request->user_id)->get();
You will need to change the order from the inputs, in case $request->user_id is less than auth()->user()->idor it wouldn't work.
messages Table
+----+----------+
| id | text |
+----+----------+
| 1 | message1 |
| 2 | message2 |
+----+----------+
tags table
+----+-----------+
| id | name |
+----+-----------+
| 1 | valentine |
| 2 | funny |
| 3 | santa |
+----+-----------+
message_tag
+----+------------+--------+
| id | message_id | tag_id |
+----+------------+--------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 2 | 2 |
+----+------------+--------+
I have written this query so far to get all messages but i cant return the
message where tag_id = 1;
Message::with([
'tags'=>function($q){
$q->select("name","tag_id");
}
])->select("id", "text")->paginate(10);
i have used where clause inside function($q){$q->where('tag_id',1)}. but it didn't worked.
You have to include use Illuminate\Support\Facades\DB; at the top of class
$tagId = 1;
$return = DB::table('message_tag')
->join('messages', 'messages.id', '=', 'message_tag.message_id')
->join('tags', 'tags.id', '=', 'message_tag.tag_id')
->where("message_tag.tag_id", "=", $tagId)
->select('messages.text', 'tags.text')
->get();
Try using whereHas(), assuming you set a many-to-many relationship properly:
$tag = 'Madhab452';
$messages = Message::whereHas('tags', function ($query) use ($tag) {
$query->where('name', '=', $tag)
->select('name', 'tag_id');
})->get();