How can I join with Eloquent: Relationships? - php

My query is like this :
<?php
public function getListReviews()
{
$reviews = Review::where('user_id', auth()->user()->id)
->get();
return $reviews;
}
From the query, it can get all review data by id
I want get user photo, store photo and product photo
I want get it use Eloquent: Relationships
How can I get it with Eloquent: Relationships?
My review model is like this :
<?php
namespace App;
use Jenssegers\Mongodb\Eloquent\Model as Eloquent;
use Jenssegers\Mongodb\Eloquent\HybridRelations;
class Review extends Eloquent
{
use HybridRelations;
protected $connection = 'mongodb';
protected $fillable = ['user_id', 'user_name', 'product_id', 'product_name', 'store_id', 'store_name', 'invoice_number', 'rating', 'comments', 'created_at', 'updated_at'];
public function user()
{
return $this->belongsTo(User::class);
}
}
My user model is like this :
<?php
namespace App;
...
class User extends Authenticatable
{
...
protected $fillable = ['name', 'email', 'password', 'birth_date', 'mobile_number', 'photo'];
public function store()
{
return $this->hasOne(Store::class);
}
}
My store model is like this :
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Store extends Model
{
protected $fillable = ['user_id', 'name', 'address', 'phones', 'total_product', 'photo'];
public function products()
{
return $this->hasMany(Product::class);
}
}
My product model is like this :
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
protected $fillable = ['store_id','category_id','name', 'photo','description'];
public function store()
{
return $this->belongsTo(Store::class);
}
}

If you want to find out product and store from review model then add two more methods to Review model as below.
Edit App\Review.php
//You already have key to to find store i.e. store_id
public function store()
{
return $this->belongsTo(Store::class);
}
//You already have key to to find product i.e. product_id
public function product()
{
return $this->belongsTo(Product::class);
}
then execute your query as below
$reviews = Review::where('user_id', auth()->user()->id)
->with('store')
->with('product')
->with('user')
->get();
and you can access them as below,
Iterate through $reviews object as $review
$review->store->photo;
$review->product->photo;
$review->user->photo;

Related

Is there a way to make this query without raw part, between realtion models?

