{
    "href": "/post/2018/02/07/atlas-2-1-0-released-with-polymorphic-association-support/",
    "relId": "2018/02/07/atlas-2-1-0-released-with-polymorphic-association-support",
    "title": "Atlas 2.1.0 Released with \"Polymorphic Association\" Support",
    "author": "pmjones",
    "markup": "html",
    "tags": [
        {
            "href": "/tag/atlas/",
            "relId": "atlas",
            "title": "Atlas",
            "author": null,
            "created": "2020-09-21 14:37:38 UTC",
            "updated": [
                "2020-09-21 14:37:38 UTC",
                "2023-06-22 02:17:41 UTC"
            ],
            "markup": "markdown"
        },
        {
            "href": "/tag/php/",
            "relId": "php",
            "title": "PHP",
            "author": null,
            "created": null,
            "updated": [],
            "markup": "markdown"
        },
        {
            "href": "/tag/programming/",
            "relId": "programming",
            "title": "Programming",
            "author": null,
            "created": null,
            "updated": [],
            "markup": "markdown"
        }
    ],
    "created": "2018-02-07 13:40:30 UTC",
    "updated": [
        "2018-02-07 13:40:30 UTC"
    ],
    "html": "<p>I\u2019m happy to announce that I released <a href=\"https://github.com/atlasphp/Atlas.Orm\">Atlas 2.1.0</a> late yesterday. (Atlas is a data mapper for your persistence model in PHP \u2013 <em>not</em> your domain model.)</p>\n<p>In addition to some minor added informational and convenience functionality, the big addition in this release is support for many-to-one relationships by reference (aka \u201cpolymorphic association\u201d). You can see the documentation for it <a href=\"http://atlasphp.io/mapper/2.x/relationships.html#1-1-2-5\">here</a>.</p>\n<p>I.</p>\n<p>Atlas uses SQL terms for relationships instead of OOP ones (e.g., \u201cmany-to-one\u201d instead of \u201chas one\u201d). As such, the OOP term \u201cpolymorphic assocation\u201d just wasn\u2019t a good name for the feature.</p>\n<p>However, some research revealed that <del>Postgres</del><ins>ANSI SQL</ins> has a constraint type named <code>REFERENCES</code> <del>that supports the feature natively</del>:</p>\n<ul>\n<li><a href=\"https://www.postgresql.org/message-id/55CD3B20.6040502%40aklaver.com\">https://www.postgresql.org/message-id/55CD3B20.6040502%40aklaver.com</a></li>\n<li>\n<a href=\"https://www.postgresql.org/docs/9.4/static/sql-createtable.html\">https://www.postgresql.org/docs/9.4/static/sql-createtable.html</a> (search for \u201cREFERENCES\u201d)</li>\n</ul>\n<p>After trying out several alternative names, \u201cmany-to-one by reference\u201d was a much better fit than \u201cpolymorphic association.\u201d</p>\n<p>II.</p>\n<p>Because Atlas is for the persistence model, and not for the domain model, I had to wonder if this kind of behavior belongs in the database work at all. Should it happen in the domain instead?</p>\n<p>After working through the problem, the answer turned out to be that it <em>has</em> to go in the database work. You simply don\u2019t know which foreign tables to select from in the first place, without that information being represented in a relationship description. The reference column determines what the foreign table should be. If there are different values in the reference column, then you have to select from different tables to get the related rows. That can\u2019t happen once you\u2019re in the domain layer; it must happen in the persistence layer.</p>\n<p>III.</p>\n<p>Relationships-by-reference may not be a good data design choice if you are starting from scratch. See this 2009 presentation from Bill Karwin for some other alternatives:</p>\n<p><a href=\"https://www.slideshare.net/billkarwin/practical-object-oriented-models-in-sql/22\">https://www.slideshare.net/billkarwin/practical-object-oriented-models-in-sql/22</a></p>\n<p>These each have different tradeoffs, and in one case require that your database system supports parent tables.</p>\n<p>Of course, if you already have a database design that uses many-to-one relationships by reference, then you\u2019re probably stuck with it. Atlas can now help you out in this situation.</p>\n<p><strong>UPDATE:</strong> <a href=\"https://www.reddit.com/r/PHP/comments/7vw5jk/atlas_210_released_with_polymorphic_association/dtvn191/\">This Reddit comment</a> leads me to understand that I read the <code>REFERENCES</code> Postgres doc too hastily. In context of the linked mailing list message, I understood \"refcolumn\" to be on the native table, not the foreign one. So it's a standard foreign key constraint, not a specialized/extended form provided by Postgres; I confess I find it easy to believe that Postgres often supports things that other databases do not.</p>\n<hr>\n<p>You can read the Reddit commentary on this post <a href=\"https://www.reddit.com/r/PHP/comments/7vw5jk/atlas_210_released_with_polymorphic_association/\">here</a>.</p>\n"
}
