Accessing Related Model inside the mutator - laravel

I have question about my problem, so let me explain..
I have these Model which is Product and ProductVariant , the ProductVariant has "belongsTo" relation into the Product model.. and Product model have "hasMany" relation into the ProductVariant
My Question is...
i did createMany for variation from the product which is like
Product->variant()->create($variantProducts);
and i'd like to create some mutator on the ProductVariant model to manipulate one column called "sku".
my problem is, how to get some column value from the mutator to get data from the related model ( Product ) , in this case i want to get the category_id of the Product from the ProductVariant mutator
i try to do this , but it seems doesnt work
public function setSkuAttribut($v){
// product() is belongsTo relation to the product model
$cat = $this->product()->category_id;
dd($cat);
}
but it returns me this error
Undefined property: Illuminate\Database\Eloquent\Relations\BelongsTo::$category_id
Any helps would be really appreciated.. thankyou :)

You're calling the product() relation method as a method, which means you're receiving a Builder instance. In order to get the model instance, you'll either have to execute ->product()->get()->category_id, which will make a new query on each occasion or use the lazy eager loading with ->product->category_id which will use an already loaded relation instance if present.

Related

Laravel Relationships, don't know how to display

I have two models. Business and City.
Business:
id
title
-some columns--
city_id
City:
id
name
How to display the city name, when I get business data to view
I was able to display cities using the laravel voyager lessons
When I want to get it like $business->city_id
If you are using models, you can create a relationship by adding hasOne or hasMany to your model codes.
When you call it from your controller, you can call the relationship you wrote in your model with the 'with' query.
Model
public function city()
{
return $this->hasOne(City::class,'id','cityid');
}
Controller
$business=Business::with('city')->first();
$cityname=$business->city->name;
If you don't use model, you can connect with 'join'
You have 2 options. First, you can get city details on the controller:
Business::with('city')...;
On the blade
$business->city->name;
Other option fetching it on the blade directly. I don't recommend this because of extra database queries.
$business->city()->name;

belongsToMany with nullable foreign - Laravel 5.8

in my Laravel project i get this database structure:
Products
Id
Name
Orders
Id
Total
Order_Product
Product_id (nullable)
Order_Id
Details
In my Order model I make belongsToMany retaltionship with Product model:
public function products() {
return $this->belongsToMany(Product::class)->withPivot('Details');
}
The Problem is when I try to get the Order Products Collection
$order->products();
I don't get rows with nullable product_id, Any solution please ? Thank you.
Laravel support "Null Object Pattern" since version 5.5 which allows you to define a default model that will be returned if the given relationship is null.
Try using the following code:
public function products() {
return $this->belongsToMany(Product::class)->withDefault()->withPivot('Details');
}
Most likely, you don't get "nullable" products because you have a relation Order->Products. When you call $order->products(), eloquent tries to get all Product entities that are connected to your Order via product_id field. So, if field is empty, then you can't get Product because there is no connection.
One of the solutions is:
create another entity like OrderLine(Order_Product table); add methods like $orderLine->details() and relation to Product like $orderLine->product()
add relation to OrderLine inside Order - $order->line() or $order->info() etc. -> Order hasMany OrderLine
then use $order->line() to get an order's details and products (if exists)
p.s. I've compiled it in my head so it might need some code adjustments.
Good luck

Query hasMany relation with slug instead of id?

I'm trying to query a category and all of its channels based on a slug.
Works
\App\Category::find(1)->channels()->get();
Doesn't Work
\App\Category::where('slug','animals')->channels()->get()
BadMethodCallException with message 'Method Illuminate/Database/Query/Builder::channels does not exist.'
Relationship on Category Model
public function channels()
{
return $this->hasMany(Channel::class,'category_id');
}
Assuming that you correctly have your slug field set-up in migration and model attributes (It looks like so from the Exception message).
Doing
\App\Category::find(1)->channels()->get();
is under the hood equivalent to
\App\Category::where('category_id', 1)->first()->channels()->get();
So what you are requiring, is to get the categories to actually execute the query and then be able to retrieve the channels from the hydrated model.
\App\Category::where('slug', 'animals')->first()->channels()->get();
should work as well as
\App\Category::where('slug', 'animals')->first()->channels; // calling as attribute will perform the get() on the relationship
Also take note that you may take advantage of other methods like with() for eager loading the relationship, first() to perform a get and ensure you take only one instance, and calling the relationship as attribute as shown above. Refer to the docs
there are so many possible answer in your question .. be more specific .. but here's the list of sample queries that may help you ..
GETTING ALL THE CATEGORY WITH ITS CHANNELS WHERE CATEGORY SLUG = ANIMAL
Category::with(['channels'])->where('slug', 'animal')->get();
GETTING ALL THE CATEGORY WITH ITS CHANNELS WHERE HAS A CHANNEL SLUG = ANIMAL
Category::with(['channels'])->whereHas('channels'=>function($q){
$q->where('slug','animal');
})->get();
GETTING ALL THE CATEGORY WITH ONLY CHANNELS THAT HAS A SLUG = ANIMAL
Category::with(['channels'=>function($q){
$q->where('slug','animal');
}])->get();

