2121 *
2222 * This allows accessing all distantly related models through an intermediate one.
2323 */
24- class HasManyThrough extends Relation
24+ class HasManyThrough extends ThroughRelation
2525{
2626 use PerParentLimit;
2727
@@ -30,62 +30,6 @@ class HasManyThrough extends Relation
3030 */
3131 public RelationTypes $ type = RelationTypes::HasManyThrough;
3232
33- /**
34- * The intermediate model
35- */
36- protected Model $ throughModel ;
37-
38- /**
39- * The foreign key on the intermediate table
40- */
41- protected string $ firstKey ;
42-
43- /**
44- * The foreign key on the final table
45- */
46- protected string $ secondKey ;
47-
48- /**
49- * The local key on the parent table
50- */
51- protected string $ localKey ;
52-
53- /**
54- * The local key on the intermediate table
55- */
56- protected string $ secondLocalKey ;
57-
58- /**
59- * Constructor
60- *
61- * @param Model $parentModel The parent model instance
62- * @param string $relatedModelClass The final related model class
63- * @param string $throughModelClass The intermediate model class
64- * @param string|null $firstKey Foreign key on intermediate table
65- * @param string|null $secondKey Foreign key on final table
66- * @param string|null $localKey Local key on parent table
67- * @param string|null $secondLocalKey Local key on intermediate table
68- */
69- public function __construct (
70- Model $ parentModel ,
71- string $ relatedModelClass ,
72- string $ throughModelClass ,
73- ?string $ firstKey = null ,
74- ?string $ secondKey = null ,
75- ?string $ localKey = null ,
76- ?string $ secondLocalKey = null ,
77- ) {
78- $ this ->parentModel = $ parentModel ;
79- $ this ->model = model ($ relatedModelClass );
80- $ this ->throughModel = model ($ throughModelClass );
81- $ this ->localKey = $ localKey ?? get_model_property ($ parentModel , 'primaryKey ' );
82- $ this ->firstKey = $ firstKey ?? get_foreign_key ($ parentModel );
83- $ this ->secondLocalKey = $ secondLocalKey ?? get_model_property ($ this ->throughModel , 'primaryKey ' );
84- $ this ->secondKey = $ secondKey ?? get_foreign_key ($ this ->throughModel );
85- $ this ->primaryKey = $ this ->localKey ;
86- $ this ->foreignKey = $ this ->secondKey ; // For compatibility with base class
87- }
88-
8933 public function eagerLoad (array $ results , string $ returnType , string $ relationName ): array
9034 {
9135 if ($ results === []) {
@@ -100,26 +44,11 @@ public function eagerLoad(array $results, string $returnType, string $relationNa
10044 }
10145
10246 // Build the through query with joins
103- $ throughTable = get_model_property ($ this ->throughModel , 'table ' );
104- $ finalTable = get_model_property ($ this ->model , 'table ' );
105-
106- // Start with the final model
107- $ this ->model
108- ->select ("{$ finalTable }.* " )
109- ->join (
110- $ throughTable ,
111- "{$ throughTable }. {$ this ->secondLocalKey } = {$ finalTable }. {$ this ->secondKey }" ,
112- 'inner ' ,
113- )
114- ->whereIn ("{$ throughTable }. {$ this ->firstKey }" , $ ids );
115-
116- // Apply custom query callback if provided
117- if ($ this ->queryCallback !== null ) {
118- ($ this ->queryCallback )($ this ->model );
119- }
47+ $ this ->buildThroughJoinQuery ($ ids );
12048
12149 if ($ this ->hasLimitInQuery ()) {
12250 // Add partition column to SELECT for window function (with DB prefix)
51+ $ throughTable = get_model_property ($ this ->throughModel , 'table ' );
12352 $ prefixedThroughTable = $ this ->model ->db ->prefixTable ($ throughTable );
12453 $ this ->model ->select ("{$ prefixedThroughTable }. {$ this ->firstKey }" , false );
12554
@@ -151,23 +80,8 @@ public function lazyLoad(array|object $parent): array
15180 {
15281 $ id = $ this ->getPrimaryKeyValue ($ parent );
15382
154- $ throughTable = get_model_property ($ this ->throughModel , 'table ' );
155- $ finalTable = get_model_property ($ this ->model , 'table ' );
156-
157- // Build query with joins
158- $ this ->model
159- ->select ("{$ finalTable }.* " )
160- ->join (
161- $ throughTable ,
162- "{$ throughTable }. {$ this ->secondLocalKey } = {$ finalTable }. {$ this ->secondKey }" ,
163- 'inner ' ,
164- )
165- ->where ("{$ throughTable }. {$ this ->firstKey }" , $ id );
166-
167- // Apply custom query callback if provided
168- if ($ this ->queryCallback !== null ) {
169- ($ this ->queryCallback )($ this ->model );
170- }
83+ // Build the through query with joins
84+ $ this ->buildLazyThroughQuery ($ id );
17185
17286 return $ this ->model ->findAll ();
17387 }
0 commit comments