PHP中基于键值合并两个API返回对象的实现方法
问题
我从API获取了两个对象,一个是可用订阅套餐列表,另一个是当前用户的活跃订阅及其对应状态,希望将二者合并。
第一个对象结构
This\Collection Object ( [object] => list [data] => Array ( [0] => This\Product Object ( [id] => 444 [name] => Test Plan 4 ) [1] => This\Product Object ( [id] => 333 [name] => Test Plan 3 ) [2] => This\Product Object ( [id] => 222 [name] => Test Plan 2 ) [3] => This\Product Object ( [id] => 111 [name] => Test Plan 1 ) ) [has_more] => )
第二个对象结构
Array ( [0] => This\Subscription Object ( [id] => sub_xxx [current_period_end] => 1670307654 [current_period_start] => 1667715654 [plan] => This\Plan Object ( [currency] => usd [product] => 111 ) [start_date] => 1667715654 [status] => active ) [1] => This\Subscription Object ( [id] => sub_xxx [current_period_end] => 1770507654 [current_period_start] => 1767715454 [plan] => This\Plan Object ( [currency] => usd [product] => 333 ) [start_date] => 1767715654 [status] => active ) )
预期合并结构
当subscription->plan->product与product->id匹配时,将第二个对象合并到第一个对象中,预期结构如下:
This\Collection Object ( [object] => list [data] => Array ( [0] => This\Product Object ( [id] => 444 [name] => Test Plan 4 ) [1] => This\Product Object ( [id] => 333 [name] => Test Plan 3 [subscription] => This\Subscription Object ( [id] => sub_xxx [current_period_end] => 1770507654 [current_period_start] => 1767715454 [plan] => This\Plan Object ( [currency] => usd [product] => 333 ) [start_date] => 1767715654 [status] => active ) ) [2] => This\Product Object ( [id] => 222 [name] => Test Plan 2 ) [3] => This\Product Object ( [id] => 111 [name] => Test Plan 1 [subscription] => This\Subscription Object ( [id] => sub_xxx [current_period_end] => 1670307654 [current_period_start] => 1667715654 [plan] => This\Plan Object ( [currency] => usd [product] => 111 ) [start_date] => 1667715654 [status] => active ) ) ) [has_more] => )
我知道可以通过两层foreach循环将对象转为数组后合并,但希望直接以对象形式完成合并。以下是我的尝试代码,但不知道如何正确匹配对应位置的对象:
foreach($array1 as $product) { foreach($array2 as $subscription) { if ($subscription->plan->product == $product->id){ //how do I append to the object in the right place (where the 0 is)? $array1->data[0]->subscription = $subscription->plan; } } }
解决方案
直接操作对象实现合并的关键是正确遍历集合中的产品对象并通过引用修改原对象,同时可以先把订阅列表转成以产品ID为键的数组,优化匹配效率。
优化后的代码
// 先将订阅列表转成以产品ID为键的关联数组,减少后续匹配次数 $subscriptionMap = []; foreach ($subscriptionsArray as $subscription) { $productId = $subscription->plan->product; $subscriptionMap[$productId] = $subscription; } // 遍历产品集合中的每个产品对象,直接添加订阅属性 foreach ($productCollection->data as &$product) { if (isset($subscriptionMap[$product->id])) { $product->subscription = $subscriptionMap[$product->id]; } } // 解除引用,避免后续操作意外修改对象 unset($product);
代码说明
- 构建订阅映射表:遍历订阅数组,把每个订阅用对应的产品ID作为键存到关联数组里,后续匹配时只需O(1)的时间复杂度。
- 引用遍历产品集合:使用
&$product的引用方式遍历productCollection->data,对$product的修改会直接作用于原集合中的对象。 - 匹配并添加订阅:如果当前产品ID在订阅映射表中存在,直接给产品对象添加
subscription属性并赋值对应的订阅对象。 - 解除引用:遍历结束后用
unset($product)解除引用,防止后续代码对$product的修改影响到集合中的对象。
原代码问题说明
你原代码中直接遍历$array1(This\Collection对象)的方式错误,而且$array1->data[0]->subscription会固定修改第一个产品对象,无法匹配到对应位置的产品。使用引用遍历$productCollection->data才能正确修改对应位置的产品对象。
内容的提问来源于stack exchange,提问作者tony
相关产品推荐
相关产品推荐