Laravel 5.5 retrieving null by nested relation

I have 3 databases:
Routes:
id
name
Rates:
Id
Route_id
Car_id
Cars:
id
name
My model for routes
public function rates()
{
return $this->hasMany('App\Rate', 'route_id');
}
My model for rates
public function car() {
return $this->belongsTo('App\Car','car_id');
}
Now I need to access the car relation, but when I do
return $this->route->with('from','to','rates.car')->paginate(74);
I get null for the car relation
{"id":1,"from_id":1,"to_id":2,"distance":400,"created_at":null,"updated_at":null,"from":{"id":1,"name":"\u0410\u043a\u043a\u043e","created_at":null,"updated_at":null,"lat":32.93310000000000314912540488876402378082275390625,"long":35.0827000000000026602720026858150959014892578125},"to":{"id":2,"name":"\u0410\u0440\u0430\u0434","created_at":null,"updated_at":null,"lat":31.261399999999998300381776061840355396270751953125,"long":35.21490000000000009094947017729282379150390625},"rates":[{"id":1,"route_id":1,"car_id":1,"rate":1123,"night_rate":1391,"car":null},{"id":5551,"route_id":1,"car_id":2,"rate":1123,"night_rate":1391,"car":null},{"id":11101,"route_id":1,"car_id":3,"rate":1123,"night_rate":1391,"car":null},{"id":16651,"route_id":1,"car_id":4,"rate":1123,"night_rate":1391,"car":null},{"id":22201,"route_id":1,"car_id":5,"rate":1123,"night_rate":1391,"car":null},{"id":27751,"route_id":1,"car_id":6,"rate":1123,"night_rate":1391,"car":null},{"id":33301,"route_id":1,"car_id":7,"rate":1123,"night_rate":1391,"car":null},{"id":38851,"route_id":1,"car_id":8,"rate":1123,"night_rate":1391,"car":null}]},
From my understanding you are trying to access a Car model through a Route model.
A couple of things I noticed that should help you find a solution.
First off I think the inverse relation you are supposed to use the belongToMany() function instead.
public function car() {
return $this->belongsToMany('App\Car','Rates'); // Perhaps call the table something like routes_cars to more clearly define it's a pivot table
}
Next I see you are trying to use model functions within the context of $this(). I assume you are doing this in your model? That logic should be in a controller, that might cause some undesired results but I'm not entirely sure. Also it looks like your parameters are incorrect when using with(). You use the function name that you defined in belongsToMany()
App/Route::with('car')->paginate(74);
With the correct relationships setup you rarely need to worry about the pivot table. If you are going to add extra information in the pivot table there are laravel functions to help you do that in the documentation.

eloquent filter result based on foreign table attribute

I'm using laravel and eloquent.
Actually I have problems filtering results from a table based on conditions on another table's attributes.
I have 3 tables:
venue
city
here are the relationships:
a city has many locations and a location belongs to a city.
a location belongs to a venue and a venue has one location.
I have a city_id attribute on locations table, which you may figured out from relationships.
The question is simple:
how can I get those venues which belong to a specific city?
the eloquent query I expect looks like this:
$venues=Venue::with('location')->where('location.city_id',$city->getKey());
Of course that's not gonna work, but seems like this is common task and there would be an eloquent command for it.
Thanks!
A couple of options:
$venues = Venue::whereIn('location_id', Location::whereCityId($city->id)->get->lists('id'))
->get();
Or possibly using whereHas:
$venues = Venue::whereHas('location', function($query) use ($city) {
$query->whereCityId($city->id);
})->get();
It is important to remember that each eloquent query returns a collection, and hence you can use "collection methods" on the result. So as said in other answers, you need a Eager Loading which you ask for the attribute you want to sort on from another table based on your relationship and then on the result, which is a collection, you either use "sortBy" or "sortByDesc" methods.
You can look at an example below:
class Post extends Model {
// imagine timpestamp table: id, publish, delete,
// timestampable_id, timestampble_type
public function timestamp()
{
return $this->morphOne(Timestamp::class, 'timestampable');
}
}
and then in the view side of the stuff:
$posts = App\Post::with('timestamp')->get(); // we make Eager Loading
$posts = $posts->sortByDesc('timestamp.publish');
return view('blog.index', compact('posts'));

Resources