laravel - How to get data by pivot table - mysql

I have a problem with laravel. I have created relationships between tables and relationships at the model level in laravel but if I want to display data to the view, I get an error: Property [category] does not exist on this collection instance.
the table with the films is called: videos
the table with the categories is called: categories
the pivot table is called: category_video
Video model code:
public function categories()
{
return $this->belongsToMany('App\Category');
}
Categories model code:
public function videos()
{
return $this->belongsToMany('App\Video');
}
In controller i have this:
$slider_videos = Video::->orderBy('rating','desc')
->limit(5)
->get();
In view i try this:
#foreach($slider_videos as $slider_video)
{{$slider_video->category->name}}
#endforeach
I will add that when I use this: {{$slider_video->category}} it's displaying all contents of single row
By the way, how can I specify the name of the pivot table in the model?

Categories are a collection you need to loop over it :
#foreach($slider_videos as $slider_video)
{{ $slider_videos->name }} categories are :
#foreach($slider_video->categories as $category)
{{$category->name}}
#endforeach
#endforeach

belongsToMany returns a collection even if there is only a single record linked with the relationship.
You need to access it in a foreach loop.
Like so.
#foreach($slider_video->categories as $category)
{{$category->>field_name}}
#endforeach

Related

How to concat two tables into one row with validations (Lumen, Laravel)

I'm using Laravel and I'm trying to return this on API:
{
id: 1
name: BOM DIA
},
id: 2
name: BOM DIA (SUPERM VANEZA, BATISTA & IZEPE, BOM DIA)
}
But I'm confused. I have a table named 'Teams', and at this table, some columns have a number 'biid'. This 'biid' is the same information from another table name 'Clients'.
More than one 'Clients' can have same 'biid', but 'Teams' only have unique 'biid' or don't have any 'biid'.
I wanna to concat 'Teams' who has 'biid' with column named 'slug' in table 'Clients'.
Tables:
This should be like this:
How can I even think in make this?
Hello you need relations to do it if i know your problem
so let's talk about relation in your case Teams as many clients
the relation in your model teams will be this:
public function client(){
return $this->belongsToMany(Client::class);
}
What laravel does with belongsToMany method ?
for each client who as the same id's who you references teams and laravel will add it to you Eloquent Object.
Your client has one teams
soin your client model if you named it client :
public function team(){
return $this->belongsTo(Model::class);
}
to get the detail of relation who you need :
you will need to make the relations request, this will contribute to remove n +1 problem:
$clients = Client::with(['team']);
$teams = Team::with(['client']);
// here i don't know if you need ->get() try without and with
To access the relations:
foreach($clients as $client){
echo $client->team->name;
}
foreach($teams->client as $team){
echo $team->name;
}
// or
foreach($teams as $team){
echo $team->client->name;
}
But i think for that you need to rename you column because that are not explicit for laravel
to access relations you column need to have client_id and team_id to work.

Eloquent belongsToMany and Three Tables (Including Pivot)

I am working on an Ecommerce project using the Laravel framework. I have a products table, a flavors table, and a flavor_product table (I believe this is referred to as a pivot table). I have a Product model and a Flavor model (from what I have read it is unnecessary to create a model for the pivot table).
In the Product model I have defined the following relationship:
public function flavors()
{
return $this->belongsToMany('App\Flavor');
}
In the Flavor model I have defined the following relationship:
public function products()
{
return $this->belongsToMany('App\Product');
}
Now, in my Product controller I have attempted the following:
$flavors = Product::select('id')->with('flavors')->get();
which gets sent to the applicable view (product.blade.php).
In product.blade.php I have the following:
#foreach ($flavors as $flavor)
<select id="product-flavor" class="bs-select">
<option value="{{ $flavor }}">{{ $flavor }}</option>
</select>
#endforeach
So, what is the giving me? Well, it's showing me the following:
{"id":1,"flavors":[{"id":1,"name":"Cake Batter","created_at":"2018-05-29 20:12:56","updated_at":"2018-05-29 20:12:56","pivot":{"product_id":1,"flavor_id":1}},{"id":2,"name":"Caramel Coffee","created_at":"2018-05-29 20:48:25","updated_at":"2018-05-29 20:48:25","pivot":{"product_id":1,"flavor_id":2}},{"id":3,"name":"Chocolate Milkshake","created_at":"2018-05-29 20:49:09","updated_at":"2018-05-29 20:49:09","pivot":{"product_id":1,"flavor_id":3}},{"id":4,"name":"Cookies & Cream","created_at":"2018-05-29 20:49:50","updated_at":"2018-05-29 20:49:50","pivot":{"product_id":1,"flavor_id":4}},{"id":5,"name":"Vanilla Milkshake","created_at":"2018-05-29 20:50:16","updated_at":"2018-05-29 20:50:16","pivot":{"product_id":1,"flavor_id":5}}]}
which I definitely don't want all of that. All I want is to retrieve the name of the flavors associated to that product via the pivot table.
How can I proceed on this?
Edit
The following code is in the ShopController.php (regarding how the product is retrieved and displayed):
/**
* Display the specified resource.
*
* #param string $slug
* #return \Illuminate\Http\Response
*/
public function show($slug)
{
$product = Product::where('slug', $slug)->firstOrFail();
$mightAlsoLike = Product::where('slug', '!=', $slug)->mightAlsoLike()->get();
return view('product')->with([
'product' => $product,
'mightAlsoLike' => $mightAlsoLike,
]);
}
From web.php:
Route::get('/shop/{product}', 'ShopController#show')->name('shop.show');
What you're doing here is telling Laravel to select id from all products and retrieve all of their associated flavours.
Product::select('id') // <-- Will only select `id` attribute from the `products` table
->with('flavors') // <-- Will attach associated flavors to the product id
->get(); // <-- End the query (get all product ids and their flavours)
In your case, you don't want to select all the products and you have the relation set up correctly. So what you should do is call ->with('flavors') on your original query (actually not needed in this case, since you won't run into n+1 problems but still good practice):
$product = Product::where('slug', $slug)->with('flavors')->firstOrFail();
$mightAlsoLike = Product::where('slug', '!=', $slug)->mightAlsoLike()->get();
return view('product')->with([
'product' => $product,
'mightAlsoLike' => $mightAlsoLike,
]);
And then just call the $product->flavors in the view:
#foreach ($product->flavors as $flavor)
<select id="product-flavor" class="bs-select">
<option value="{{ $flavor }}">{{ $flavor }}</option>
</select>
#endforeach
The above view code would work as-is without actually calling ->with('flavors') on the query. ->with(...) eager loads the relationship and is good practice to explicitly call when loading multiple parents, to avoid n+1 problem (performance!).
But in your case you're only showing the flavors from 1 product, so there's no real advantage to calling it explicitly (except clearer code).
Edit to address the comment:
<select id="product-flavor" class="bs-select">
#foreach ($product->flavors as $flavor)
<option value="{{ $flavor->id }}">{{ $flavor->name }}</option>
#endforeach
</select>
You're seeing multiple selects because you're printing the whole select inside the loop instead of just printing the options.
And to display any attribute from the current flavor, just call the attribute name: $flavor->name for example.

