@@ -60,13 +60,88 @@ trait QueryBuilderRelationsWithTrait
6060 // return $this;
6161 // }
6262
63+ protected $ withs = [];
64+
6365 // public function with(...$props)
6466 // {
6567 // $this->withs = array_merge($this->withs, $props);
6668 // echo dumpOrm($this->withs);
6769 // return $this;
6870 // }
6971
72+ public function with (...$ props )
73+ {
74+ // echo dumpOrm($props);
75+ $ withs = [];
76+ foreach ($ props as &$ prop ) {
77+ if (is_string ($ prop )) {
78+ $ withs [] = $ this ->levels (explode ('. ' , $ prop ));
79+ } else if (is_array ($ prop )) {
80+ $ withs [] = $ this ->recursiveArrayWith ($ prop );
81+ }
82+ }
83+ $ this ->withs = array_merge_recursive (...$ withs );
84+ // echo dumpOrm($this->withs);
85+ return $ this ;
86+ }
87+
88+ protected function levels ($ levels , $ value = [])
89+ {
90+ $ levels = array_reverse ($ levels );
91+ $ with = $ value ;
92+ foreach ($ levels as $ level ) {
93+ $ with = [$ level => $ with ];
94+ }
95+ return $ with ;
96+ }
97+
98+ protected function recursiveArrayWith (array $ props )
99+ {
100+ $ withs = [];
101+ foreach ($ props as $ i => $ prop ) {
102+ $ key = is_string ($ i ) ? $ i : $ prop ;
103+ $ val = is_string ($ i ) ? $ prop : [];
104+
105+ if (is_array ($ val )) $ val = $ this ->recursiveArrayWith ($ val );
106+ else if (is_string ($ val )) $ val = [$ val => []];
107+
108+ // вложенность связей в ключе
109+ if (is_string ($ key )) {
110+ $ levels = explode ('. ' , $ key );
111+ if (count ($ levels ) > 1 ) {
112+ $ key = array_shift ($ levels );
113+ $ val = $ this ->levels ($ levels , $ val );
114+ }
115+ }
116+ // слияние значений уже существующего ключа
117+ if (isset ($ withs [$ key ]) && is_array ($ withs [$ key ])) {
118+ if (is_numeric ($ val )) return ;
119+ if (is_string ($ val )) $ val = [$ val ];
120+ $ val = array_merge ($ withs [$ key ], $ val );
121+ }
122+ $ withs [$ key ] = $ val ;
123+ }
124+ return $ withs ;
125+ }
126+
127+ // protected function recursiveArrayWith(array $props)
128+ // {
129+ // $withs = [];
130+ // foreach ($props as $i => $prop) {
131+ // $names = is_string($i) ? explode('.', $i) : [];
132+ // if (is_string($prop)) {
133+ // $withs[] = array_merge($names, explode('.', $prop));
134+ // } else if (is_array($prop)) {
135+ // $subs = $this->recursiveArrayWith($prop);
136+ // foreach ($subs as $sub) {
137+ // $withs[] = array_merge($names, $sub);
138+ // }
139+ // }
140+ // }
141+ // return $withs;
142+ // }
143+
144+
70145 protected function applyWiths (array $ ids , array &$ models )
71146 {
72147 // // $withOne = array_filter($this->withOne, fn($with) => $with->isOne());
@@ -77,6 +152,32 @@ protected function applyWiths(array $ids, array &$models)
77152 // foreach ($this->withOne as [$relation, $columns, $query]) {
78153 // $this->applyWith($relation, $columns, $query);
79154 // }
155+ // return;
156+ if (1 > count ($ this ->withs )) return ;
157+ $ keys = array_keys ($ this ->withs );
158+ foreach ($ keys as $ key ) {
159+ $ this ->applyWith ($ key , $ this ->withs [$ key ], $ ids , $ models );
160+ }
161+ }
162+
163+ protected function applyWith ($ key , $ val , array $ ids , array &$ models )
164+ {
165+ $ relation = $ this ->getRelation ($ key );
166+ $ qb = (new static ($ this ->db , $ relation ->foreignModel ));
167+ $ qb ->whereIn ($ relation ->foreignKey , $ ids );
168+ if (!empty ($ val )) $ qb ->with ($ val );
169+ $ subModels = $ qb ->get ();
170+ if (!$ subModels ) return ;
171+ $ idsLocal = [];
172+ foreach ($ subModels as $ subModel ) {
173+ $ idsLocal [] = $ subModel ->primaryValue ();
174+ foreach ($ models as $ model ) {
175+ if ($ model ->{$ relation ->localKey } == $ subModel ->{$ relation ->foreignKey }) {
176+ $ model ->addRelated ($ relation ->name , $ subModel );
177+ break ;
178+ }
179+ }
180+ }
80181 }
81182
82183 // protected function applyWith(
0 commit comments