code: public static function replaceRecursive($iterable1, $iterable2)
      {
          Assert::allIsIterable([$iterable1, $iterable2]);
  
          if ($iterable1 instanceof Traversable) {
              $iterable1 = iterator_to_array($iterable1);
          }
          if ($iterable2 instanceof Traversable) {
              $iterable2 = iterator_to_array($iterable2);
          }
  
          $merged = $iterable1;
  
          foreach ($iterable2 as $key => $value) {
              if ($value instanceof Traversable) {
                  $value = iterator_to_array($value);
              }
              if (is_array($value) && static::isAssociative($value)
                  && isset($merged[$key]) && \is_iterable($merged[$key])
              ) {
                  $merged[$key] = static::replaceRecursive($merged[$key], $value);
              } elseif ($value === null && isset($merged[$key]) && \is_iterable($merged[$key])) {
                  // Convert iterable to array to be consistent.
                  if ($merged[$key] instanceof Traversable) {
                      $merged[$key] = iterator_to_array($merged[$key]);
                  }
                  continue;
              } else {
                  $merged[$key] = $value;
              }
          }
  
          return $merged;
      }
docs: Replaces values from second iterable into first iterable recursively.
  
  This differs from {@see array_replace_recursive} in a couple ways:
  
  - Lists (indexed arrays) from second array completely replace list in first array.
  
  - Null values from second array do not replace lists or associative arrays in first
  (they do still replace scalar values).
  
  This converts all `Traversable` objects to arrays.
  
  @param iterable $iterable1
  @param iterable $iterable2
  
  @return array The combined array