Skip to content

fix(manager): remove per-node alias queries from resource tree - #8

Closed
elcreator wants to merge 2 commits into
3.5.xfrom
fix-tree-alias-n-plus-one
Closed

elcreator wants to merge 2 commits into
3.5.xfrom
fix-tree-alias-n-plus-one

Conversation

@elcreator

Copy link
Copy Markdown
Owner

Summary

Rendering a fully expanded resource tree called makeUrl() once per node. With aliaslistingfolder or full_aliaslisting = 1, that meant one SiteContent query per node just to rebuild alias paths: about 10k queries for a 10k-resource site.

  • UrlProcessor::primeAliasListings() fills the alias listing from rows the tree query already selects. getAliasListing() now builds the path of a primed entry on first use, and loads a parent that wasn't primed with one query, then reuses it.
  • Priming runs only when UrlProcessor::usesLazyAliasListing() is true. makeUrl() uses the same check. In the default mode the tree takes its aliases from the site cache, exactly as before.
  • Tree rows skip Eloquent's toArray() and go through normalizeTreeNodeRow(), a fixed list of int/bool casts that matches SiteContent::$casts. Null values and strings are left alone, so OnManagerNodePrerender / OnManagerNodeRender payloads keep their types.
  • CI image: GD is enabled, and the installer directory is renamed before the HTTP smoke test.

Results (10,000 resources, 100 categories, full tree expanded)

  • Tree request time went from about 8.1 s to about 1.4 s.
  • The rendered tree HTML is byte-for-byte identical to the output before the change: 10,108 nodes, same URLs.

Tests

  • core/tests/Unit/UrlProcessorAliasListingTest.php has 6 tests:
    • primed paths are built without database queries, with a guard at the Eloquent connection resolver
    • a parent folder with a hidden alias is skipped in the path
    • entries already loaded from the site cache are kept
    • a parent that wasn't primed is loaded once and reused (SQLite)
    • which settings turn lazy mode on
    • the row cast whitelist
  • Full Pest suite passes. The one exception is ApacheConfigHardeningTest, which needs a git checkout and failed only because the suite ran in a non-git copy.
  • PHPStan: no errors.

🤖 Generated with Claude Code

elcreator and others added 2 commits September 23, 2026 23:31
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Full-tree rendering issued one SiteContent lookup per node to rebuild its
alias path. Prime the alias listing from the tree query when URLs are
resolved lazily (aliaslistingfolder / full_aliaslisting), and normalise tree
rows with a cast whitelist instead of Eloquent toArray() so plugin payloads
keep the same types.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@elcreator

Copy link
Copy Markdown
Owner Author

Opened upstream instead: evolution-cms#2476

@elcreator elcreator closed this Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant