Batch translations during model hydration - #679
Conversation
|
Recheck of head [P2] Allow replacement translation loaders to bypass the default store. Reproduced on PHP 8.4 with such a loader and no Preserve this extension behavior with an override-aware fallback or overridable batch eligibility/storage, and add a regression without the default translation table. This contradicts the promised preservation of normal model overrides. The existing full suite passes (251 tests, 1529 assertions, one pre-existing risky test), so this needs additional coverage. Separately, current develop has an add/add conflict in tests/Database/Traits/TranslatableTest.php; retain both sets of tests when updating. |
Models that override the loader or table getter already skip batching, so the hydration snapshot no longer needs to route through the loader. Keep only tests that fail when a batching guarantee breaks.
Check the locale before reading row keys, and return before reading the key when no batch is active, so default-locale fetches cost the same as before.
|
@daftspunk rechecked and simplified this. Models that override
The default locale still runs one query and takes the same time (6.3 to 7.1 ms for 1000 rows on both). On MySQL or Postgres each skipped query also saves a network round trip, so the gap is larger than shown here. Ready for another pass. |
The batch must query the model's morph class on the default connection, the same storage the per-row loader reads.
|
Bravo! Thanks |
Fetching translatable models in a non-default locale runs one translation query per row during
afterFetch. This preloads the active locale's translations for the rows being hydrated, in chunks of 500 ids, and gives each model its rows beforefetchedfires, so fetched listeners still see translated values. Fetching 100 records goes from 101 queries to 2.Missing translations, the default locale, eager-loaded
translations, dirty tracking and saves behave as before. Models that overrideloadTranslatableData()orgetTranslateAttributeTable(), or whose morph class depends on the row, keep loading per row, since those can read other storage.cursor()is unchanged. Rows selected without their key also skip the translation query they used to run.