Laravel = Parent - Child On The Same Table - laravel

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.

Related

Get relationships across multiple fields

How can I get relationship records across multiple fields
Following the example below, I want to return a category with id 2 only if all the conditions are met, namely option [1, 5, 8] with active = 1
Please help me, I searched through a lot of information and did not find a solution
`$options = [1, 5, 8];
$categories = Category::whereHas('products', function ($query) use ($options){
$query->where(....);
})->get();`
`
```
My Model Category
```
`class Category extends Model
{
public function products()
{
return $this->hasMany(Product::class, "category_id");
}
}`
```
Table products
| id | category_id | active | option |
| -------- | ----------- | ------ | ------ |
| 1 | 2 | 1 | 1 |
| 2 | 13 | 1 | 2 |
| 3 | 28 | 0 | 3 |
| 4 | 2 | 1 | 5 |
| 5 | 2 | 1 | 8 |
```
$options = [1, 5, 8];
$categories = Category::whereHas('products', function ($query) use ($options){
$query->whereIn('option',$options)->where('active',1);
})->get();

Laravel Eloquent Query using Where, With, Where and orWhere condition

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();

Laravel eloquent whereHas where first date equals a specific date

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
});

Laravel: Query the models where the relationship is greater than 0

I'm doing a Laravel query to query a list of elements that his relationship is grater than 0.
The table concerts:
| ID | NAME |
|----|-----------|
| 1 | Concert A |
| 2 | Concert B |
| 3 | Concert C |
And the Position table.
| ID | concert_id | user_id | Content |
|----|----------------|------------|----------|
| 1 | 1 | 1 | xxx |
| 2 | 1 | 2 | yyy |
| 3 | 3 | 1 | zzz |
| 4 | 3 | 2 | www |
| 5 | 1 | 3 | xyx |
| 6 | 3 | 3 | rer |
The query that I need to do is, get the concerts where their position has in the content a value like $some_query$.
The code I've is the following:
$result = $this->model->whereHas('positions')
->with(['positions' => function ($query) {
$query->where('content', 'like', "%{$content}%");
}])->get();
But as far as I can tell, this will bring all the concerts, and also this is going to bring only the positions that has the desired content.
So I've two problems, the first one is I need to get the concerts that his queried positions are greather than 0.
And the second one is that also I need to bring all the positions, not only the queried ones.
Basically the query is just a way to know which concerts I need to bring.
Is there possible to achieve this on a single query?
You'll have to move your query to the whereHas.
If I understood well, this is what you want:
$result = $this->model
// Take the Concerts that has positions with a similar content
->whereHas('positions', function ($query) use ($content) {
$query->where('content', 'like', "%{$content}%");
})
// Take (all) the Positions of these concerts
->with('positions')
->get();

How to whereHas when use belongsToMany relation

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.

Resources