Polymorphic model only working on one model - laravel

I currently have a polymorphic relationship using a model like so:
The model is called Productable
In the model I have:
public function productable()
{
return $this->morphTo();
}
I have another model called Product that has access to the Productable model like so:
public function productDetails()
{
return $this->morphMany(Productable::class, 'productable');
}
This works as expected and I can create a record in the Productable table like so:
$p = new Product;
$p->product_name = $request->product_name;
$p->product_type = $request->product_type;
$p->category_id = $request->product_category;
$p->description = $request->product_description;
$p->save();
$p->productDetails()->create([
'product_id' => $p->id,
]);
However the issue is I have another model called Media
which also has:
public function productDetails()
{
return $this->morphMany(Productable::class, 'productable');
}
On that model I attempt to write a record like so:
$pMedia = new Media;
$pMedia->productDetails()->create([
'product_id' => $p->id,
'productable_id' => $value,
]);
The error I get is:
Integrity constraint violation: 1048 Column 'productable_id' cannot be null (SQL: insert into `productables` (`product_id`, `productable_id`, `productable_type`, `updated_at`, `created_at`) values (38, ?, App\Models\Media, 2021-03-04 18:46:51, 2021-03-04 18:46:51))
What am I doing wrong here? Shouldn't I be to write to Media in the same way? I'm wondering what I'm missing.

Related

how to sync() method additional pivot table Laravel

i have pivot table call user_privilege,
user_id,
privilege_id
house_group_id,
i use method sync for store data into pivot tabl, this is my method
$data = $this->getCollectedData($getListCollectData, $viewType, $data);
$getData = $this->crud->store($data);
$getData->getPrivilege()->sync([
'user_id' => $getData->id,
'house_group_id' => $this->request->get('house_group_id'),
'privilege_id' => 3,
]);
this is my getPrivilege() method in Users Model
public function getPrivilege()
{
return $this->belongsToMany(Privilege::class, 'user_privilege', 'user_id', 'privilege_id', 'house_group_id');
}
but when i click submit, return error like this
SQLSTATE[HY000]: General error: 1364 Field 'house_group_id' doesn't have a default value (SQL: insert into `user_privilege` (`privilege_id`, `user_id`) values (b3f08343-a8f6-4a45-b7bc-b396125634d3, ?))
when i dd($this->request->get('house_group_id')) return ID house_group_id like this
"2539d741-1526-4c42-b57a-da60e2e862d8"
this is UUID from house_group_id,
Whats wrong in My Code, how to save data with addtional pivot table ?
thanks

Laravel Polymorphic Relations: constraint violation: Duplicate entry for key 'images_imageable_id_unique

I'm building an application with 4 tables: Films, Actors, Categories and Images
There is a Polymorph relation between Images in one side and Films, Actors and Categories in the other side.
These are my models:
- Actor
class Actor extends Model
{
protected $fillable = ['name', 'image_id', 'genre', 'slug',];
public function images()
{
return $this->morphMany('App\Comment', 'imageable');
}
}
- Category
class Category extends Model
{
protected $fillable = [ 'category', 'description', 'image_id', 'slug'];
public function images()
{
return $this->morphMany('App\Comment', 'imageable');
}
}
- Film
class Film extends Model
{
protected $fillable = ['name','image_id','description','slug','trailer','year','duration','age_id','language_id','category_id'];
public function images()
{
return $this->morphMany('App\Comment', 'imageable');
}
}
- Images
class Image extends Model
{
protected $fillable = [ 'image', 'imageable_id', 'imageable_type' ];
public function imageable()
{
return $this->morphTo();.
}
}
As far as I understand the "imageable_id" in Images table is the id (INCREMENT) of the position in the other tables (film->id, category->id or actor->id)
But the "imageable_id" must be also UNIQUE.
Here is my problem:
Let's say I create the first film and associate an image to it.
Image.id = 1, imageable_id = 1 (the id of the film), imageable_type = film
Second I create an actor and associate an image to it.
Image.id = 2, imageable_id = 1 (the id of the actor).... <-- ERROR
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '7' for key 'images_imageable_id_unique
Should I remove the AUTO_INCREMENT in all tables?
Any idea on how to solve that problem?
The Store methods in my 3 Controllers (CategoriesController, FilmsControllers and ActorControllers) are similar. (I share here just the Categoriescontrollers)
public function store(CategoriesRequest $request)
{
$file = $request->file('image');
$name = time() . '-' . $file->getClientOriginalName();
$file->move('images', $name);
$last_img = Image::orderBy('id', 'desc')->first();
$category = Category::create([
'category' => $request->category,
'description' => $request->description,
'slug' => str_slug($request->category, '-'),
'image_id' => $last_img->id + 1,
]);
$image = Image::create([
'image' => $name,
'imageable_type' => 'Category',
'imageable_id' => $category->id
]);
$category->save();
Session::flash('success', 'Category successfully created!');
return redirect()->route('categories.index');
}
But the "imageable_id" must be also UNIQUE.
It can't be unique with polymorphic relationships. If you want to use polymorphic relationships it really cannot be unique, as the polymorphic relationships are connected to multiple tables and each of those tables will have their own autoincrementing ids, which are unique on their respective table, but not unique across the database.
It's possible to have unique ids across multiple tables, but rather uncommon in MySQL.
The solution is to remove the unique index from you imageable_id column on the images table.
You probably want the combination of imagaeble_id and imageable_type to be unique, which will enforce a 1-to-1 relationship, which can be done on a MySQL level.

Laravel Eloquent Saving Behavior

Is it normal behavior that Laravel requires you to save a parent model before saving a hasMany relationship? I am able to use belongsTo before the model is saved.
$team = new Team();
$team->tournament()->associate($tournament);
// $team->save(); without this line, it will throw an error
$team->players()->save(new TeamPlayer([
'user_id' => 1
]));
$team->save();
The Team model's relationships looks like this:
public function players()
{
return $this->hasMany(TeamPlayer::class);
}
public function tournament()
{
return $this->belongsTo(Tournament::class);
}
The error that is thrown is this
Integrity constraint violation: 1048 Column 'team_id' cannot be null (SQL: insert into `team_players` (`user_id`, `team_id`, `updated_at`, `created_at`) values (1, , 2017-12-18 13:32:29, 2017-12-18 13:32:29))

Multiple options to questions using eloquent

Im creating a survey app, and basically when a user selects a input type of "select" it appears a option input that can be dynamiclly increase, but that im having some issues in inserting these options in my database, im sugin the sync method to insert these options in my table, but is giving me a error of
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'toufarto.question_id' doesn't exist (SQL: select `option_question_id` from `question_id` where `id` = 11)
Here is my code:
Tables:
questions:
- id;
- input_type;
option_question
- id;
- label_option;
- question_id
My controller:
public function store(Request $request)
{
$this->validate($request, array(
'label_option' => 'max:255',
'input_type' => 'required|integer'
));
$question = new Question();
$question->input_type = $request->input_type;
$question->save();
$question->options()->sync($request->option, false);
Session::flash('success', 'success');
return back();
}
My Question Model:
public function options()
{
return $this->belongsToMany(OptionQuestion::class,'question_id','id');
}
My OptionQuestion Model:
class OptionQuestion extends Model
{
protected $table = "option_question";
}
Note: How i could add the label column to the "sync" method, since i need to insert the label from the option field of the form
As mentioned in the docs of Laravel you need to define your parameters as follows:
$this->belongsToMany(Model,table_name);
or
$this->belongsToMany(Model, table_name, table_1_key, table_2_key);
Looking at your DB schematic however it seems you should make a small adjustment.
questions
- id
- input_type;
options
- id
- label_option
option_question
- id
- question_id
- option_id
Question model
public function options()
{
return $this->belongsToMany(OptionQuestion::class);
}
Options model
public function questions()
{
return $this->belongsToMany(Question::class);
}

How to create Eloquent model with relationship?

How to create Eloquent model with relationship?
I have:
Person table
id
firstname
lastname
Employee table
id
person_id
position
I want to do something like this:
Employee::create([
'firstname' => 'Jack',
'lastname' => 'London',
'position' => 'writer'
])
I know, that can create two model and then associate their. But may be there is a way do this more beautiful?
First, you have to create relation in your Person model
class Person extends Model
{
protected $fillable = ['firstname', 'lastname'];
public function employee()
{
return $this->hasOne('App\Employee');
}
}
After that in your controller you can do:
$person = Person::create($personData);
$person->employee()->create($employeeData);
As #Alexey Mezenin mentioned you can use:
$person = Person::create(request()->all());
$person->employee()->create(request()->all());
Also inverse would be:
class Employee extends Model
{
protected $fillable = ['position'];
public function person()
{
return $this->belongsTo('App\Person');
}
}
You still need to create person first, so if you're looking for readable and consize solution, you can do is this:
$data = [
'firstname' => 'Jack',
'lastname' => 'London',
'position' => 'writer'
];
$person = Person::create($data);
$person->employee()->create($data);
I'd suggest you create a static method that creates the instance and related models. Many times you not only create a model, but you may have to populate it with some additional data and having a single createModel() method is a best practice.
In my case:
public static function createCompany($data) : Company {
$company = new Company($data);
$company->save();
$company->settings()->create();
// TODO Configure settings according to $data
$company->blog()->create();
// TODO: Create demo blog post
// TODO: Create default admin user.
// TODO: Etc.
}
All these details can be abstracted from the controller, in which I only call:
$company = Company::createCompany($request->all());

Resources