Laravel Eloquent: whereHas on relationship involving multiple tables - laravel

I am working on a Laravel project. I am using Eloquent to query data from the database.
I have the following models
Donation.php
class Donation extends Model
{
public function donator()
{
return $this->belongsTo(User::class);
}
}
User.php
class User extends Model
{
public function charities()
{
return $this->belongsToMany(Charity::class);
}
}
Charity.php
class Charity extends Model
{
public function donators()
{
return $this->belongsToMany(User::class);
}
}
I am writing a query on Donation model class and I am trying to query something like this. The query is just abstraction.
Donation::whereHas('donator.charities', function($query) {
$query->whereIn('charities.id', [ 1,2,3,4 ])
})
As you can see in the whereHas, I am applying the where clause on charities of donator. Is it possible to do that? How can I do that?

I hope this would be the answer of your question.
Donation::whereHas('donator',function($query){
$query->whereHas('charities',function($query){
$query->whereIn('id',[1,2,3,4]);
})
})->get();

Related

Many to Many Get All Distinct Values From a Related Model

I have an Article model with many-to-many relation with the Tag model
The Article model
class Article extends Model
{
public function tags()
{
return $this->belongsToMany(Tag::class);
}
}
The Tag model
class Tag extends Model
{
public function articles()
{
return $this->belongsToMany(Article::class);
}
}
What I want is to get all the unique tags that have a relation with at least one (or more) article in the articles table. I want to retrieve it through a static method in the Article model like below
public static function allTags()
{
// return static:: all the tags
}
How can I do this? Thanks in advance.
EDIT: this is how I solved it. Appreciate the help!
public static function allTags()
{
return Tag::query()->whereHas('articles', function($query) {
$query->where('status', '<>', 'draft');
})->pluck('tag', 'id');
}
Using whereHas()
$tags = Tag::query()->whereHas('articles')->get();

How I can make the same SQL query whith the halp of Eloqument ORM methods and models

I have followng database:
And database diagramm is on next picture. Simply speaking, Users have many shops, Shops have many products etc.
In need to select all products from all shops of particular user. In my Controller it's look like so:
But it's does't work (
Instade of this I try to write direct SQL
I just need to make following request by Eloqument methods
SELECT * FROM tmp.products
WHERE tmp.products.shop_id IN
(SELECT id FROM shops where user_id = 1);
with dynamics parametrs of course.
You could get all products by using whereHas filter like
$products = Product::whereHas('shop.user', function ($query) use($request) {
$query->where('id', '=', $request->user()->id);
})->get();
I assume you have defined proper mappings in your models like
class Product extends Model {
public function shop() {
return $this->belongsTo('Shop', 'shop_id');
}
}
class Shop extends Model {
public function user() {
return $this->belongsTo('User', 'user_id');
}
public function products() {
return $this->hasMany('Product', 'shop_id');
}
}
class User extends Model {
public function shops() {
return $this->hasMany('Shop', 'user_id');
}
}

Laravel Eloquent - Get all records of child relation model

My data model is this:
Users > Offices > Organization
This is my model
class Organization extends Model {
protected $table = 'organizations';
public function offices()
{
return $this->hasMany('App\Models\Office');
}
public function users()
{
return $this->offices()->users();
}
....
So.. I want to get all users from an organization (of all the offices).
But I don't know how to do something like
$this->offices()->users();
(Avoiding user a manual collection or map to do that)
Thanks!
So, you have organization ID. You can load all users by using whereHas():
$users = User::whereHas('office', function ($q) use ($organizationId) {
$q->where('organization_id', $organizationId);
})
->get();
Make sure office() relationship is defined correctly in User model:
public function office()
{
return $this->belongsTo('App\Office');
}
Alternatively, you could define hasManyThrough() relationship:
public function users()
{
return $this->hasManyThrough('App\Office', 'App\User');
}
And use it:
$organization->users()

Laravel Sum of relation

I want to return the sum of "amount" from my payments table. There can be many payments for one invoice. The below "->sum('amount') does not work, it returns:
Call to a member function addEagerConstraints() on a non-object.
How to return the sum of all payments for each invoice in my relation?
Invoices Model:
class Invoices extends Eloquent {
public function payments()
{
return $this->hasMany('Payments')->sum('amount');
}
}
Expenses Model:
class Payments extends Eloquent {
public function invoices()
{
return $this->belongsTo('Invoices');
}
}
My table "payments" holds the foreign key of my tables invoices, which is invoices_id.
Starting by Laravel 8 you can simply use withSum() function.
use App\Models\Post;
$posts = Post::withSum('comments', 'votes')->get();
foreach ($posts as $post) {
echo $post->comments_sum_votes;
}
https://laravel.com/docs/8.x/eloquent-relationships#other-aggregate-functions
class Invoices extends Eloquent {
public function payments()
{
return $this->hasMany('Payments');
}
}
class Payments extends Eloquent {
public function invoices()
{
return $this->belongsTo('Invoices');
}
}
In your controller
Invoice::with(['payments' => function($query){
$query->sum('amount');
}])->get();
;
You can show this package
$invoices = Invoices::withSum('payments:amount')->get();
First decide which Invoice (for example id 1)
$invoice = Invoices::find(1);
Then eager load all the corresponding payments
$eagerload = $invoice->payments;
Finally assuming you have the amount field in your Invoice model you can simply find the sum using the method below:
$totalsum = $eagerload->sum('amount');
This is also possible. we can do by model itself.
class Invoices extends Eloquent {
public function payments()
{
return $this->hasMany('Payments')
->selectRaw('SUM(payments.amount) as payment_amount')
->groupBy('id'); // as per our requirements.
}
}
}
Note
SUM(payments.amount)
payments is tableName
amount is fieldName
I found a simple way to acomplish this in here, you can use withPivot() method.
You can redefine a bit your relation to something like following
public function expenses()
{
return $this->belongsToMany('Expenses', 'invoices_expenses')
->withPivot('name', 'amount', 'date');
}

Laravel query multiple tables using eloquent

hi sorry bit of a newbie here but I am have three tables users, profiles, friends. they all have the user_id fields within them and I want fetch all of the fields in one statement using Eloquent and not DB::statement and doing the table joins.
How can I achieve this?
Try this
use the User class and the with method that laravel has to query model relationships
$user = User::with(['profile', 'friend'])->get();
Ensure your models has the correct relationships as follows:
app/models/User.php
public function friend () {
return $this->hasMany('Friend');
}
public function profile () {
return $this->hasOne('Profile');
}
app/models/Profile.php
public function user() {
return $this->belongsTo('User');
}
app/models/Friend.php
public function user() {
return $this->belongsTo('User');
}
use some thing like this:
You should define relations in your models with hasOne, hasMany.
class Review extends Eloquent {
public function relatedGallery()
{
$this->hasOne('Gallery', 'foreign_id', 'local_id');
}
}
class Gallery extends Eloquent {
public function relatedReviews()
{
$this->hasMany('Review', 'foreign_id', 'local_id');
}
}
$gallery = Gallery::with('relatedReviews')->find($id);
Will bring the object Gallery with
$gallery->id
gallery->name
...
$gallery->relatedReviews // array containing the related Review Objects

Resources