How to order by the number of relationships - laravel

I am trying to create a "tag cloud" that lists the tag with the most relationships on a many-to-many pivot table schema.
I'm afraid I don't even know what to search in order to begin. I would appreciate any links or code examples, but prefer references so I can learn this once and for all.
I have a table named companies and a table named categories. There is a pivot table named category_company and the proper relationships are setup and working great.

Simply using withCount() should get you there.
$companies = Company::withCount('categories');
Now you are able to access the count like so.
foreach ($companies as $company) {
$company->categories_count; // gives out the count for this companies categories.
}
See the docs.

Related

Laravel models, database and pivot tables question

Hello I am working with Laravel,
I have to create two simple models, let's say Stores and Books.
Stores can have one or multiple Books and Books can belong to many Stores.
Of course I will use a many to many relationship, with a pivot table.
Books the can have different prices depending the store.
I think a separate table can only complicate things, in my mind the pivot table associating books and stores should have a price column, but pivot tables only contains store_id and book_id.
Should I create a book_prices and associate it with books and to stores? What is the best approach?
You are free and able to set other attributes on your pivot table. You can read more about it in the docs.
https://laravel.com/docs/9.x/eloquent-relationships#retrieving-intermediate-table-columns
You have to define the relationship accordingly, the following should clarify how this works. In this example you use the many-to-many relationship and add the price column to every retrieved pivot model.
public function books()
{
return $this->belongsToMany(Book::class)
->withPivot('price')
}
For example, you are able to access the pivot column in a loop like this
foreach ($shop->books as $book)
{
echo $book->pivot->price;
}
You can define additional columns for your pivot table in the migration for the pivot table, and then when defining the relationship use withPivot to define the additional columns so they come through in the model:
return $this->belongsToMany(Book::class)->withPivot('price');
(Adapted from the Laravel documentation, see https://laravel.com/docs/9.x/eloquent-relationships#retrieving-intermediate-table-columns)
Depends on the complexity of your case, but yes, you have two options for it. Let's say that the pivot table is called as book_store:
Directly adds price column to book_store. This is obviously the simpler option. The drawbacks are:
The history of the price changes isn't logged. You'll have to create another table for logging if you want to keep this history information.
Changes made to price will directly change the price of the related book_store record. Meaning that a price is being updated "live" e.g users cannot update the price now but "publish" it some time later just like this example in the doc.
Create a new, different table to store the price. This may seems relatively more complex, but it may also be more future-proof.
Basically, you get 2 things that you miss in the first option above.
Don't think too much about book_store being a pivot table. One way to see it is like this: book_store IS a pivot table from books and stores tables viewpoints, but it's also just a normal SQL table which could relate to any other tables using any kind of relationships.
If you want to implement this, make sure to create a primary-key in the book_store table.
Alast, it all depends on what you need. Feel free to ask if you need more insight about this. I hope this helps.

How to Get Order Details per a single User in Laravel 7

I am making a multi-vendor ecommerce website using Laravel 7. I am trying to make an Order History page where in a single can user can view only his/her own orders. I am having a problem building the query on my OrderHistoryController. These are the codes on my controller:
$users = User::get();
$orders = Order::find($users);
return view('order-history', compact('orders'));
And I'm trying to loop $orders on my blade file. I have:
#foreach ($orders as $order)
<div>{{ $order->id}}</div>
<div>{{ $order->grand_total}}</div>
#endforeach
I am trying to pass the order id and order grand total to my view. I don't get any error however it shows a different order details from a different customer. How do I do this?
You should use MySQL (or any other database you are using) table relationships and foreign keys.
So, your orders table, should have columns id, user_id, date, and so on. The important thing is user_id column. You want to make that column a foreign key. That basically means that user_id will hold an id value from another table, in this case user. See how to make foreign key columns in laravel migrations here.
Next up is to use Laravel's built in model relationships. You can read more about them here. Basically, in your orders model you want to have a function user which returns $this->belongsTo(App\Models\User::class) and in your user model you want to have a function orders which returns $this->hasMany(App\Models\Order::class) (or whatever the namespace is for both of them).
That way, you can call $user->orders and get a collection of Order models which will contain only the orders of that particular user.
Definitely read the documentation carefully and learn basic concepts of the framework first and how relational databases function!
You can get a lot of this information just by googling it or reading the documentation of Laravel or any other framework you plan on using! Good luck learning :)

Inverse of belongsToMany

I got two Models:
Order
Invoice
Each Order can have many Invoices - and an Invoice can belong to many Orders.
So I can search for an Order and check: "Hey, which Invoices have been created for this Order?"
The other way round each Invoice can belong to multiple Orders, because maybe a customer ordered two products on the same day and so it would be great he'd only get one Invoice, which includes both orders.
So this is how I did this:
Invoice
public function orders()
{
return $this->belongsToMany(Order::class);
}
Order
public function invoices()
{
return $this->belongsToMany(Invoice::class, 'invoice_order');
}
This does work - but it does not seem right to change the table to the intermediate table invoice_order here. Do you have any thoughts on this? :-)
Thanks in advance for your thoughts :-)
Seperating the relation into a seperate pivot table is the commonly used method in laravel (and in most other frameworks) for many to many relationships.
It's easy to maintain, easy to get related models using many to many relationship, and if someone else needs to work on it in the future, they'll probably have used it in the past as well so wouldn't end up burning their heads.
The other method you could use is to create a json column on one of the tables (you can create on both tables as well if you want, but that's just extra overhead). Then you can store the ids of the related models in this json column. You can then join the tables using the json related commands provided by your database. Eloquent does not support relationships on json, but you can use this package staudenmeir/eloquent-json-relations to build relationships on json fields.
So overall, I'd suggest keeping a pivot table like the standard way, but if that just won't do, then you can try the json column method

how do I make relationships for 4 tables including pivot table

I have many to many relationships. Imagine I have 3 tables. Something like this :
users.
roles.
role_user.
(This example is also provided in laravel's docs).
Now I'm doing this : $user->roles() which returns roles with Pivot attributes . but what I actually want to do is move forward and also get the appropriate data from the 4th table. something like this $user->roles()->types(); and the difficult thing is that this types() belongs to pivot table.
Do you know how to do this kind of thing ? where Do I write types() function?
Assuming your "Roles" model has the relationship set you may try
$user->roles()->with("types")
Source docs: https://laravel.com/docs/5.7/eloquent-relationships#eager-loading

Eloquont related data

I have a ProductCategory say "Dresses". Products are related to product category and images are related to Products. I want the list of records with both products, product images for a particular ProductCategory id using Laravel 5.2.
I tried:
$productCategories = ProductCategory::find(1)->products;
This give me related products, but now I want all the related images to the products in the result.
look for eloquent nested relationships eager loading. need to know what kind of relationships and relationship names you are using.
haven't tested but it should work something like this. if many to many relationship come by you may need to use a foreach to loop through finding related model of each.
$productCategories = ProductCategory::with('products', 'products.images')->findOrFail(1);

Resources