Get relationships across multiple fields - laravel

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

Related

Laravel query builder: group relations and count total amount

I'm using Laravel 9 and want to create chart for user-role dependency and I need count amount of users with specific role
This is my tables (for example)
// users
| id | name |
| --- | --- |
| 1 | John Doe |
| 2 | Not John Doe |
// roles
| id | slug |
| --- | ----- |
| 1 | admin |
| 2 | ga |
// role_users
| user_id | role_id |
| ------- | ------- |
| 1 | 1 |
| 2 | 1 |
| 2 | 2 |
I want to count users with admin role
User::whereHas('roles', fn ($query) => $query->whereSlug(Role::ADMIN()))->count()
It works, I get correct number but I need to do same query for another roles so this is where things become ugly. I want to avoid doing this
$a = User::whereHas('roles', fn ($query) => $query->whereSlug(Role::ADMIN()))->count(); // 2
$b = User::whereHas('roles', fn ($query) => $query->whereSlug(Role::MODERATOR()))->count(); // 10
$c = User::whereHas('roles', fn ($query) => $query->whereSlug(Role::GA()))->count(); // 12
$d = User::whereHas('roles', fn ($query) => $query->whereSlug(Role::CA()))->count(); // 85
At the end I need to get an array of numbers like [2, 10, 12, 85]. How can I do it using Laravel queries?
Was able to achieve similar with
$users_count = DB::table('role_users')
->select(DB::raw('count(*) as users_count, role_id'))
->groupBy('role_id')
->get()
->mapWithKeys(fn($item, $key) => [$item->role_id => $item->users_count])
->toArray();
Now I can access count array with array_values($users_count)

How Products is order by relation in Laravel?

How can I sort the products in table1 according to their connection with table2 i.e. sort the products in table1 by example_relation in table2?
Table1
| id | product |
|----|---------|
| 1 | pro1 |
| 2 | pro2 |
| 3 | pro3 |
| 4 | pro4 |
| 5 | pro5 |
Table2
| id | example_relation | product_id |
|----|------------------|------------|
| 1 | 700 | 1 |
| 2 | 800 | 2 |
| 3 | 900 | 3 |
| 4 | 850 | 2 |
| 5 | 600 | 4 |
| 6 | 125 | 5 |
Table1 model page:
public $belongsTo = [
'pro_relation' => [
'models\Model',
'key' => 'id',
'otherKey' => 'product_id',
],
Sorting section that needs to be arranged correctly:
$query->whereHas('pro_relation', function($q) use ($postFrom,$postTo){
$q->select('example_relation END AS expose');
})->orderBy("expose", DESC);
Okay, when you want to order the result of one table from another table then you can use orderBy() inside a closure of the relationship to another table.
So from your query, you can add orderBy() like so.
$query->whereHas('pro_relation', function($q) use ($postFrom,$postTo){
$q->select('example_relation END AS expose')
->orderBy('example_relation');
});
This is work
$query->join('table2', 'table1.id', '=', 'table2.yacht_id')
->orderBy(example_relation DESC);

Laravel - Get Data from Table where clause in other table

I have this following 2 tables:
Table: Products
+----+---------+-------------+
| id | fn_id | created_at |
+----+---------+-------------+
| 1 | 4 | SOME TIME |
| 2 | 5 | SOME TIME |
| 3 | 6 | SOME TIME |
| 4 | 10 | SOME TIME |
| 5 | 10 | SOME TIME |
+----+---------+-------------+
Table Fn
+----+---------+-------------+
| id | fn_id | created_at |
+----+---------+-------------+
| 1 | 10 | SOME TIME |
| 2 | 11 | SOME TIME |
| 3 | 12 | SOME TIME |
| 4 | 14 | SOME TIME |
+----+---------+-------------+
And a User Input which is giving me a timestamp ($user_timestamp).
Now I need to get all produtcs, where
products.fn_id is 10
fn.fn_id is 10
fn.created == $user_timestamp
The products model has this relation:
public function fn() {
return $this->hasMany('App\FN', 'fn_id', 'fn_id');
}
Now I've tried multiple things like a where query where I want to check if the fn_id on both are "10" and the created_at value of the fn table is equal to $user_timestamp.
However, I wasn't able to do it.
$products = Products::with('fn')->where('fn.fn_id', function ($query) use ($user_timestamp) {
$query->where([['fn_id', 10],['created_at', $user_timestamp]]);
})->get();
You would have to use whereHas to constrain Products based on fn.
$products = Products::with('fn')->whereHas('fn', function($q) use($user_timestamp){
$q->where('fn_id', 10)->where('created_at', $user_timestamp);
})->get();
try this
$id_to_search=10;
$products = Products::with('fn')->where('fbn_id',$id_to_search)->whereHas('fn', function($q) use($user_timestamp,$id_to_search){
$q->where('fn_id', $id_to_search)->where('created_at', $user_timestamp);
})->get();

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

Yii2 AR left join with where and relations

Book
----------------------------
| id | name | published |
----------------------------
| 1 | book1 | 1 |
| 2 | book2 | 1 |
| 3 | book3 | 0 |
Chapter
----------------------------
| id | book_id | name | published |
----------------------------
| 1 | 1 | chapter1 | 1 |
| 2 | 1 | chapter2 | 0 |
| 2 | 2 | chapter1 | 0 |
| 3 | 3 | chapter1 | 1 |
class Book{
public function getChapter()
{
return $this->hasMany(Chapter::className(), ['kook_id' => 'id']);
} }
class Chapter{
public function getBook()
{
return $this->hasOne(Book::className(), ['id' => 'book_id']);
} }
How can i get published books with published pages using ActiveRecord (i want get book1 with chapter1 and book2 without any chapters)?
smth like Book::find($id)->where(['published' => 1])-> {{{left join with where}}} ->all())
ADDED
And then i wand to use it
echo $book->name;
foreach($book->getChapter() as chapter){
echo chapter->name;
}
Change your Book class relation as
class Book
{
public function getChapter()
{
return $this->hasMany(Chapter::className(), ['book_id' => 'id'])->where(['published' => 1]);
}
}
To get Related Records use with()
Book::find()->with(['chapter'])->where(['id' => $id ,'published' => 1])->all()
To Use it:
//Book Name
echo $book->name;
//For Chapters Name
if($book->chapter){
foreach($book->chapter as $chapter){
echo $chapter->name;
}
}

Resources