I have defined attribute in model which gets data from another table, but I haven't defined a relation between those two tables:
LeaseRequest model
public function getSecurityDepositEntryAttribute() {
return Rent::where([
['property_id', $this->property_id],
['lease_request_id', $this->id],
['type', 'security_deposit_migration'],
])->orderBy('created_at', 'asc')->first();
}
Can I now filter LeaseRequest table using this attribute? I have tried this, but getting BadMethodCallException:
LeaseRequest::whereHas('security_deposit_entry', function($query) {
$query->whereColumnNotIn('status', ['refund_in_process', 'refunded']);
})->get();
If this is not possible, can I define relationship between those two tables with predefined where clauses like in attribute?
No not possible you have to use relations and to use compoships lib:
public function rent() {
return $this->hasOne(Rent::class,['lease_request_id','property_id'],['id','property_id'])
->where('type', 'security_deposit_migration')
->orderBy('created_at', 'asc');
}
['lease_request_id','property_id'] are the foriegn keys
['id','property_id'] are the local keys
then you can use whereHas
Related
i want to use scope method inside join subquery so is there any way I can do that in laravel?
Post Model
public function scopePublished($query)
{
return $query->where('published',true);
}
Now I want to join user table with post table but in join I want to use this scope method directly but its giving me error.
Users::join('posts',function($q){
$q->on('posts.user_id','users.id');
$q->published();
})->get();
So is there any way I can use scope directly inside join subquery ?
First, you need to add the relation between posts and users to the User model like so:
User Model
public function posts()
{
return $this->hasMany(Post::class);
}
and then your scope stays as it is, and your query if you wanna get users with their published posts:
return User::with(['posts' => function ($query) {
$query->published();
}])
->get();
and if you want to get only users that have published posts:
return User::whereHas('posts', function ($query) {
$query->published();
})
->get();
Note that while with('posts') will include the related table's data in the returned collection, whereHas('posts') will not include the related table's data.
Hence sometimes you may need to call both together, I mean, only with('posts') will eager load relations (in this case posts).
I have an issue where a profile can have many campaigns and also many locations.
The campaigns are linked via a pivot table but my goal is just to return all of the location ids.
Profile:
public function campaigns() {
return $this->hasMany('App\Models\Campaign', 'profile_id', 'id');
}
Campaign:
public function locations() {
return $this->belongsToMany('App\Models\Location')->withPivot('campaign_id', 'location_id');
}
Currently I am solving this by doing
$campaigns = $profile->campaigns;
[Doing a nested foreach loop and placing each ID into the array]
How would I get this via a query?
I've tried
$campaigns = $profile->campaigns()
->with('locations')
->get()
->pluck('location.id');
Well, your goal is to get information from the location, so I'd start your query with that. You can condition your query based on the relationships using the whereHas() method.
This assumes your Location has the campaigns relationship defined, and your Campaign has the profile relationship defined.
$ids = Location::whereHas('campaigns.profile', function ($query) use ($profile) {
return $query->where('id', $profile->id);
})->pluck('id');
You can read more about querying by relationships in the documentation here.
I'm trying to do where clause for fortune_code inside joindraw table, comparing with the lucky_fortune_code from product table. How can i access and do the check?
Product::where('status', StatusConstant::PT_ENDED_PUBLISHED)
->where('lucky_fortune_code', '<>', '')
->with(['joindraw' => function ($query){
$query->where('fortune_code', $this->lucky_fortune_code)
->with('user');}])->desc()->get();
Product.php
class Product extends Model
{
public function joindraw(){
return $this->hasMany('App\Models\Joindraw');
}
Joindraw.php
class Joindraw extends Model
{
public function product(){
return $this->belongsTo('App\Models\Product', 'product_id');
}
What you can do is a join:
Product::where('status', StatusConstant::PT_ENDED_PUBLISHED)
->where('lucky_fortune_code', '!=', '')
->join('joindraws', 'joindraws.fortune_code', '=', 'products.lucky_fortune_code')->get();
By the way, you can also omit the second 'product_id' parameter in the belongsTo() relation, as this column name is already assumed by convention.
Also, there is no desc() method on the query builder. Use orderBy('lucky_fortune_code', 'desc') instead.
However, whenever you have to write joins in Laravel, you should think about your relationship structure, because there's probably something wrong.
I have the following query:
$objects = Object::with("prototypes");
As you can see I do request to model Object and join it with prototypes.
The prototypes table has structure:
prototype_id
name
How to make where in above query like as:
$objects = Object::with("prototypes")->where("prototype_id", 3);
Object model:
public function prototypes()
{
return $this->belongsToMany('App\Prototype', 'object_prototype', 'object_id');
}
Prototype model:
public function objects(){
return $this->belongsToMany("App\Object", "object_prototype", "prototype_id", "object_id");
}
If the relationship is correctly set in your Eloquent models, you can use the WhereHas function to query relationship existence.
$objects = Object::with('prototypes')
->whereHas('prototypes', function ($query) {
$query->where('prototype_id', 3);
})
->get();
Just to add on #Jerodev answer.
If you need even more power, you may use the whereHas and
orWhereHas methods to put "where" conditions on your has queries.
These methods allow you to add customized constraints to a
relationship constraint, such as checking the content of a comment:
// Retrieve all posts with at least one comment containing words like foo%
$posts = Post::whereHas('comments', function ($query) {
$query->where('content', 'like', 'foo%');
})->get();
You can read more about Eloquent Relationships
And in your case you can also construct a your query like.
Object::whereHas('prototypes', function ($query)){
$query->where('prototype_id', 3);
})->get();
I have an eloquent object Performer that has Albums and Albums have Images
Here is setup:
Model Performer->albums():
public function albums()
{
return $this->belongsToMany('Album','performer_albums','performer_id','album_id');
}
Model Album->images()
public function images()
{
return $this->belongsToMany('Image','album_images','album_id','image_id')->withPivot(['type','size']);
}
I have performer object stored as such:
$performer = Performer::where...->first();
Now I need to get Performer's Albums with images where size is 'large'
So to avoid nesting queries, can I use with()?
I tried
$performer->albums()
->with('images')
->wherePivot('size','large')
->get();
But laravel tells me it's trying to use wherePivot for Performer-Album relationship (M-2-M)
PS. I am also aware that I can do this,
$performer = Performer::with('albums')
->with('albums.images')
->.....-conditions for additional fields in album_images....
->get();
but question remains the same.
You need eager load constraints:
$performer->albums()
->with(['images' => function ($q) {
$q->wherePivot('size','large');
}])
->get();
And btw, no, you can't do this:
Performer::with('albums')
->with('albums.images')
->.....-conditions for additional fields in album_images....
->get();
instead you could do:
Performer::with(['albums.images' => function ($q) {
$q-> .....-conditions for additional fields in album_images....
}])->get();