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!!
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.
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.
"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.
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!'); });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With