I'm having issues with how to deal with tables relationships in laravel. i have three tables Orders table, Order_product table and User table. A User can either be described as a seller or a buyer depending on if they listed or bought something. Now when a user submit order form i get an error
"General error: 1364 Field 'seller_id' doesn't have a default value (SQL: insert into order_product (order_id, product_id, quantity, `up ▶"
Here is how those tables look like in phpmyAdmin
https://imgur.com/a/fvxo1YZ
And below are the 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');
}
}
Products_model
<?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', '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');
}
}
Here is my store Function
public function store(Request $request)
{
//Insert into orders table
$order = Order::create([
'buyer_id' => auth()->user() ? auth()->user()->id : null,
'shipping_email' => $request->email,
'shipping_name' => $request->name,
'shipping_city' => $request->city,
'shipping_phone' => $request->phone,
// 'error' => null,
]);
//Insert into order product table
if ($order) {
foreach(session('cart') as $productId =>$item) {
if (empty($item)) {
continue;
}
OrderProduct::create([
'order_id' => $order->id ?? null,
'product_id' => $productId,
// $products=DB::table('products')->where('id',$id)->get();
'quantity' => $item['quantity'],
//dd($item)
]);
}
}
//Empty Cart After order created
$cart = session()->remove('cart');
return redirect()->route('confirmation.index')->with('success_message', 'Thank you! Your payment has been successfully accepted!');
}
the error is very specific:
General error: 1364 Field 'seller_id' doesn't have a default value
(SQL: insert into order_product
And looking at the code you posted, assume it happens here:
OrderProduct::create([
'order_id' => $order->id ?? null,
'product_id' => $productId,
'quantity' => $item['quantity'],
]);
You can not create an OrderProduct without giving a value to seller_id when that field doesn't have a default value or is not nullable in DB. So, give it a value when creating the record. Looking at the models, I think you could do something like this:
$product = products_model::find($productId);
OrderProduct::create([
'order_id' => $order->id ?? null,
'product_id' => $productId,
'quantity' => $item['quantity'],
'seller_id' => $product->seller_id,
'buyer_id' => $order->buyer_id,
]);
You need to send value of the seller id.
$order = Order::create([
'buyer_id' => auth()->user() ? auth()->user()->id : null,
'seller_id' => $request->seller_id,
'shipping_email' => $request->email,
'shipping_name' => $request->name,
'shipping_city' => $request->city,
'shipping_phone' => $request->phone,
// 'error' => null,
]);
or you can remove the seller_id on your Order Table because you can get the seller information from the Product Model
Post model to relationship one to one,
and User model to relationship one to many.
Related
i have manytomany relation ship between categroy and product
category model
class Attribute extends Model implements Auditable
{
use HasFactory, AuditableTrait;
protected $fillable = ['category','sub_categ'];
public function products(): BelongsToMany
{
return $this->belongsToMany(Product::class);
}
}
product model
class Product extends Model implements Auditable
{
use HasFactory, AuditableTrait;
protected $table = 'products';
protected $fillable = ['name','price','description', 'details'];
public function products(): BelongsToMany
{
return $this->belongsToMany(Product::class);
}
}
the pivot table
Schema::create('attributes_products', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->foreignId('product_id')->constrained('products')->onUpdata('cascade')->onDelete('cascade');
$table->foreignId('attribute_id')->constrained('attributes')->onUpdata('cascade')->onDelete('cascade');
});
what should i do after this i did not undrestant how attach will work in pivot table and return it with the product as json response ?
edit
this is the schema i am working on
i want to give each product it's own category
and this is my product controller store function
public function store(Request $request)
{
$request->validate([
'name' => 'required',
'price' => 'required|numeric',
'description' => 'required',
'details' => 'required',
'stocks' => 'required|numeric',
//'discounts' => 'required|numeric'
]);
$product = Product::create($request->only('name','price','description', 'details'));
$product->stocks()->create([
'quantity' => $request->stocks,
'product_id' => $product->id
]);
$product->discounts()->create([
//'discount' => $request->discounts,
'product_id' => $product->id
]);
if($request->hasFile('images'))
{
foreach( $request->file('images') as $file)
{
$file->store('public/products');
$product->images()->create([
'product_id' => $product->id,
'file_path' => $file->hashName()
]);
}
}
$product->categories()->sync([
'product_id' => $product->id,
'attribute_id'=> 1
]);
}
In your product model check your relation.
public function categories()
{
return $this->belongsToMany(Category::class);
}
Also usually the pivot table needs to have only 2 Ids. So in your case only 2 columns: product_id & category_id.
Your table name by convention should be category_product, otherwise, you should specify it on the second parameter on the relationship.
Fix this too, you got a typo on update:
$table->foreignId('attribute_id')->constrained('attributes')->onUpdate('cascade')->onDelete('cascade');
And finally to attach:
$product = Product::find(1);
$product->categories()->attach($categoryId);
All is explained very well on documentation too: https://laravel.com/docs/8.x/eloquent-relationships
I'm working on a project where users can sell and also buy products, and in my database there are two tables(orders and order products table)in orders tables there's a buyer_id and seller_id. So if a user buys product it shows buyer_id now the problem comes to seller_id. It doesn't show the seller_id.
Here is my code.
User.php
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()
{
$this->hasManyThrough(OrderProduct::class, Products_model::class, 'buyer_id', 'product_id');
}
public function orderFromSellers()
{
$this->hasManyThrough(OrderProduct::class, Products_model::class, 'seller_id', 'product_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', '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');
}
}
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');
}
My store Function
public function store(Request $request)
{
//Insert into orders table
$order = Order::create([
'buyer_id' => auth()->user() ? auth()->user()->id : null,
'shipping_email' => $request->email,
'shipping_name' => $request->name,
'shipping_city' => $request->city,
'shipping_phone' => $request->phone,
// 'error' => null,
]);
//Insert into order product table
if ($order) {
foreach(session('cart') as $productId =>$item) {
if (empty($item)) {
continue;
}
OrderProduct::create([
'order_id' => $order->id ?? null,
'product_id' => $productId,
// $products=DB::table('products')->where('id',$id)->get();
'quantity' => $item['quantity'],
//dd($item)
]);
}
}
CheckoutController(function)
public function store(Request $request)
{
//Insert into orders table
$order = Order::create([
'buyer_id' => auth()->user() ? auth()->user()->id : null,
'seller_id' => auth()->user() ? auth()->user()->id : null, 'shipping_email' => $request->email,
'shipping_name' => $request->name,
'shipping_city' => $request->city,
'shipping_phone' => $request->phone,
// 'error' => null,
]);
//Insert into order product table
if ($order) {
foreach(session('cart') as $productId =>$item) {
if (empty($item)) {
continue;
}
OrderProduct::create([
'order_id' => $order->id ?? null,
'product_id' => $productId,
// $products=DB::table('products')->where('id',$id)->get();
'quantity' => $item['quantity'],
//dd($item)
]);
}
}
//Empty Cart After order created
$cart = session()->remove('cart');
return redirect()->route('confirmation.index')->with('success_message', 'Thank you! Your payment has been successfully accepted!');
}
ProductController(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'));
My View File(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>
#endforeach
#endforeach
Let's see if we can find probably the easiest solution. I can see from your product model that it has a seller_id field. When you are looping over the products to display them, why don't you use a hidden input which has a value of seller_id? i.e.
#foreach ( $products as $product )
<form> // assuming you will be creating a form for the buy button
<input type="hidden" value={{ $product->seller_id }} />
<button type="submit">Buy Now</button>
</form>
#endforeach
Now in your Controller, you will have access to seller_id as
$seller_id = request('seller_id');
hope that helps
There is an issue that is every product must have a seller. If then, you should use buyer and seller relation with OrderProduct model not Order model.
Or you may collect seller by make relation with product-seller.
First
remove 'buyer_id', 'seller_id', from Order model and orders migration.
Second
Add 'buyer_id', 'seller_id', from OrderProduct model and order_product migration.
Third
Transfer relation buyer and seller from Order model to OrderProduct model
Fourth
When you create the OrderProduct data, you add buyer_id and seller_id. Finally catch and use them as you want.
Fifth
Dont forget to update buys and sells relation Order model to OrderProduct model on User model.
Sixth
you have to updatye orders relation on User model. It should be ,
public function orderFromBuyers()
{
$this->hasManyThrough(OrderProduct::class, Products_model::class, 'buyer_id', 'product_id');
}
and
public function orderFromSellers()
{
$this->hasManyThrough(OrderProduct::class, Products_model::class, 'seller_id', 'product_id');
}
Note that, You cannot make them from one function.
Finally update any other things relation to these changes.
Add this to OrderProduct.php
public function order()
{
return $this->belongsTo(Order::class);
}
Update product Controller
public function viewOrders(User $user)
{
// $products = Products_model::where('seller_id', '=', $user->id)->get();
// all sells
$sells = $user->orderFromSellers;
return view('orders')->with(compact('sells'));
}
//dd( $products);
Update your view to,
#foreach($sells as $sell)
<tr>
<td>{{$sell->orders}}</td>
<td>{{$sell->products}}</td>
<td>{{$sell->created_at}}</td>
<td>{{$sell->order->shipping_name}}</td>
<td>{{$sell->order->shipping_city}}</td>
<td>{{$sell->order->shipping_phone}}</td>
<td>
View Order Details
</td>
</tr>
#endforeach
On CheckoutController (store) update to,
public function store(Request $request)
{
//Insert into orders table
$order = Order::create([
'shipping_email' => $request->email,
'shipping_name' => $request->name,
'shipping_city' => $request->city,
'shipping_phone' => $request->phone,
// 'error' => null,
]);
//Insert into order product table
if ($order) {
foreach(session('cart') as $productId =>$item) {
if (empty($item)) {
continue;
}
OrderProduct::create([
'buyer_id' => auth()->user() ? auth()->user()->id : null,
'seller_id' => $products=DB::table('products')->find('productId')? $products=DB::table('products')->find('productId')->seller_id : null,
'order_id' => $order->id ?? null,
'product_id' => $productId,
// $products=DB::table('products')->where('id',$id)->get();
'quantity' => $item['quantity'],
//dd($item)
]);
}
}
//Empty Cart After order created
$cart = session()->remove('cart');
return redirect()->route('confirmation.index')->with('success_message', 'Thank you! Your payment has been successfully accepted!');
}
I am trying to get (order_id, product_id and quantity) to be stored in Order Product table in database, so when placed an order it should store orders and order product in database . But now it only store orders and gives this error "Trying to get property of non-object".
I have tried some solutions from other sources but still not working.
CheckoutController
<?php
namespace App\Http\Controllers;
use App\Order;
use App\OrderProduct;
use Illuminate\Http\Request;
use cart;
class CheckoutController extends Controller
{
public function index()
{
return view('checkout');
}
public function create()
{
//
}
public function store(Request $request)
{
//Insert into orders table
$order = Order::create([
'user_id' => auth()->user() ? auth()->user()->id : null,
'shipping_email' => $request->email,
'shipping_name' => $request->name,
'shipping_city' => $request->city,
'shipping_phone' => $request->phone,
// 'error' => null,
]);
//Insert into order product table
$cart = session('cart');
foreach(session('cart') as $products) {
OrderProduct::create([
'order_id' => $order->id,
'product_id' => $products->id,
'quantity' => $products->quantity,
]);
}
$cart = session()->remove('cart');
return redirect()->route('confirmation.index')->with('success_message', 'Thank you! Your payment has been successfully accepted!');
}
public function show($id)
{
//
}
public function edit($id)
{
//
}
public function update(Request $request, $id)
{
//
}
public function destroy($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'];
}
Order.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
protected $fillable = [
'user_id', 'shipping_email', 'shipping_name', 'shipping_city', 'shipping_phone',
];
public function user()
{
return $this->belongsTo('App\User');
}
public function products()
{
return $this->belongsToMany('App\Product')->withPivot('quantity');
}
}
Updated:
I have changed code now it shows quantity but can't show product_id it gives error "Trying to get property of non-object"
if ($order) {
foreach(session('cart') as $products) {
if (empty($products)) {
continue;
}
OrderProduct::create([
'order_id' => $order->id ?? null,
'product_id' => $products['id'], //-> This not working
'quantity' => $products['quantity'],
]);
I'm kinda new to Laravel and I hope someone we'll be able to give me some help.
I apologize for my english
So I'm trying to develop an application with some friends to manage our food by sending alert when the peremption date is near.
I'm developing the API, the actual structure is this way:
A user,
A product,
A basket containing the user_id, the product_id and of course the peremption date.
So now when I make a call to get the User 'stock' on my API I wish I could get something like this:
{
'id' : 1,
'peremption_date': XX-XX-XX,
'product' : {
'id' : 3,
'name': bblablabala,
'brand' : blablabala
},
'id' : 2,
'peremption_date': XX-XX-XX,
'product' : {
'id' : 4,
'name': bblablabala,
'brand' : blablabala
},
}
So I took a look on resources and saw that if I define the right relations, this could do the stuff for my output.
I'll link you my actual class declarations and their resources:
User:
//user.php
class User extends Authenticatable
{
use Notifiable, HasApiTokens;
protected $fillable = [
'name', 'email', 'password',
];
protected $hidden = [
'password', 'remember_token',
];
public function baskets()
{
return $this->hasMany(Basket::class);
}
}
Product:
//Product.php
class Product extends Model
{
protected $table = 'products';
protected $fillable = ['code_barre', 'product_name', 'generic_name', 'brand', 'quantity'];
public function basket()
{
return $this->belongsToMany(Basket::class);
}
}
//productResource.php
class ProductResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'code_barre' => $this->code_barre,
'product_name' => $this->product_name,
'generic_name' => $this->generic_name,
'brand' => $this->brand,
'quantity' => $this->quantity,
'created_at' => (string) $this->created_at,
'updated_at' => (string) $this->updated_at,
];
}
}
Basket:
//Basket.php
class Basket extends Model
{
protected $table = 'baskets';
protected $fillable = ['user_id', 'product_id', 'dlc_date'];
public function user()
{
return $this->belongsTo(User::class);
}
public function product()
{
return $this->hasOne(Product::class);
}
}
//BasketResource.php
class BasketResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'dlc_date' => (string) $this->dlc_date,
'created_at' => (string) $this->created_at,
'updated_at' => (string) $this->updated_at,
'product' => $this->product
];
}
}
So when I try to store a new basket in my store method:
//BasketController.php
public function store(Request $request)
{
$this->product->storeProduct($request->input('code_barre'));
$att = DB::table('products')
->where('code_barre', '=', $request->input('code_barre'))
->first();
$basket = Basket::create([
'user_id' => $request->user()->id,
'product_id' => $att->id,
'dlc_date' => $request->input('dlc_date')
]);
return new BasketResource($basket);
}
I get the following error (this one)
saying than products.id_basket does not exist and its right, it's not supposed to exist. This is Basket who have a product_id. so I know this is coming from the relationship I declared but I can't figure how to do it right.
Can someone come and save me ???
Thanks a lot, I hope you understood me !
Wish you a good day
As I look at your Basket model, it seems you have to change your:
public function product()
{
return $this->hasOne(Product::class);
}
to:
public function product()
{
return $this->belongsTo(Product::class);
}
Because you have product_id in your baskets table. To use hasOne() relation, you will need to remove product_id from baskets table and add basket_id to products table, because hasOne() relation is something like hasMany(), only calling ->first() instead of ->get()
I need to update the items for specific order with Eloquent.
I have this models:
class Orders extends \Illuminate\Database\Eloquent\Model
{
public $timestamps = false;
protected $fillable = ['items_array'];
public function items()
{
return $this->hasMany(Items::class, 'order_id', 'order_id');
}
public function setItemsArrayAttribute($data)
{
$this->items()->whereIn('article_id', array_map(function($item){
return $item['article_id'];
}, $data['items']))->update($data);
}
}
class Items extends \Illuminate\Database\Eloquent\Model
{
protected $table = 'order_to_items';
public $timestamps = false;
protected $fillable = ['internal_code'];
public function order()
{
return $this->belongsTo(Orders::class, 'order_id', 'order_id');
}
}
I have the api response like that:
$response = [
'message'=>'some',
'order_id'=>'111-222-333',
'items'=>[
[
'article_id' => 'R-320108',
'internal_code' => 333
],
[
'article_id' => 'R-320116',
'internal_code' => 444
],
]
];
So I make this
$order = Orders::where('order_id', $response['order_id'])->with('items')->first();
and I was trying to make this:
$order->update([
'is_sent' => true,
'items_array' => $response['items']
]);
but that doesn't work. Is there any way to match the related model with API response and make update?
Thanks!
You can use save():
$order->is_sent = true;
$order->items_array = $response['items'];
$order->save();
Or update():
$order = Orders::where('order_id', $response['order_id'])
->update([
'is_sent' => true,
'items_array' => $response['items']
]);