feat(meta): typed meta as attributes of the Pollora models - #400
Merged
Merged
Conversation
HasTypedMeta on Post, Page, Term, User and Comment: typed reads, checked writes stored on save, whereMeta() and one meta cache query per collection. Post models are bound to their $postType at discovery.
…erriding newCollection() Overriding newCollection() could not keep Eloquent's generic return type (PHPStan in CI). Models loaded together now join a batch on 'retrieved', primed in one update_meta_cache() call on the first typed read.
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Second half of phase 2 of « Pollora — Meta typées : document d'implémentation ». Stacked on #399 (base
feature/meta-owners; GitHub retargets it todeveloponce #399 is merged and its branch deleted).Design
HasTypedMetais onPollora\Models\Post,Page,Term,UserandComment(as the document puts it, so$user->newsletter_opt_inworks on the authenticated user).getAttribute()/setAttribute()intercept only names a schema of the object type declares (MetaSchemaRepository::declares(), an O(1) index), then find the schema for the object's subtype:post_typecolumn or$postTypefor posts, thetaxonomyrelation for terms, none for users and comments. Everything else goes to Colt/Eloquent untouched.MetaValueCaster::toStorage()immediately, kept out of the model's attributes, and written by thesavedevent through aMetaRecord(so a new model gets its ID first).$postType; users/comments: any#[UserMeta]/#[CommentMeta]). Only then does it dropmetafrom$with; each model it loads joins a batch onretrieved, and the first typed read primes the whole batch with oneupdate_meta_cache()call. (A first version overrodenewCollection(), whose generic return type PHPStan could not reconcile with Colt's models in CI.) The genericPostkeeps eager loading. Undeclared keys keep Colt's fallback (lazy relation).whereMeta():CAST(meta_value AS SIGNED)/DECIMAL(65, 10)for numbers, stored-form comparison otherwise (dates are stored in UTC with a fixed format, so they sort as strings);nullmeans the meta is absent. Operators are whitelisted (they are concatenated into the raw SQL).Post::registerPostType():MetaDiscoveryalso keeps classes extending a Colt post model and binds their$postTypedefault.ScalarParamTypeByMethodCallTypeRectoris skipped for the trait: typing$keybreaks compatibility with Eloquent's untypedgetAttribute($key)(fatal).Verified on pollora-test, temporary classes and values since removed
#[PostMeta('post')](int $tmpViews,?string $tmpSubtitle),class Article extends Post { $postType = 'post' },#[UserMeta]:Post::find()returnsApp\Cms\TmpMeta\Article.->tmpViewson each: 1 Eloquent query + 1 wpdb query (meta cache), integers; measured again after the batch rework: 20 posts, 1 wpdb query.$article->tmpViews = 999; ->tmpSubtitle = 'Typé'; ->save()→get_post_meta()returns them;'many'throws.whereMeta('tmpViews', '>=', 300)andwhereMeta('tmpSubtitle', null)return the right IDs on MySQL.User::find(1)->tmpNewsletterOptIn:false, thentrueaftersave()._edit_lock) still reads through Colt on a typed model.Tests
HasTypedMetaTest(reads by property and key, generic post model, untouched attributes, checked writes and save, defaults before save, user meta,$with, cache priming,whereMeta()SQL), repositoryforObject()/declares(), discovery binding. Full suite 1648 passed; Pint, PHPStan, Rector clean.