I'm building a platform where a user can sign up and add products to sell. Also another user can buy products listed. When a buyer place an order, i want it to be seen by a seller(user) who listed the product. Right now all users can see all orders even if they are not sellers.
I have no idea how to proceed but here is my
order function in product controller
//Orders View Function
public function viewOrders(){
$orders = Order::with('orders')->orderBy('id','Desc')->get();
return view('orders')->with(compact('orders'));
}
Any help will be appreciated.
Your viewOrders action should be hidden behind authentication process (obviously, user has to first sign in before he can view his orders). Once you do that (using auth middleware for it's route), Laravel can resolve authenticated user for you - you can simply hint it as a parameter of your viewOrders action:
public function viewOrders(User $user)
{
$orders = $user->orders()->orderBy('id', 'desc')->get();
return view('orders')->with(compact('orders'));
}
As you notice, here I've modified your query a little bit. Instead of selecting all orders we are now selecting them through authenticated user's relation to it's orders. Orders obviously belong to user, but through products (as an intermediate) - one user can have many products, one product can have many orders, thus one user can have many orders. In Laravel this kind of relationship between eloquent models is called HasManyThrough. Therefore you should declare it in your User model:
class User extends Model {
...
public function orders()
{
return $this->hasManyThrough(Order::class, Product::class);
}
}
Note that your Product will probably also have orders() relation, but it will be of HasMany type instead since it's a direct one without any intermediates.
Filter your query base on your needs
Example:
Model Relationship
public function orders(){
return $this->hasMany(Order::class);
}
public function getMyOrders(User $user){
$orders = Order::with('orders')->orderBy('id','Desc')->where('user_id','=', $user->id)->get();
return view('orders')->with(compact('orders'));
}
To get sellers Orders
public function getSellerOrders(User $user){
$products = Product::where('user_id', '=', $user->id)->get();
$orders = [];
foreach($products as $product){
array_merge($orders, $product->order);
}
return view('orders')->with(compact('orders'));
}
In your DB table for orders you are suggested to have 2 IDs, one which denotes Buyer and Other which denotes Seller, i.e., Whenever a user places an order, then it must be a buyer then insert it's(buyer) ID into buyer_id in Order's table, similarly the product_id for denoting produc from Products' Table should be there and from Product's Table you can get seller_id which is suggested to be there for denoting which seller owns a particular product. Insert seller_id into Order's Table and use it to your query as:
$seller = Order::where('seller_id',$variable_for_product_id)->with('orders')->get();
Do this for all sellers in your Order's Table
Related
I have a question
I have a table called cart_product that has these fields:
qty, price, cart_id
And i have a main table called carts
So every user has one cart => carts
and every cart has a lot of products => cart_product
I wanna calculate all the money user should pay for his cart, it means i should do this for every user:
sum = qty * price
here is my models:
class Cart extends Model
{
protected $with = 'coupon';
protected $fillable = [
'user_id', 'coupon', 'total'
];
public function user()
{
return $this->belongsTo(User::class);
}
public function products()
{
return $this->belongsToMany(Product::class, 'cart_product')->withPivot(['qty', 'price']);
}
public function coupon()
{
return $this->belongsTo(Coupon::class);
}
}
Can i do it with sum function? Thanks
The collections' sum function allows you to use a function as the "aggregator" (probably the wrong word) example.
The following should work:
$cart = Cart::with('products')->first();
$totalPrice = $cart->products->sum(function ($product) {
return $product->pivot->price*$product->pivot->qty;
});
For convenience, I would add this as an attribute (though be careful if you do because it will need the products to be loaded and if they are not it will do queries, which might be expensive).
Add this in your Cart model:
public function getTotalPriceAttribute() {
return $this->products->sum(function ($product) {
return $product->pivot->price*$product->pivot->qty;
});
}
The reason why this is convenient is that you can then do:
$totalPrice = $cart = Cart::with('products')->first()->total_price;
This of course works for a single cart. You can sum all the money a user must pay if they have multiple carts by doing:
$totalForUser = $user->carts->sum(function ($cart) {
return $cart->total_price;
});
However, if you prefer to get the price via a query directly without loading the related products you can do a plain-old join:
Cart::join('cart_product', 'carts.id', 'cart_product.cart_id')
->selectRaw('carts.*, SUM(cart_product.qty*cart_product.price) as total_cart_price')
->groupBy('carts.id', ...) // needs all the `carts` columns in the group by
This should result in each cart result to have a $cart->cart_total_price with the price.
The last solution will not need to load related models so will probably be faster, but if you want to display a cart with products along with the total then use the methods above this.
i have three tables, products , discount ,and dicount_products.
the discount table have the discount data, and the discount_products have the id's of the product and the discount tables, to make a connection bettwen them.
in my model products , am trying to accsess the discount throught the relationship table by doing this
//the discount relationship table
public function discount_list(){
return $this->hasOne(Discount_products::class,'product_id','id');
}
//getting the discount throught the discount_list
public function discount(){
return $this->discount_list()->discount();
}
the Discount_products model
public function discount(){
return $this->belongsTo(Discounts::class,'discount_id','id');
}
PS: i know i can do this in the controller but am trying to make discount accessble in one step.
I have three models: Payment, Booking and Customer. A payment relation belongs to the Booking model and the Booking model belongs to the Customer model.
I need to make a customer relation inside the Payment model, however, they are not related, the only relation between them is through the Booking model.
My code:
public function booking(){
return $this->belongsTo(Booking::class , 'payable_id' , 'id')->with('customer');
}
// what i need , i need to consume that booking function to get customer info
// something like this
public function customer(){
// consume the booking relation
// return customer info
}
Could you please advise me on the right approach?
The answer to that is a Has One Through or Has Many Through relationship, depending on your business model.
Class Payment {
public function customer()
{
return $this->hasOneThrough('Customer', 'Booking');
}
// or:
public function customers()
{
return $this->hasManyThrough('Customer', 'Booking');
}
}
Hope it helps.
Based on your question you want to get customer information through "booking" let's say it is your lookup table where a customer id and payment id fields exist.
It should look like this
ERD of table image
In your Booking Model you have should two functions
public function customer() {
return $this->belongsTo(Customer::class, 'cust_id', 'id');
}
public function payment() {
return $this->belongsTo(Payment::class, 'payable_id', 'id');
}
In both your Customer and Payment Models add
public function bookings() {
return $this->hasMany(Booking::class, '(cust_id or payable_id respectively)', 'id');
}
in case you want to access booking via customer/payment models as well.
Now with those relationships you can access both payment and customer by accessing booking.
e.g.
$customers = Booking::all()->with('customer');
$payments = Booking::all()->with('payment');
Now you can manipulate all other data for display and/or editing or whatever you need to do with it.
You can also now access a customer's data with all of his/her bookings and payments associated. Below code results a collection of payments based on c
$customer = Customer::find(1)->with('bookings')->first();
$payments = $customer->bookings->payment;
For more questions feel free to delve in to the Official Laravel documentations.
In answering your question I based it on this.
https://laravel.com/docs/5.8/eloquent-relationships
Hope I helped and cheers!
I'm using Larvel 5.3 and I have four tables I wish to set up relations with.
- Users
- Orders
- Products
- Brands
An order belongs to a user and a user has many orders.
A product belongs to many orders and additionally, to one brand.
A brand has many products.
I'm trying to find a way to get a user's order, with the products AND the brand of the products.
User.php
public function orders(){
return $this->hasMany('App\Order');
}
Order.php
public function user() {
return $this->belongsTo('App\User');
}
public function products(){
return $this->hasMany('App\Product');
}
Product.php
public function orders() {
return $this->belongsToMany('App\Orders');
}
public function brand(){
return $this->belongsTo('App\Brand');
}
Brand.php
public function products() {
return $this->hasMany('App\Flavour');
}
I wish to get back an array containing the users orders, along with each orders products and the products' brand.
Could anyone advise?
First, Products and Orders have a many to many relationship.
public function products(){
return $this->belongsToMany('App\Product');
}
Get a user's order first. Because users have many orders, you need to specify which order you want to view the products list from.
$order = $user->orders->first();
Then get all products and their brand
foreach($order->products) ...
For your super array, you can try Eager Loading
$arr = User::with('orders.products.brand')->get(); //Not tested
I have 3 Tables
Product:[Table]
Person:[Table]
Payment:[Table]
Many To Many Relationship Between Product and Person
One To Many Relationship Between Product and Payment (One Product Has Many Payments)
One To Many Relationship Between Person and Payment (One Person Has Many Payments)
Payment:[Table]
id
person_id
product_id
amount
The thing is that i am trying to get All persons with products and Product payments filtered by person_id.
Reason is that i dont want to have any other persons record in payments.
This is actually the query i am running yeah i know its wrong cuz i cant filter it by person_id.
$query = $person::with('product', 'payment')->where('is_active', 1);
I want to achieve something like this..
$query = $person::with(array('product', 'payment' => function ($query) {
$query->where('person_id', '=', 'person.id');
}))->where('is_active', 1);
If you setup your relations like:
class Person extends Model
{
public function payments()
{
return $this->hasMany(Payment::class);
}
}
class Payment extends Model
{
public function product()
{
return $this->belongsTo(Product::class);
}
}
Then you should be able to do:
$person = Person::with('payments.product')->where('id',$personId)->where('is_active',1)->first();
Which will return a Person with all the relations loaded and you can access those like:
#foreach($person->payments as $payment)
{{$person->name}} bought {{$payment->product->name}} for {{$payment->amount}}
#endforeach