From 3976e52f433ffd6b0e065b4757b5a4c5b9b92511 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 24 Mar 2026 13:37:42 +0000 Subject: [PATCH] perf: lazy-load Workspace relationships to reduce N+1 queries Add explicit $with = [] to prevent any auto-eager-loading of the 30+ relationships defined on the Workspace model. Provide scopeWithCommon() for eager-loading core tenant relationships (users, members, teams, workspacePackages, namespaces) and scopeWithCommonCounts() as a lighter alternative using withCount() for listing pages. Fixes #21 Co-Authored-By: Claude Opus 4.6 (1M context) --- Models/Workspace.php | 52 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/Models/Workspace.php b/Models/Workspace.php index 490bc64..edd1f71 100644 --- a/Models/Workspace.php +++ b/Models/Workspace.php @@ -54,6 +54,17 @@ class Workspace extends Model { use HasFactory; + /** + * Relationships that should be eager-loaded by default. + * + * Explicitly empty to prevent N+1 queries when listing workspaces. + * Use scopeWithCommon() to eager-load the most frequently needed + * relationships, or call ->with() explicitly for specific use cases. + * + * @var array + */ + protected $with = []; + protected static function newFactory(): WorkspaceFactory { return WorkspaceFactory::new(); @@ -778,6 +789,47 @@ class Workspace extends Model return $query->orderBy('sort_order'); } + /** + * Scope to eager-load the most commonly needed relationships. + * + * Use this when listing workspaces or rendering dashboards to avoid + * N+1 queries. Only loads core tenant relationships that are almost + * always needed; module-specific relationships (social, analytics, + * trust, notify, commerce, etc.) should be loaded explicitly. + * + * Example: Workspace::withCommon()->paginate(20) + */ + public function scopeWithCommon($query) + { + return $query->with([ + 'users', + 'members', + 'teams', + 'workspacePackages', + 'namespaces', + ]); + } + + /** + * Scope to add commonly needed relationship counts. + * + * Lighter alternative to withCommon() when only counts are needed + * (e.g. admin listing pages). Uses withCount() to add _count + * columns without loading full relationship collections. + * + * Example: Workspace::withCommonCounts()->paginate(20) + */ + public function scopeWithCommonCounts($query) + { + return $query->withCount([ + 'users', + 'members', + 'teams', + 'workspacePackages', + 'invitations', + ]); + } + /** * Convert to array format used by WorkspaceService. */