Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to save entries in many to many polymorphic relationship in Laravel?

Tags:

I have an Org model and a Tag model. I want to associate tags with organizations. My database tables and Eloquent models are set up like so ...

org     id - integer     name - string     ...  tags     id - integer     name - string  taggables     id - integer     taggable_id - integer     taggable_type - string  // app/models/Org.php class Org extends Eloquent {     protected $table = "org";      ...      public function tags()     {         return $this->morphToMany('Tag', 'taggable');     } }  // app/models/Tag.php class Tag extends Eloquent {     protected $table = "tags";     public $timestamps = false;      public function org()      {         return $this->morphedByMany('Org', 'taggable');     } } 

In my view, I have a form with a multiple select box where the user can select the tags he/she wants to be associated with the organization ...

... {{ Form::select('tags[]', $tag_options, null, array(         'multiple',         'data-placeholder' => 'Select some tags')) }} ... 

... And $tag_options comes from my routes.php file ...

View::composer('*', function($view) {     $tags = Tag::all();      if(count($tags) > 0)     {         $tag_options = array_combine($tags->lists('id'),                                     $tags->lists('name'));     }     else     {         $tag_options = array(null, 'Unspecified');     }      $view->with('tag_options', $tag_options); }); 

When the form in my view is submitted, the following route will catch it to update the org model ...

Route::put('org/{org}', function(Org $org){     $org->description = Input::get('description');     $org->website = Input::get('website');     $org->tags = Input::get('tags');     $org->save();      return Redirect::to('org/'.$org->id)         ->with('message', 'Seccessfully updated page!'); }); 

Now, Input::get('tags') is just an array of the tag IDs, of the form

["1","6","8"] 

How can I use this to associate the tags with the organization?

I also have comments set up for organizations using a polymorphic relationship where I just do this ...

Route::put('org/post/{org}', function(Org $org){     $comment = new Comment;     $comment->user_id = Auth::user()->id;     $comment->body = Input::get('body');     $comment->commentable_id = $org->id;     $comment->commentable_type = 'Org';     $comment->save();      return Redirect::to('org/'.$org->id)         ->with('message', 'Seccessfully posted comment!'); }); 

However, it's not as simple with a many-to-many polymorphic relationship when I want to associate one or more tags with an organization.

Any help is appreciated, thanks!!

like image 544
chipit24 Avatar asked May 27 '14 18:05

chipit24


People also ask

Is polymorphism is many to many relationship?

A polymorphic relationship is used when you want something like Many to Many relationship, but without having to create extra tables every time you want to add a new Model to the mix. Polymorphic helps you combine all the junction tables into 1 very slim table, but at a cost.

What is polymorphic relationship laravel?

A one-to-one polymorphic relationship is a situation where one model can belong to more than one type of model but on only one association. A typical example of this is featured images on a post and an avatar for a user. The only thing that changes however is how we get the associated model by using morphOne instead.

What is MorphTo laravel?

"MorphTo" is used to define the relationship from a one-to-one or one-to-many polymorphic table to whichever model or models it is linked to. https://laravel.com/docs/5.7/eloquent-relationships#one-to-many-polymorphic-relations.


1 Answers

You can use all of the belongsToMany methods for this, for polymorphic many-to-many extends that relation:

// I would call that relation on tag in plural 'entities()' to be more accurate  $tag->entities()->save(new or existing model, array of pivot data, touch parent = true) (used on existing model) $tag->entities()->saveMany(array of new or existing models, array of arrays with pivot data) $tag->entities()->attach(existing model / id, array of pivot data, touch parent = true) $tag->entities()->sync(array of ids, detach = true) $tag->entities()->updateExistingPivot(pivot id, array of pivot data, touch) 

All of those methods work both ways of course.


Examples:

$tag = Tag::first(); $entity = Entity::find(10);  // save() works with both newly created and existing models: $tag->entities()->save(new Entity(...)); $tag->entities()->save($entity);  // saveMany() like above works with new and/or existing models: $tag->entities()->saveMany([$entity, new Entity(...)]);  // attach() works with existing model or its id: $tag->entities()->attach($entity); $tag->entities()->attach($entity->id);  // sync() works with existing models' ids: $tag->entities()->sync([1,5,10]); // detaches all previous relations $tag->entities()->sync([1,5,10], false); // does not detach previous relations, attaches new ones skipping existing ids 

Your case:

Route::put('org/{org}', function(Org $org){    $org->description = Input::get('description');   $org->website = Input::get('website');   $org->save();    $org->tags()->sync(Input::get('tags'));    // or if you don't want to detach previous tags:   // $org->tags()->sync(Input::get('tags'), false);     return Redirect::to('org/'.$org->id)     ->with('message', 'Seccessfully updated page!'); }); 
like image 132
Jarek Tkaczyk Avatar answered Sep 24 '22 02:09

Jarek Tkaczyk