Laravel eloquent get model property of current query - laravel

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.

Related

Access another table over attribute

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

How to use where by second table Laravel?

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

non trivial relationship in eloquent

i get:
Relationship method must return an object of type
Illuminate\Database\Eloquent\Relations\Relation
code of model:
class Order extends Model{
public function order_status(){
$q = self::GetQueryWithCurrentOrderStatus();
return $q->where('order.id', '=', $this->id)->get();
}
private static function GetQueryWithCurrentOrderStatus(){
$rawSql = OrderOrderStatus::selectRaw('order_order_status.order_id as id, max(created_at)')->groupBy('order_order_status.order_id')->toSql();
$query = OrderStatus::join('order_order_status', 'order_order_status.order_status_id', '=', 'order_status.id')
->join('order', 'order.id', '=', 'order_order_status.order_id')
->join(DB::raw('( ' . $rawSql . ') CurrentOrderStatus'), function ($join) {
$join->on('order_order_status.id', '=', 'CurrentOrderStatus.id');
});
return $query;
}
}
db structure is written in the answer here:
https://dba.stackexchange.com/questions/151193/good-database-structure-for-scenario-with-orders-that-have-a-state-and-the-state/151195#151195
order_status_history is order_order_status
now i could write in the blade file just:
$order->order_status() instead of $order->order_status ... but why? is there a solution?
If you're trying to call a method, call a method. order_status isn't a property.
If you access it as a property, it requires an Eloquent relationship (like it says) which are created through the hasOne, hasMany, belongsTo, belongsToMany methods: https://laravel.com/docs/master/eloquent-relationships

How to get relationship with union in eloquent?

How can I make relationship with union in laravel eloquent? I've already tried two different approaches.
User::with(['url' => function($query) use(&$some_property) {
$favouriteUrls = \DB::table('urls')
->select('urls.*')
->join('favourite_urls', function($join) {
$join->on('favourite_urls.url_id', '=', 'urls.id');
})
->where('some_condition', '=', $some_property);
$query = $query->union($favouriteUrls);
}]);
In the first attempt there wasn't any union in the query. Then I tried to move the logic to the model.
class User extends \Eloquent {
public function urls() {
$favouriteUrls = \DB::table('urls')
->select('urls.*')
->join('favourite_urls', function($join) {
$join->on('favourite_urls.url_id', '=', 'urls.id');
})
->where('some_condition', '=', $this->some_property);
return $this->belongsTo('Url')->union($favouriteUrls);
}
}
It has executed successfully but $this->some_property was set inside the query to the null value.
I can't create two separate relationship in this case. It has to be one with union. How can I fix it?
If you call that relation as User::with('urls') you will get that $this->some_property doesn't exists, because the object itself doesn't exists. But if you call the urls() method on an object, it should work. Something like this:
$user = User::find(1);
$user->urls; // here $this->some_property should have a value
Assuming you're calling the urls() method from a User object, the $this->some_property should give you the value. If for some reason you cannot access a property directly on an Eloquent model you can always refer to the attributes[] array inside of the model. For example
// calling
$this->some_property
// should be the same as
$this->attributes['some_property']
Fetch all the users joining with the condition
Assuming users is the table for all the users, in your query you could change $this->some_property with 'users.some_property' and everything should work as expected, for each user it will query based on that property. Here is the code:
class User extends \Eloquent {
public function urls() {
$favouriteUrls = \DB::table('urls')
->select('urls.*')
->join('favourite_urls', function($join) {
$join->on('favourite_urls.url_id', '=', 'urls.id');
})
->where('some_condition', '=', 'users.some_property');
return $this->belongsTo('Url')->union($favouriteUrls);
}
}
And then just call the method like this:
User::with('urls')->get();

Laravel eloquent: get data with model wherePivot equal to custom field

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

Resources