Closed sidewaysglance closed 1 year ago
Depends how many models you have. You could just have a links table for each model and have your morphs to other models in there? That'd seem to be the simplest way in my mind at least.
E.g songs (id, other fields) song_links (contains song_id, linkable_id, linkable_type) books (id, other fields) book_links (contains book_id, linkable_id, linkable_type)
You could of course then use something like https://github.com/chelout/laravel-relationship-events to add the inverse of the relationship whenever an event happens, so that it exists on both sides, for ease of retrieval etc.
Mm the thing is there are currently 10 models, so currently 10*10 polymorphic m2m relationships. In the future I can see there might be many more and it will be hugely unwieldy.
Ideally I would be able to use a trait on models which would provide the functionality I am after.
I am working with https://github.com/omaximus/laravel-pivot-polymorph, it does work as described, but it's immature, I have to keep a maintain a fork which I'm updating with framework versions etc.
Hi @sidewaysglance, This is not possible with the package at the moment.
I am working with https://github.com/omaximus/laravel-pivot-polymorph, it does work as described
Can you share the relationship you are using here?
Hi, I am using morphsTo() in a trait:
public function connections()
{
return $this->morphsTo('link_from', 'link_to', 'connections');
}
There is a lot more going off in there which I don't understand but might be really useful. In an ideal world it would be possible to store a string with the connection, again I don't think it's possible.
They are based in Ukraine and don't feel happy chucking GitHub issues at them when they probably have a lot on their minds.
If someone would be willing to take it on I would be willing to pay low hundreds of gbp to support development / documentation
I'd still suggest a morph for each model with its own table in the interim.
It's easily stubbable, so you could generate the tables and relations using commands to save yourself a load of pain.
@sidewaysglance Thanks for your generous donation! I'll look into this topic.
I found an approach using one of my other packages that merges multiple relationships with SQL views: https://github.com/staudenmeir/laravel-merged-relations
For everyone of your connected models, you need to create a view that merges native MorphToMany
relationships to all the other models (Post
-> Book
, Post
-> Song
etc.).
use Staudenmeir\LaravelMergedRelations\Facades\Schema;
$models = [Book::class, Post::class, Song::class]; // TODO
foreach ($models as $model) {
$relations = [];
foreach ($models as $relatedModel) {
if ($model !== $relatedModel) {
$relations[] = (new $model)
->morphToMany($relatedModel, 'link_from', 'connections', 'link_from_id', 'link_to_id')
->where('link_to_type', $relatedModel);
}
}
Schema::createOrReplaceMergeView(
(new $model)->getTable() . '_connections',
$relations
);
}
use Staudenmeir\LaravelMergedRelations\Eloquent\HasMergedRelationships;
trait HasConnections
{
use HasMergedRelationships;
public function connections()
{
return $this->mergedRelation($this->getTable() . '_connections');
}
}
class Post extends Model
{
use HasConnections;
}
Post::with('connections')->get();
It's not as elegant as with the other package, but you don't have to worry about the ongoing Laravel support.
Might make a quick command for generating this to save manual intervention for the future.
Thanks for the advice all!
All the best
Hi
I have a situation where I have been asked to provide functionality that could create links from "anything to anything".
For example with a normal polymorphic relationship, I might be needing to link a comment to either a song or a book.
But what I need to do is, with one table, link a song to a book, link a book to a comment, link anything to anything. Something like:
I have been using this: https://github.com/omaximus/laravel-pivot-polymorph
But the documentation is v poor, I don't fully understand it, & I don't need much of what it has to offer.
Can anyone suggest another solution?