How do I connect a "related products" table

I have the following tables
products table
product_id
name
desc
with a has many relation to
suggested products table
id
product_id
suggested_product_id
Quantity
required (boolean)
What I am trying to accomplish is being able to access the name of a suggested product id in my view.
Products Controller
public function show($id)
{
$product = Product::with('stockitems','suggestedproducts.product')->find($id);
return view('backend.products.show', compact('product'));
}
I know the issue is at "suggestedproducts.product" just not sure how i specify the key(suggested_product_id) for the eager load is a product_id.
You should define the following relationship in your Product model:
public function suggestedProducts()
{
return $this->belongsToMany(Product::class, 'suggestedproducts', 'product_id', 'suggested_product_id')
->withPivot(['quantity', 'required']);
}
This would allow you to get all related products as Eloquent models by doing the following:
$product = Product::with('suggestedProducts')->find($id);
$product->suggestedProducts; // This accesses the suggested products
To access the name of each suggested product, just do the following:
foreach ($product->suggestedProducts as $suggestedProduct)
echo $suggestedProduct->name;
To access the data in the pivot table, you have to use the following:
foreach ($product->suggestedProducts as $suggestedProduct)
echo $suggestedProduct->pivot->quantity;

Accessing the table fields with relation yii2

Model users has onetomany relation with category
public function getCategory()
{
return $this->hasMany(Category::className(), ['user_id' => 'user_id']);
}
I am not being able to access the fields of category using this relation.
public function actionGetResults()
{
$results = users::find()->where(['user_id' =>8])
->with('category')
->all();
echo "<pre>"; print_r($results);
}
$results here shows an array with fields of category. i.e category_name, category_id etc. but if i do this:
echo "<pre>"; print_r($results->category_name);
it fails.
First of all, since relation type is has many, category name is misleading and it's better to use categories.
Second, you are accessing related field wrong. $results is an array of User models and categories property of each model contains an array of related Category models to that user.
Use nested foreach loop:
foreach ($results as $user) {
foreach ($user->categories as $category) {
var_dump($category->name);
}
}
Or to get the name of the first user's first category:
$results[0]->categories[0]->name
Note that the second approach is only for demonstration purposes and can fail with Undefined index error if user or / and category does not exist.
Read Working with Relational Data for more info.

How to loop first() in laravel

Context :
I make an Json api with laravel 5.1 to fetch all of categories and sub categories
and the relationship between categories table and subcategories table is ManyToMany
Code :
Categories model :
public function subcategory() {
return $this->belongsToMany(Subcategory::class);
}
Subcategory model :
public function category() {
return $this->belongsToMany(Categories::class);
}
Api Controller :
$response = Categories::with('subcategory')->first();
return $response
Problem :
I want loop $response to get all data not only the first one
The answer is
$response = Categories::with('subcategory')->take(-1)->get();
You are calling the first method which retrieve only the first model from Categories. In order to get all the records, you should use the get method like so:
$response = Categories::with('subcategory')->get();
Now the $response object will be a Collection of Eloquent models.
The get method is usually the last method of your queries, that acts like: run the query now please Eloquent
Take a look of the documentation about Eloquent Collection