I have an Order table that has buyer_id and seller_id as columns. The buyer_id is the current login user who is buying something from the seller. What I want is when the buyer is submitting the order, the seller_id of the product should also be present.
Here is how I'm creating the order in checkout controller inside the store function
//Insert into the orders table
$order = Order::create([
'buyer_id' => auth()->user() ? auth()->user()->id : null,
'seller_id' => //what should i put here to query the owner of the product(the user who listed the product)
'shipping_email' => $request->email,
'shipping_name' => $request->name,
'shipping_city' => $request->city,
'shipping_phone' => $request->phone,
// 'error' => null,
]);
User.php
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password', 'Seller'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
//public function isSeller() {
// return $this->seller;
//}
public function products()
{
return $this->hasMany(Products_model::class);
}
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function orders()
{
$this->hasManyThrough(Order::class, Products_model::class, 'buyer_id', 'seller_id', 'product_id');
}
public function buys() {
$this->hasMany(Order::class, 'buyer_id', 'id');
}
public function sells() {
$this->hasMany(Order::class, 'seller_id', 'id');
}
}
Products_model.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class products_model extends Model
{
protected $table='products';
protected $primaryKey='id';
protected $fillable=['seller_id','pro_name','pro_price','pro_info','image','stock','category_id'];
}
OrderProduct.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class OrderProduct extends Model
{
protected $table = 'order_product';
protected $fillable = ['order_id', 'product_id', 'quantity'];
public function products()
{
return $this->belongsTo('App\Products_model');
}
}
Order.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
//protected $table = 'orders';
protected $fillable = [
'buyer_id', 'seller_id','shipping_email', 'shipping_name', 'shipping_city', 'shipping_phone', 'billing_subtotal', 'billing_total',
];
public function user()
{
return $this->belongsTo('App\User');
}
public function products()
{
return $this->belongsToMany('App\Products_model')->withPivot('quantity');
}
public function orders()
{
return $this->hasMany('App\OrderProduct', 'order_id');
}
public function buyer()
{
return $this->belongsTo(User::class, 'id', 'buyer_id');
}
public function seller()
{
return $this->belongsTo(User::class, 'id', 'seller_id');
}
}
Seller view Order function
public function viewOrders(User $user)
{
$products = Products_model::where('seller_id', '=', $user->id)->get();
// all sells
$sells = $user->sells;
// all buys
$buys = $user->buys;
}
//dd( $products);
return view('orders')->with(compact('orders'));
Seller Dashboard blade
#foreach($sells as $sell)
<tr>
<td>{{$sell->orders}}</td>
<td>{{$sell->products}}</td>
#foreach($sell->orders as $order)
<td>{{$order->created_at}}</td>
<td>{{$order->shipping_name}}</td>
<td>{{$order->shipping_city}}</td>
<td>{{$order->shipping_phone}}</td>
<td>
View Order Details
</td>
</tr>
Your products table should have the relationship to the seller of the product, and in the order table you should have the product_id instead of the seller_id. Then when you create an order, you should put the product that the buyer is buying and the seller will be there through the product relationship. I hope I am clear and this is what you are looking for.
And even more, while I am thinking about it. I don't know your idea on the orders/products but I guess an order to a product should be a many to many relationship as most of the stores do. Meaning an order contains many products.
A seller has many orders through the products model. So if a product belongs to a seller, then you can make this in your Seller model:
public function orders()
{
return $this->hasManyThrough(Order::class, Product::class);
}
You can read more on this here.
Related
User Model:
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* #var string[]
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* #var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function venues()
{
return $this->hasMany(Venue::class);
}
public function profile()
{
return $this->hasOne(Profile::class);
}
}
Venue Model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Venue extends Model
{
use HasFactory;
protected $fillable = ['user_id', 'city_id', 'category_id', 'title', 'address', 'phone', 'email', 'website', 'facebook', 'instagram', 'content_bg', 'content_en', 'cover_image', 'lat', 'lng'];
public function user()
{
return $this->belongsTo(User::class, 'user_id');
}
public function category()
{
return $this->belongsTo(Category::class, 'category_id');
}
public function city()
{
return $this->belongsTo(City::class, 'city_id');
}
public function features()
{
return $this->belongsToMany(Feature::class, 'venue_feature');
}
public function images()
{
return $this->hasMany(VenueImage::class);
}
public function reviews()
{
return $this->hasMany(Review::class);
}
}
Everything is fine, but now I want to have two methods where to call active / inactive venues of the user and I'm not sure where to place them in User Model or in Venue Model, generally which is better?
If I put them in Venue model (getUserActiveVenues and getUserInactiveVenues) and pass authenticated user to these methods, or to put them in User model (getActiveVenues and getInactiveVenues).
add relations to the user model
public function venues()
{
return $this->hasMany(Venue::class);
}
public function activeVenues()
{
return $this->hasMany(Venue::class)->where('active',true);
}
public function inActiveVenues()
{
return $this->hasMany(Venue::class)->where('active',false);
}
then you can eager load the relevant type of venue. I had to guess at what you mean be 'active'
User Model:
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* #var string[]
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* #var array
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function venues()
{
return $this->hasMany(Venue::class);
}
public function reviews()
{
return $this->hasMany(Review::class);
}
public function profile()
{
return $this->hasOne(Profile::class);
}
public function approvedVenues()
{
return $this->hasMany(Venue::class)->where('is_approved', '=', 1);
}
public function unapprovedVenues()
{
return $this->hasMany(Venue::class)->where('is_approved', false);
}
public function ownVenuesReviews()
{
return $this->reviews()->whereIn('user_id', function($query) {
$query->select('id')
->from('venues')
->whereRaw('venues.user_id = users.id');
})->get();
}
}
Venue Model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Venue extends Model
{
use HasFactory;
protected $fillable = [
'user_id',
'city_id',
'category_id',
'title',
'address',
'phone',
'email',
'website',
'facebook',
'instagram',
'content_bg',
'content_en',
'cover_image',
'lat',
'lng'
];
public function user()
{
return $this->belongsTo(User::class, 'user_id');
}
public function category()
{
return $this->belongsTo(Category::class, 'category_id');
}
public function city()
{
return $this->belongsTo(City::class, 'city_id');
}
public function features()
{
return $this->belongsToMany(Feature::class, 'venue_feature');
}
public function images()
{
return $this->hasMany(VenueImage::class);
}
public function reviews()
{
return $this->hasMany(Review::class);
}
}
Review Model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Review extends Model
{
use HasFactory;
protected $fillable = ['rating', 'content', 'venue_id', 'user_id'];
public function venue()
{
return $this->belongsTo(Venue::class);
}
public function images()
{
return $this->hasMany(ReviewImage::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
So Users have many Venues, Venues have many reviews.
I want to get reviews on own Venues for example (If I own venues with id 100, 101 - I want to get all reviews for these two venues)
Raw query is this:
SELECT * FROM `reviews` WHERE reviews.venue_id IN (SELECT venues.id FROM venues WHERE venues.user_id = 1)
What I tried in Laravel in User model (doesn't work), I'm also curious if there is a way, without raw part:
public function ownVenuesReviews()
{
return $this->reviews()->whereIn('user_id', function($query) {
$query->select('id')
->from('venues')
->whereRaw('venues.user_id = users.id');
})->get();
}
A HasManyThrough relationship should work, if I'm understanding your model relationships properly:
public function ownVenueReviews(): HasManyThrough
{
return $this->hasManyThrough(Review::class, Venue::class);
}
The raw part is only needed because you have to include the foreign key in the select portion of the sub query. Even though you may not want the user_id in the query result it must still be selected for Laravel to be able to make the relationship match work.
public function ownVenuesReviews()
{
return $this->reviews()->whereIn('user_id', function($query) {
$query->select('id', 'user_id')
->from('venues');
})->get();
}
I did it like this, but I'm not quite sure, that this is the best way, I'm open to suggestions:
public function ownVenuesReviews()
{
return Review::whereIn('venue_id', function($query) {
$query->select('id')
->from('venues')
->where('user_id', $this->id);
})->get();
}
I'm trying to display orders to sellers but also buyers can be able to see their orders. I have created all the necessary relationships and the data is on the database. I'm stuck in trying to query this data from database so i can show it. I have these tables orders table, order_product table. Here is how they look like https://imgur.com/a/Ud9e2Hh
I have tried below functions but still no luck in solving the problem.
If you need more information, just comment and i will provide.
Here are my functions
// Seller Orders
public function viewOrders(User $user)
{
// all sells
$sells = $user->allOrderFromSellers();
dd($sells);// this returns empty array
return view('orders')->with(compact('sells'));
}
//Buyer Orders
public function myOrders(User $user)
{
return view('myOrders', compact('user','orders'));
dd($orders);
}
And here are the models.
order_product.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class OrderProduct extends Model
{
protected $table = 'order_product';
protected $fillable = ['order_id', 'buyer_id', 'seller_id','product_id', 'quantity'];
public function products()
{
return $this->belongsTo('App\Products_model');
}
public function buyer()
{
return $this->belongsTo(User::class, 'id', 'buyer_id');
}
public function seller()
{
return $this->belongsTo(User::class, 'id', 'seller_id');
}
public function order()
{
return $this->belongsTo(Order::class);
}
}
and this is User.php
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password', 'Seller'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
//public function isSeller() {
// return $this->seller;
//}
public function products()
{
return $this->hasMany(Products_model::class);
}
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function orders()
{
return $this->hasManyThrough(Order::class, Products_model::class, 'buyer_id', 'seller_id', 'product_id');
}
public function orderFromBuyers()
{
return $this->hasManyThrough(OrderProduct::class, Products_model::class, 'buyer_id', 'product_id');
}
public function orderFromSellers()
{
return $this->hasManyThrough(OrderProduct::class, Products_model::class, 'seller_id', 'product_id');
}
public function allOrderFromBuyers()
{
return $this->hasMany(OrderProduct::class, 'buyer_id');
}
public function allOrderFromSellers()
{
return $this->hasMany(OrderProduct::class, 'seller_id');
}
}
the above functions give me this collection as result:
"Collection {#281 ▼
#items: []
}"
please help me on this, i have spent so much time but nothing is working.
The relationship is not correct
You need to use many to many and has many through relations, as order has many products and product has many orders ....
https://laravel.com/docs/5.8/eloquent-relationships#many-to-many
https://laravel.com/docs/5.8/eloquent-relationships#has-many-through
Don't create model and relations for pivot table like OrderProduct
That is not correct
In this case order_product is a pivot table
So this is a correct Models
For Order model
public function products()
{
return $this->belongsToMany('App\Product', 'order_product');
}
For Product model
public function orders()
{
return $this->belongsToMany('App\Order', 'order_product');
}
After that you can handle rest of things
$order = Order::with('products')->findOrFail($id);
$products = $order->products
I'm trying to get orders placed by buyers to be seen by the respective seller but it does not show anything.
I have tried for hours to solve this problem but I'm still stuck.
This is my model Order.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
//protected $table = 'orders';
protected $fillable = [
'user_id', 'shipping_email', 'shipping_name', 'shipping_city', 'shipping_phone', 'billing_subtotal', 'billing_total',
];
public function user()
{
return $this->belongsTo('App\User');
}
public function products()
{
return $this->belongsToMany('App\Products_model')->withPivot('quantity');
}
public function orders(){
return $this->hasMany('App\OrderProduct', 'order_id');
}
}
This is my OrderProduct.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class OrderProduct extends Model
{
protected $table = 'order_product';
protected $fillable = ['order_id', 'product_id', 'quantity'];
public function products()
{
return $this->belongsTo('App\Products_model');
}
}
This is my User.php
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password', 'Seller'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function products()
{
return $this->hasMany(Products_model::class);
}
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function orders()
{
$this->hasManyThrough(Order::class, Products_model::class, 'user_id', 'product_id');
}
}
And finally here is my viewOrder function in ProductController
//Orders View Function
public function viewOrders(User $user)
{
$products = Products_model::where('user_id', '=', $user->id)->get();
$orders = [];
foreach($products as $product){
array_merge($orders, $product->order);
}
//dd( $products);
return view('orders')->with(compact('orders'));
}
I need every seller(user) who listed the product to receive the order when another buyer(user) purchase. so far it shows
"Order ID Order Date Customer Name Customer City Customer Phone
On order model, You have a relation with a user, which means you have the buyers info.
But You don't have any relation for the seller.
So add a relation for the seller.
note: I assume that both buyer and seller are User
You must add a relation for a buyer and relation for a seller (don't forget to add them on database too. That means you need to add buyer_id and seller_id field on orders table).
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
//protected $table = 'orders';
protected $fillable = [
'buyer_id', 'seller_id', 'shipping_email', 'shipping_name', 'shipping_city', 'shipping_phone', 'billing_subtotal', 'billing_total',
];
public function products()
{
return $this->belongsToMany('App\Products_model')->withPivot('quantity');
}
public function orders(){
return $this->hasMany('App\OrderProduct', 'order_id');
}
public function buyer()
{
return $this->belongsTo(User::class, 'id', 'buyer_id');
}
public function seller()
{
return $this->belongsTo(User::class, 'id', 'seller_id');
}
}
Add these two relations to the User model. so you can call them easily.
public function buys() {
$this->hasMany(Order::class, 'buyer_id', 'id');
}
public function sells() {
$this->hasMany(Order::class, 'seller_id', 'id');
}
//Orders View Function
public function viewOrders(User $user) {
$products = Products_model::where('user_id', '=', $user->id)->get();
// all sells
$sells = $user->sells;
// all buys
$buys = $user->buys;
}
In view, you can loop it like,
#foreach($sells as $sell)
{{ $sell->orders }} //for orders.
{{ $sell->products }} //for product
#foreach($sell->orders as $order)
{{ $order->product }} //single product
#endforeach
#endforeach
I have three tables in the database. orders, products, and order_product table. this is how they look like in my phpmyAdmin https://imgur.com/a/Ud9e2Hh
I would like sellers to see orders placed by buyers in their view (dashboard). Also, buyers to be able to see their orders in their view.
Here are my relationships in models
User.php
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password', 'Seller'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
//public function isSeller() {
// return $this->seller;
//}
public function products()
{
return $this->hasMany(Products_model::class);
}
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function orders()
{
return $this->hasManyThrough(Order::class, Products_model::class, 'buyer_id', 'seller_id', 'product_id');
}
public function orderFromBuyers()
{
return $this->hasManyThrough(OrderProduct::class, Products_model::class, 'buyer_id', 'product_id');
}
public function orderFromSellers()
{
return $this->hasManyThrough(OrderProduct::class, Products_model::class, 'seller_id', 'product_id');
}
}
OrderProduct.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class OrderProduct extends Model
{
protected $table = 'order_product';
protected $fillable = ['order_id', 'buyer_id', 'seller_id','product_id', 'quantity'];
public function products()
{
return $this->belongsTo('App\Products_model');
}
public function buyer()
{
return $this->belongsTo(User::class, 'id', 'buyer_id');
}
public function seller()
{
return $this->belongsTo(User::class, 'id', 'seller_id');
}
public function order()
{
return $this->belongsTo(Order::class);
}
}
Order.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
//protected $table = 'orders';
protected $fillable = [
'shipping_email', 'shipping_name', 'shipping_city', 'shipping_phone', 'billing_subtotal', 'billing_total',
];
public function user()
{
return $this->belongsTo('App\User');
}
public function products()
{
return $this->belongsToMany('App\Products_model')->withPivot('quantity');
}
public function orders()
{
return $this->hasMany('App\OrderProduct', 'order_id');
}
}
Seller Function
// Seller Orders
public function viewOrders(User $user)
{
// $products = Products_model::where('seller_id', '=', $user->id)->get();
// all sells
$sells = $user->orderFromSellers();
dd($sells);
return view('orders')->with(compact('sells'));
}
Buyer Function
//Buyer Orders
public function myOrders()
{
$cart = session();
$orders = Auth::user()->orders;
$orders->transform(function($order, $key) {
dd($orders);
$order->cart = unserialize($order->cart);
return $order;
});
return view('myOrders', ['orders' => $orders]);
}
Right now it shows nothing. Any help on how to solve this will be appreciated.
Products_model
protected $table='products';
protected $primaryKey='id';
protected $fillable=['seller_id','pro_name','pro_price','pro_info','image','stock','category_id '];
Try by changing two function.
public function orderFromBuyers()
{
return $this->hasManyThrough(Products_model::class, OrderProduct::class, 'buyer_id', 'product_id');
}
public function orderFromSellers()
{
return $this->hasManyThrough(Products_model::class, OrderProduct::class, 'seller_id', 'product_id');
}
Or the two will be more better. Add these two functions to User model.
public function allOrderFromBuyers()
{
return $this->hasMany(OrderProduct::class, 'buyer_id');
}
public function allOrderFromSellers()
{
return $this->hasMany(OrderProduct::class, 'seller_id');
}
Then change this to,
// Seller Orders
public function viewOrders(User $user)
{
// all sells
$sells = $user->allOrderFromSellers();
dd($sells);
return view('orders')->with(compact('sells'));
}