Trying to get the product_id from table one then inserting it to table two, but gives back an error
1048 Column 'product_id' cannot be null (SQL: insert into product_details (product_id, category, brand, provider_id) values (, Peripherals, Riders, 1))
Code:
$product = Product::create([
'product_name' => $request['product_name'],
'quantity' => $request['quantity']
]);
$product->save();
$product_id = $product->id;
$productDetails = ProductDetails::create([
'product_id' => $product_id,
'category' => $request['category'],
'brand' => $request['brand'],
'provider_id' => $request['provider_id']
]);
Fillable for productdetails model
protected $fillable = ['product_id', 'category', 'brand', 'provider_id'];
Database structure: (Just remembered, just a while ago I made some changes on my database that was the time when this error popped out.)
Products:
Schema::create('products', function (Blueprint $table) {
$table->increments('product_id');
$table->string('product_name');
$table->integer('quantity');
Product Details:
Schema::create('product_details', function (Blueprint $table) {
$table->integer('product_id')->unsigned();
$table->string('category',255);
$table->string('brand',255);
$table->integer('provider_id')->unsigned();
$table->foreign('product_id')
->references('product_id')
->on('products')
->onDelete('cascade');
$table->timestamps();
});
This has been solved,
It was just a simple mistake on my part. I should've been using 'product_id' at '$product_id = $product->id' instead of 'id'. Apologies to everyone.
Before inserting into ProductDetails check if Product is saved or not. Also check your fillable field in your ProductDetails model whether you have added product_id or not.
$product = Product::create([
'product_name' => $request['product_name'],
'quantity' => $request['quantity']
]);
if($product) {
$productDetails = ProductDetails::create([
'product_id' => $product->id,
'category' => $request['category'],
'brand' => $request['brand'],
'provider_id' => $request['provider_id']
]);
}
Update your fillable field like below:
protected $fillable = ['product_id', 'category', 'brand', 'provider_id'];
Update
If your primary key is product_id, you should call $product->product_id
Hey you have to change your fillable property like this:
protected $fillable = ['product_id', 'category', 'brand', 'provider_id'];
I don't think you need to use save() method. after create() method you can get model object and get the id from it directly but make sure your id in db is id not product_id.
$product = Product::create([
'product_name' => $request['product_name'],
'quantity' => $request['quantity']
]);
if($product){
$productDetails = ProductDetails::create([
'product_id' => $product->id,
'category' => $request['category'],
'brand' => $request['brand'],
'provider_id' => $request['provider_id']
]);
}else{
echo "Something went wrong";
}
You shouldn't run a save() method after running a create; its redundant.
You can run a db transaction in a try and catch to know what exactly is going wrong.
try {
\DB::transaction(function () use($request) {
$product = Product::create([
'product_name' => $request['product_name'],
'quantity' => $request['quantity']
]);
$productDetails = ProductDetails::create([
'product_id' => $product->id,
'category' => $request['category'],
'brand' => $request['brand'],
'provider_id' => $request['provider_id']
]);
});
dd('successful');
} catch (\Exception $e) {
dd( $e->getMessage() );
}
You will need to specify either a fillable or guarded attribute on the model, as all Eloquent models protect against mass-assignment by default.
Fillable you specify which fields are mass-assignable in your model, So in the model you need to add also product_id:
Model:
protected $fillable = ['product_id', 'category', 'brand', 'provider_id'];
////only the field names inside the array can be mass-assign
Automatically assumes your primary key column is going to be id. In order for this to work correctly, you should set your primary key in your model product.php:
protected $primaryKey = 'product_id';
Related
Hello I faced the following error:
SQLSTATE[HY000]: General error: 1364 Field 'title' doesn't have a default value.
It happens when I try to update amount of views on specific post.
I've just set default value of points while initializing it specified in the model in $attributes table.
Posts table migration:
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->longText('text');
$table->integer('points');
$table->bigInteger('views');
$table->integer('user_id')->unsigned()->nullable();
$table->integer('is_closed');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('set null');
});
}
Post model:
const POINTS = 0;
const VIEWS = 0;
const IS_CLOSED = 0;
protected $attributes = [
'points' => self::POINTS,
'views' => self::VIEWS,
'is_closed' => self::IS_CLOSED,
'title' => null,
'text' => null,
'user_id' => null,
];
protected $fillable = [
'title',
'text',
'user_id',
];
My Service where I try to increment the value of views:
public function incrementPostViews($id)
{
$post = $this->post->findOrFail($id);
$post->views++;
return $post->save();
}
I did use the Request rule but only while creating new post:
public function rules()
{
return [
'title' => ['required', 'max:50'],
'text' => ['required', 'max:1000'],
'user_id' => ['numeric', 'nullable'],
];
}
So by default the points, views and is_closed fields are set to 0 while creating new Post. To be honest I do not have any ideas why it is causing an error.
Update:
In Post model I've changed the $attributes array and added title, text and user_id which default value is set to null. Those three fields stays in $fillable array also. I'm not sure if it's the right way to fix it. If it's not, please correct me.
In the migration there are not changes made.
All changes are visible above.
You declared your title item as required in your table but you didn't declare a default value. And your insert operation doesn't give a value for that column, so it fails.
The easiest way to fix this is probably to declare title as nullable instead.
But if you have a good reason to make it required, you'll have to revisit the way you insert your rows so you can offer a value for that column.
You must create THE post first, once that post has been created you can then update its attributes.
$user = Post::create([
'title' => $request->title,
'text' => $request->text,
'points' => 0,
'views' => 0,
'is_closed' => $request->is_closed,
]);
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
So, I have a pivot table called user_filmscores, where the users can ''follow (watching, dropped, hold-on...)'' a film and add a rating on it.
In the userController I have this function:
public function userFilm(Request $request){
$data = $request->all();
$validator=Validator::make($data,[
'user_id' => 'required',
'film_id' => 'required',
'state' => 'required',
'score' => 'nullable'
]);
if($validator->fails()){
return response()->json([
'ok' => false,
'error' => $validator->messages(),
]);
}
$film = Film::find($data['film_id']);
$user = User::find($data['user_id']);
$filmId=$data['film_id'];
$userId=$data['user_id'];
//Check if the relationship exists (I tried many methods but always the same result with false)
/*$hasFilm = User::where('id', $data['user_id'])->whereHas('film', function ($q) use ($filmId) {
$q->where('id', $filmId);
})->exists();*/
$hasFilm = $user->film()->where('film_id', '=', $filmId)->exists();
/*$user->film()->sync($film->getKey(), [
'film_id' => $data['film_id'],
'user_id' => $data['user_id'],
'state' => $data['state'],
'score'=> $data['score']
]);*/
if(User::where('id', $userId)->where('id')){
$user->film()->attach($film->getKey(), [
'film_id' => $data['film_id'],
'user_id' => $data['user_id'],
'state' => $data['state'],
'score'=> $data['score']
]);
}else{
$user->film()->detach($film->getKey());
}
}
In the final part of the code, I want to check if the relationship between the user and the film exists, to make an action or another. But when I try to check if the relationship exists, it always returns me a false.
I thought to do it like, if there is a relationship, first delete the old relationship, and then create a new one.
I don't know if there is a better way to do it.
User model has this function:
public function film(){
return $this->belongsToMany('App\Models\Film', 'user_filmscores', 'user_id', 'film_id', 'state', 'score');
}
Film model has this function:
public function user(){
return $this->belongsToMany('App\Models\Film', 'user_filmscores', 'film_id', 'user_id', 'state', 'score');
}
Users table:
Films table:
User_filmscores table:
I've got a master table called Product with the following columns:
id
product_id
product_type
name
price
in_stock
upc
Where ’id' and 'product_id' are unique (id is the PK)
I'll have other tables for different kinds of products (types).
All these other tables will have Product’s properties plus
Other properties on their own depending on the type of product
(I.e. clothing, records, etc.).
So I created a Product model using Polymorphic relationships
as follows:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
protected $fillable = [
'product_id',
'product_type',
'name',
'price',
'in_stock',
'upc'
];
public function categorizable()
{
return $this->morphTo();
}
}
And, for instance, a records model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Record extends Model
{
protected $fillable = [
'artist_id',
'title',
'label',
'code',
'format',
'number_of_discs',
'image',
'description'
];
public function products()
{
return $this->morphMany('\App\Product', 'categorizable');
}
public function artist()
{
return $this->belongsTo(Artist::class);
}
public function track()
{
return $this->hasMany(Track::class);
}
public function getItemDetails(int $itemId): array {
}
}
Whereas the columns for record are:
id
artist_id
product_id
title
label
This is the best way I could think of relating these tables.
My questions are:
Is there a better approach to this specific problem?
In this case (using polymorphic relationships), how would I insert a product?
How could I query a product in order to return data from
Both product table and record table? I mean, not a raw query
Since that I can do, but how to perform this query using
Eloquent?
Your code is perfect except product_id column in Record. You don't need that column, just remove it
how would I insert a product?
$product = Product::create([
'name' => $request->name,
'price' => $request->price,
'in_stock' => $request->in_stock
]);
$record->products()->save($product);
OR
$record->products()->create([
'name' => $request->name,
'price' => $request->price,
'in_stock' => $request-> in_stock,
'product_id' => $record->id,
'product_type' => get_class($record)
]);
If you need to create both then do it like this
$record = Record::create([
'artist_id' => $request->artist_id
'title' => $request->title,
'label' => $request->label,
'code' => $request->code,
]);
$product = Product::create([
'name' => $request->name,
'price' => $request->price,
'in_stock' => $request->in_stock
]);
$record->products()->save($product);
Fetch Data
$product = Product::with('categorizable')->find(2);
$product->categorizable; //this will be either Record, Cloth... instance
Similarly for record
$record = Record::with('products')->find(1);
$record->products; //it will give you product collection
For details you can look https://laravel.com/docs/5.1/eloquent-relationships#polymorphic-relations
The inserted row key,value are empty !!
\App\Product::find(1)->getProductMeta()->create([
'key' => 'a key',
'value' => 'a value'
]);
query SQL :
insert into `product_metas` (`product_id`) values (?)
Product:
function getProductMeta(){
return $this->hasMany('App\ProductMeta');
}
ProductMeta:
protected $fillable = ['key','value'];
Migration:
Schema::create('product_metas', function (Blueprint $table) {
$table->increments('id');
$table->integer('product_id')->unsigned()->index();
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');;
$table->string('key')->index();
$table->text('value')->nullable();
});
I don't see anything wrong with your code. Just try one of these methods to create the relationship item.
Add this to ProductMeta model
protected $fillable = ['key', 'value', 'product_id'];
In your controller do this so that you can get a valid product.
$product = Product::findOrFail(1);
Then
$product->getProductMeta()->create([
'key' => 'a key',
'value' => 'a value'
]);
Or
\App\ProductMeta::create([
'key' => 'a key',
'value' => 'a value',
'product_id' => $product->id
]);
Or
$productMeta = new \App\ProductMeta;
$productMeta->key = 'a key';
$productMeta->value = 'a value';
$productMeta->product_id = $product->id;
$productMeta->save();
i'v solved my problem with remove function __construct in my Model .
I don't know why i'v made a __construct method !
you have to make relation in both models eg. Product model and admin model
for example you say in your product model
public function admin(){
return $this->belongsTo(Admin::class, 'admin_id');
}
and in your admin model
public function product(){
return $this->hasMany(Product::class);
}
like this both tables and models will be related to each other.
PS: I don't know your exact model and tables so i just assume admins as publishers and products as post you can change it to your table names.