silk
silk copied to clipboard
Relationships
The ability to define relationships between models.
At a minimum, this should include:
- One to One
- One to Many
- Many to Many
The relationship should be polymorphic, so we can use the same syntax for all types:
PostModel <--> TermModel
TermModel <--> TermModel
PostModel <--> PostModel
Depends on #5.
First off, thank you so much for creating this! It's an awesome library! I'd like to help you on this feature as I found myself needing this as well. Did you have any plan for this already? May I send you some of the ideas I has so far? Let me know! Thanks!
Thanks Nicolo! I want to emulate Eloquent pretty closely as far as the way it is used. The challenging bit here is of course the implementation. I'm open to any ideas you may have though, feel free to share!
Case by case, here are my thoughts:
Post <---> Term
Should be written as:
public function tags(){
$this->hasOneOrMany(Tags::class);
}
The main issue I can foresee here is that Terms
do not allow for the use of a WP_query
object.
We would have to escalate to wp_get_object_terms
. We could return a Collection
instance and map the results to cast each result to a Tag::class
.
TermModel <---> PostModel
Should be written as:
public function posts(){
$this->hasOneOrMany(Post::class);
}
We could delegate this to the QueryBuilder
instance we already have in the Post::class
and simply set the tax_query
options. The benefit here is that it would already be wrapped in a Collection
.
We could detect which instance is passed to the hasOneOrMany
with the is_subclass_of
. This would enable us to be polymorphic:
- if it extends a
Term
object -> case 1 - if it extends a
Post
object -> case 2
I'm not entirely sure on how to approach the Term <---> Term
or Post <---> Post
cases though. Not even sure on what it would actually be the scenario in wordpress to create these relationships. (my bad, never really dug that much into these!). If you could provide a couple of examples I'd be more than happy to have a think about it and see how that would fit in.
Another way would be to completely delegate all of the assertions to a $wpdb
handler, but I feel like it's more likely to give problems since developers can alterate the behaviour of the query with filter (such as post_where
and so on)
Thanks Nicolo,
I think you're right in that Post to Term relationships are probably the best place to start here, as this is probably the best supported relationship in WordPress.
Like you said, a post model would have a method for getting the relationship as a query, that we should be able to continue chaining configuration on.
/**
* @return \Silk\Term\Query\Builder
*/
public function terms()
{
return $this->hasMany(Tag::class);
}
Since models have a common interface for starting a query that is configured to return models of itself, we should be able to do something like:
public function hasMany($modelClass)
{
return $modelClass::query();
}
Post to post relationships would require defining the convention that is used to relate them in the database. This could be using a taxonomy-based relationship (posts of a common term), or by post meta (likely for 1-1 relationship). I believe posts-to-posts (the plugin) uses its own table for this. This plugin is really easy to work with in a plugin, but might be hard to do as a library.
Another consideration is when a taxonomy can be used with multiple post types. In this case, there needs to be a way to handle the results when mapping into models, as queries currently only support returning a collection of a single model class. The problem gets compounded when exceptions will be thrown if a model is instantiated using a post/term of the wrong type/taxonomy.
For this reason, again, probably best to start with Post to Term and the inverse relationships due to the lack of extra tables, meta, etc.
Hi Evan,
Thank you for your insight! I agree that the post-to-post is tricky. I don't see any way of doing that that doesn't involve including some sort of functionality in the admin area to manage this kind of relationships.
We could tackle that with some meta data to avoid having to create additional tables but it will still be a custom solution, not something natively supported by WordPress (meaning we would have to include some sort of custom metabox in the admin area to allow users to modify/manage this).
I started creating a trait to manage the post-to-term
and term-to-post
relationships.
Are you happy for me to create a PR with relevant tests once it's ready?