User Model:
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* #var string[]
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* #var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function venues()
{
return $this->hasMany(Venue::class);
}
public function reviews()
{
return $this->hasMany(Review::class);
}
public function profile()
{
return $this->hasOne(Profile::class);
}
public function approvedVenues()
{
return $this->hasMany(Venue::class)->where('is_approved', '=', 1);
}
public function unapprovedVenues()
{
return $this->hasMany(Venue::class)->where('is_approved', false);
}
public function ownVenuesReviews()
{
return $this->reviews()->whereIn('user_id', function($query) {
$query->select('id')
->from('venues')
->whereRaw('venues.user_id = users.id');
})->get();
}
}
Venue Model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Venue extends Model
{
use HasFactory;
protected $fillable = [
'user_id',
'city_id',
'category_id',
'title',
'address',
'phone',
'email',
'website',
'facebook',
'instagram',
'content_bg',
'content_en',
'cover_image',
'lat',
'lng'
];
public function user()
{
return $this->belongsTo(User::class, 'user_id');
}
public function category()
{
return $this->belongsTo(Category::class, 'category_id');
}
public function city()
{
return $this->belongsTo(City::class, 'city_id');
}
public function features()
{
return $this->belongsToMany(Feature::class, 'venue_feature');
}
public function images()
{
return $this->hasMany(VenueImage::class);
}
public function reviews()
{
return $this->hasMany(Review::class);
}
}
Review Model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Review extends Model
{
use HasFactory;
protected $fillable = ['rating', 'content', 'venue_id', 'user_id'];
public function venue()
{
return $this->belongsTo(Venue::class);
}
public function images()
{
return $this->hasMany(ReviewImage::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
So Users have many Venues, Venues have many reviews.
I want to get reviews on own Venues for example (If I own venues with id 100, 101 - I want to get all reviews for these two venues)
Raw query is this:
SELECT * FROM `reviews` WHERE reviews.venue_id IN (SELECT venues.id FROM venues WHERE venues.user_id = 1)
What I tried in Laravel in User model (doesn't work), I'm also curious if there is a way, without raw part:
public function ownVenuesReviews()
{
return $this->reviews()->whereIn('user_id', function($query) {
$query->select('id')
->from('venues')
->whereRaw('venues.user_id = users.id');
})->get();
}
A HasManyThrough relationship should work, if I'm understanding your model relationships properly:
public function ownVenueReviews(): HasManyThrough
{
return $this->hasManyThrough(Review::class, Venue::class);
}
The raw part is only needed because you have to include the foreign key in the select portion of the sub query. Even though you may not want the user_id in the query result it must still be selected for Laravel to be able to make the relationship match work.
public function ownVenuesReviews()
{
return $this->reviews()->whereIn('user_id', function($query) {
$query->select('id', 'user_id')
->from('venues');
})->get();
}
I did it like this, but I'm not quite sure, that this is the best way, I'm open to suggestions:
public function ownVenuesReviews()
{
return Review::whereIn('venue_id', function($query) {
$query->select('id')
->from('venues')
->where('user_id', $this->id);
})->get();
}

how to remove children data in case many to many relationship in laravel by using observer?

there is a (card model) bleongsToMany contacts, and there is a (contact model) is bleongsToMany cards, I want when (card) get updated his children in the middle table in the relation became removed.
I'm trying to do this by using (the observer), I did all steps correctly but the issue is:
when (card model) updated his children still exist in the middle table of the relationship, I want to remove them when any update on the card.
Route:
Route::get('/test',function(){
$card = \App\Models\Card::find(1);
$card-> update([
'name' => 'firstCard1',
'user_name' =>1,
]);
return true;
});
Observer:
<?php
namespace App\Observers;
use App\Models\Card;
class CardObserver
{
public function updated(Card $card)
{
$card -> contact()-> delete();
}
}
Card Model:
<?php
namespace App\Models;
use App\Observers\CardObserver;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Card extends Model
{
use HasFactory;
protected $fillable = [
'name',
'user_id ',
];
public $timestamps = true;
protected $hidden = ['pivot'];
public function contact()
{
return $this->belongsToMany(Contact::class, 'card_contacts', 'card_id');
}
public function connection()
{
return $this->belongsTo(Connection::class, '');
}
protected static function boot()
{
parent::boot();
Card::observe(CardObserver::class);
}
}
Contact Model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Contact extends Model
{
use HasFactory;
protected $fillable = [
'provider_id',
'user_id',
'contact_string'
];
public $timestamps = true;
protected $hidden = ['pivot'];
public function card(){
return $this->belongsToMany(Card::class,'card_contacts','contact_id');
}
public function user(){
return $this->belongsTo(User::class,'user_id');
}
public function provider(){
return $this->belongsTo(Provider::class,'provider_id');
}
}
Card_contact Model (the pivot table):
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class CardContact extends Model
{
use HasFactory;
protected $fillable = [
'card_id',
'contact_id',
];
public $timestamps = true;
}
any help please?

Laravel filter max date on intermediate pivot table

I have a relationship many to many (between Invoice and Shift) as defined
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Invoice extends Model
{
public $primaryKey = 'id';
protected $fillable = [
'user_id',
'date_ins',
'tas',
];
public function user()
{
return $this->hasOne(User::class,'id','user_id');
}
/**
* The roles that belong to the invoice.
*/
public function shifts()
{
return $this->belongsToMany(Shift::class, 'invoice_shift')
->withPivot(['invoice_id','shift_id', 'shift_taken_id', 'shift_swapped_date','shift_taken_date', 'tas','msg','status_tas']);
}
}
Then Shift model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Shift extends Model
{
public $primaryKey = 'id';
protected $fillable = [
'code',
'description',
];
/**
* The users that belong to the role.
*/
public function invoices()
{
return $this->belongsToMany(Invoice::class, 'invoice_shift');
}
}
in the pivot table i have also a column called shift_swapped_date,
I wanted just to retrieve for all invoices the one row that has max value of this date in pivot table.
I tried in the controller
$invoices = Invoice::with('shifts')
->get();
$invoices->max('pivot.shift_swapped_date');
but it doesn't work
I cannot figure out how to do it...
Thx
If that is not working try to run below solution:
$invoices = Invoice::with(['shifts' => function($query) {
$query->max('shift_swapped_date');
}])->get();

Laravel Eloquent - One to Many - Can't join

I'm using laravel 5.4, have two models ParentAccount and ChildAccount,
A parent has many childs
Parent
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class ParentAccount extends Model
{
//
public $timestamps = false;
protected $table = 'parent_accounts';
protected $fillable = [
'name', 'account_id'
];
public function childs()
{
return $this->hasMany('App\ChildAccount','account_id', 'parent_id');
}
}
child
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class ChildAccount extends Model
{
//
public $timestamps = false;
protected $table = 'child_accounts';
protected $fillable = [
'name', 'account_id','parent_id'
];
}
When i use echo ParentAccount::find(1)->childs();
i get an error Call to a member function childs() on null although all parents have children
Note: child has parent_id where it's the account_id in the parent
in parent model
public function childs(){
return $this->hasMany(ChildAccount::class, 'parent_id' , 'account_id');
}
in child model
public function parent(){
return $this->belongsTo(ParentAccount::class, 'parent_id' , 'account_id');
Edited Code
public function childs()
{
return $this->hasMany('App\ChildAccount', 'parent_id','account_id');
}
The relation function must be in the format
public function post()
{
return $this->belongsTo('App\Post', 'foreign_key', 'other_key');
}
First you have to add the primaryKey property then change the relation parameters and add the revers relation to the ChildAccount :
ParentAccount :
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class ParentAccount extends Model
{
protected $primaryKey = 'account_id';
public $timestamps = false;
protected $table = 'parent_accounts';
protected $fillable = [
'name', 'account_id'
];
public function childs()
{
// 'foreign_key', 'local_key'
return $this->hasMany('App\ChildAccount', 'parent_id', 'account_id');
}
}
ChildAccount :
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class ChildAccount extends Model
{
protected $primaryKey = 'account_id';
public $timestamps = false;
protected $table = 'child_accounts';
protected $fillable = [
'name', 'account_id','parent_id'
];
public function parent() {
// foreign_key, 'other_key'
return $this->belongsTo('App\ParentAccount', 'parent_id', 'account_id');
}
}
With doing that you can get the childs :
ParentAccount::find(1)->childs;
You got Call to a member function childs() on null because ParentAccount::find(1) return null. Make sure you have ParentAccount with id=1 in your DB.
You need to change keys order like this:
public function childs()
{
return $this->hasMany('App\ChildAccount', 'parent_id', 'account_id');
}

belongsTo() not returning relationships for User

I already tried several things but I can't get this to work. I want to be able to make something like this {{ $user->city->name }}
My user model:
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
public $timestamps = false;
protected $table = 'users';
protected $fillable = ['id_city', 'name', 'email', 'password', 'admin'];
protected $hidden = ['password', 'remember_token'];
public function city()
{
return $this->belongsTo('App\City');
}
}
And this is my City model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class City extends Model
{
public $timestamps = false;
protected $table = 'cities';
protected $fillable = ['name', 'slug'];
public function users(){
return $this->hasMany('App\User');
}
}
And I'm trying to use {{ $user->city->name }} on my view but it doesn't work, it returns an error ErrorException: Trying to get property of non-object (View: .../views/app/text.blade.php).
What should I do?
Within your belongsTo relationship, Eloquent tries to match city_id as the foreign key by default as you don't pass the second argument.
However, according to your fillable attributes, what you have as the foreign key is actually id_city.
For the User model,
public function city()
{
return $this->belongsTo('App\City', 'id_city');
}
For the City model,
public function users(){
return $this->hasMany('App\User', 'id_city', 'id');
}

Categories