@@ -229,6 +229,7 @@ protected function processAutoJoins(Builder $query, string $tableName): void
229229 $ this ->collectAutoJoinPathsFromConditions ($ this ->queryConfig ['conditions ' ] ?? [], $ autoJoinPaths );
230230 $ this ->collectAutoJoinPathsFromGroupBy ($ this ->queryConfig ['groupBy ' ] ?? [], $ autoJoinPaths );
231231 $ this ->collectAutoJoinPathsFromSortBy ($ this ->queryConfig ['sortBy ' ] ?? [], $ autoJoinPaths );
232+ $ this ->collectAutoJoinPathsFromComputedColumns ($ this ->queryConfig ['computed_columns ' ] ?? [], $ autoJoinPaths , $ tableName );
232233
233234 // dedupe and sort shortest->longest so parent joins first
234235 $ autoJoinPaths = array_values (array_unique ($ autoJoinPaths ));
@@ -288,6 +289,22 @@ protected function collectAutoJoinPathsFromSortBy(array $sortBy, array &$autoJoi
288289 }
289290 }
290291
292+ protected function collectAutoJoinPathsFromComputedColumns (array $ computedColumns , array &$ autoJoinPaths , string $ rootTable ): void
293+ {
294+ foreach ($ computedColumns as $ computedColumn ) {
295+ $ expression = $ computedColumn ['expression ' ] ?? '' ;
296+ if (empty ($ expression )) {
297+ continue ;
298+ }
299+
300+ // Extract relationship paths from the expression
301+ $ paths = $ this ->extractRelationshipPathsFromExpression ($ expression , $ rootTable );
302+ foreach ($ paths as $ path ) {
303+ $ autoJoinPaths [] = $ path ;
304+ }
305+ }
306+ }
307+
291308 protected function applyAutoJoinPath (Builder $ query , string $ rootTable , string $ fullPath ): void
292309 {
293310 // Already joined?
@@ -963,8 +980,8 @@ protected function buildComputedColumns(Builder $query, array &$selects): void
963980 throw new \InvalidArgumentException ("Invalid computed column ' {$ name }': {$ errors }" );
964981 }
965982
966- // Extract and create auto -joins for relationship paths in the expression
967- $ this -> createJoinsForComputedColumn ( $ query , $ expression , $ tableName );
983+ // Note: Auto -joins for computed column relationships are now created earlier in processAutoJoins()
984+ // This ensures joins exist before aggregate expressions are resolved
968985
969986 // Resolve column references in the expression to use proper table aliases
970987 $ resolvedExpression = $ this ->resolveComputedColumnReferences ($ expression , $ tableName );
@@ -1159,12 +1176,16 @@ protected function validateQueryConfig(): void
11591176 }
11601177
11611178 /**
1162- * Extract relationship paths from a computed column expression and create necessary joins .
1179+ * Extract relationship paths from a computed column expression.
11631180 *
11641181 * This method parses the expression to find column references like "asset.financials.monthly_hire_revenue"
1165- * and ensures that all necessary auto-joins are created for the relationship paths.
1182+ * and returns the relationship paths (e.g., "asset.financials").
1183+ *
1184+ * @param string $expression The computed column expression
1185+ * @param string $rootTable The root table name (not used currently but kept for consistency)
1186+ * @return array Array of relationship paths
11661187 */
1167- protected function createJoinsForComputedColumn ( Builder $ query , string $ expression , string $ rootTable ): void
1188+ protected function extractRelationshipPathsFromExpression ( string $ expression , string $ rootTable ): array
11681189 {
11691190 // First, expand any computed column references in the expression
11701191 $ computedColumns = $ this ->queryConfig ['computed_columns ' ] ?? [];
@@ -1202,7 +1223,7 @@ protected function createJoinsForComputedColumn(Builder $query, string $expressi
12021223 preg_match_all ('/\b([a-z_][a-z0-9_]*\.[a-z_][a-z0-9_]*(?:\.[a-z_][a-z0-9_]*)*)\b/i ' , $ cleanedExpression , $ matches );
12031224
12041225 if (empty ($ matches [1 ])) {
1205- return ;
1226+ return [] ;
12061227 }
12071228
12081229 // Extract unique relationship paths (everything except the final column name)
@@ -1217,14 +1238,21 @@ protected function createJoinsForComputedColumn(Builder $query, string $expressi
12171238 }
12181239 }
12191240
1220- // Create auto-joins for each unique relationship path
1221- foreach (array_keys ($ relationshipPaths ) as $ path ) {
1222- try {
1223- $ this ->applyAutoJoinPath ($ query , $ rootTable , $ path );
1224- } catch (\Exception $ e ) {
1225- // If the join fails, it might not be a valid relationship path
1226- // Just continue - the error will be caught later when resolving the column
1227- }
1228- }
1241+ return array_keys ($ relationshipPaths );
1242+ }
1243+
1244+ /**
1245+ * Extract relationship paths from a computed column expression and create necessary joins.
1246+ *
1247+ * This method parses the expression to find column references like "asset.financials.monthly_hire_revenue"
1248+ * and ensures that all necessary auto-joins are created for the relationship paths.
1249+ *
1250+ * @deprecated This method is now redundant as join creation happens in processAutoJoins
1251+ */
1252+ protected function createJoinsForComputedColumn (Builder $ query , string $ expression , string $ rootTable ): void
1253+ {
1254+ // This method is now a no-op since joins are created earlier in processAutoJoins
1255+ // Keeping it for backward compatibility but it does nothing
1256+ return ;
12291257 }
12301258}
0 commit comments