Arr.php 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954
  1. <?php
  2. namespace Illuminate\Support;
  3. use ArgumentCountError;
  4. use ArrayAccess;
  5. use Illuminate\Support\Traits\Macroable;
  6. use InvalidArgumentException;
  7. use Random\Randomizer;
  8. class Arr
  9. {
  10. use Macroable;
  11. /**
  12. * Determine whether the given value is array accessible.
  13. *
  14. * @param mixed $value
  15. * @return bool
  16. */
  17. public static function accessible($value)
  18. {
  19. return is_array($value) || $value instanceof ArrayAccess;
  20. }
  21. /**
  22. * Add an element to an array using "dot" notation if it doesn't exist.
  23. *
  24. * @param array $array
  25. * @param string|int|float $key
  26. * @param mixed $value
  27. * @return array
  28. */
  29. public static function add($array, $key, $value)
  30. {
  31. if (is_null(static::get($array, $key))) {
  32. static::set($array, $key, $value);
  33. }
  34. return $array;
  35. }
  36. /**
  37. * Collapse an array of arrays into a single array.
  38. *
  39. * @param iterable $array
  40. * @return array
  41. */
  42. public static function collapse($array)
  43. {
  44. $results = [];
  45. foreach ($array as $values) {
  46. if ($values instanceof Collection) {
  47. $values = $values->all();
  48. } elseif (! is_array($values)) {
  49. continue;
  50. }
  51. $results[] = $values;
  52. }
  53. return array_merge([], ...$results);
  54. }
  55. /**
  56. * Cross join the given arrays, returning all possible permutations.
  57. *
  58. * @param iterable ...$arrays
  59. * @return array
  60. */
  61. public static function crossJoin(...$arrays)
  62. {
  63. $results = [[]];
  64. foreach ($arrays as $index => $array) {
  65. $append = [];
  66. foreach ($results as $product) {
  67. foreach ($array as $item) {
  68. $product[$index] = $item;
  69. $append[] = $product;
  70. }
  71. }
  72. $results = $append;
  73. }
  74. return $results;
  75. }
  76. /**
  77. * Divide an array into two arrays. One with keys and the other with values.
  78. *
  79. * @param array $array
  80. * @return array
  81. */
  82. public static function divide($array)
  83. {
  84. return [array_keys($array), array_values($array)];
  85. }
  86. /**
  87. * Flatten a multi-dimensional associative array with dots.
  88. *
  89. * @param iterable $array
  90. * @param string $prepend
  91. * @return array
  92. */
  93. public static function dot($array, $prepend = '')
  94. {
  95. $results = [];
  96. foreach ($array as $key => $value) {
  97. if (is_array($value) && ! empty($value)) {
  98. $results = array_merge($results, static::dot($value, $prepend.$key.'.'));
  99. } else {
  100. $results[$prepend.$key] = $value;
  101. }
  102. }
  103. return $results;
  104. }
  105. /**
  106. * Convert a flatten "dot" notation array into an expanded array.
  107. *
  108. * @param iterable $array
  109. * @return array
  110. */
  111. public static function undot($array)
  112. {
  113. $results = [];
  114. foreach ($array as $key => $value) {
  115. static::set($results, $key, $value);
  116. }
  117. return $results;
  118. }
  119. /**
  120. * Get all of the given array except for a specified array of keys.
  121. *
  122. * @param array $array
  123. * @param array|string|int|float $keys
  124. * @return array
  125. */
  126. public static function except($array, $keys)
  127. {
  128. static::forget($array, $keys);
  129. return $array;
  130. }
  131. /**
  132. * Determine if the given key exists in the provided array.
  133. *
  134. * @param \ArrayAccess|array $array
  135. * @param string|int $key
  136. * @return bool
  137. */
  138. public static function exists($array, $key)
  139. {
  140. if ($array instanceof Enumerable) {
  141. return $array->has($key);
  142. }
  143. if ($array instanceof ArrayAccess) {
  144. return $array->offsetExists($key);
  145. }
  146. if (is_float($key)) {
  147. $key = (string) $key;
  148. }
  149. return array_key_exists($key, $array);
  150. }
  151. /**
  152. * Return the first element in an array passing a given truth test.
  153. *
  154. * @template TKey
  155. * @template TValue
  156. * @template TFirstDefault
  157. *
  158. * @param iterable<TKey, TValue> $array
  159. * @param (callable(TValue, TKey): bool)|null $callback
  160. * @param TFirstDefault|(\Closure(): TFirstDefault) $default
  161. * @return TValue|TFirstDefault
  162. */
  163. public static function first($array, ?callable $callback = null, $default = null)
  164. {
  165. if (is_null($callback)) {
  166. if (empty($array)) {
  167. return value($default);
  168. }
  169. foreach ($array as $item) {
  170. return $item;
  171. }
  172. return value($default);
  173. }
  174. foreach ($array as $key => $value) {
  175. if ($callback($value, $key)) {
  176. return $value;
  177. }
  178. }
  179. return value($default);
  180. }
  181. /**
  182. * Return the last element in an array passing a given truth test.
  183. *
  184. * @param array $array
  185. * @param callable|null $callback
  186. * @param mixed $default
  187. * @return mixed
  188. */
  189. public static function last($array, ?callable $callback = null, $default = null)
  190. {
  191. if (is_null($callback)) {
  192. return empty($array) ? value($default) : end($array);
  193. }
  194. return static::first(array_reverse($array, true), $callback, $default);
  195. }
  196. /**
  197. * Take the first or last {$limit} items from an array.
  198. *
  199. * @param array $array
  200. * @param int $limit
  201. * @return array
  202. */
  203. public static function take($array, $limit)
  204. {
  205. if ($limit < 0) {
  206. return array_slice($array, $limit, abs($limit));
  207. }
  208. return array_slice($array, 0, $limit);
  209. }
  210. /**
  211. * Flatten a multi-dimensional array into a single level.
  212. *
  213. * @param iterable $array
  214. * @param int $depth
  215. * @return array
  216. */
  217. public static function flatten($array, $depth = INF)
  218. {
  219. $result = [];
  220. foreach ($array as $item) {
  221. $item = $item instanceof Collection ? $item->all() : $item;
  222. if (! is_array($item)) {
  223. $result[] = $item;
  224. } else {
  225. $values = $depth === 1
  226. ? array_values($item)
  227. : static::flatten($item, $depth - 1);
  228. foreach ($values as $value) {
  229. $result[] = $value;
  230. }
  231. }
  232. }
  233. return $result;
  234. }
  235. /**
  236. * Remove one or many array items from a given array using "dot" notation.
  237. *
  238. * @param array $array
  239. * @param array|string|int|float $keys
  240. * @return void
  241. */
  242. public static function forget(&$array, $keys)
  243. {
  244. $original = &$array;
  245. $keys = (array) $keys;
  246. if (count($keys) === 0) {
  247. return;
  248. }
  249. foreach ($keys as $key) {
  250. // if the exact key exists in the top-level, remove it
  251. if (static::exists($array, $key)) {
  252. unset($array[$key]);
  253. continue;
  254. }
  255. $parts = explode('.', $key);
  256. // clean up before each pass
  257. $array = &$original;
  258. while (count($parts) > 1) {
  259. $part = array_shift($parts);
  260. if (isset($array[$part]) && static::accessible($array[$part])) {
  261. $array = &$array[$part];
  262. } else {
  263. continue 2;
  264. }
  265. }
  266. unset($array[array_shift($parts)]);
  267. }
  268. }
  269. /**
  270. * Get an item from an array using "dot" notation.
  271. *
  272. * @param \ArrayAccess|array $array
  273. * @param string|int|null $key
  274. * @param mixed $default
  275. * @return mixed
  276. */
  277. public static function get($array, $key, $default = null)
  278. {
  279. if (! static::accessible($array)) {
  280. return value($default);
  281. }
  282. if (is_null($key)) {
  283. return $array;
  284. }
  285. if (static::exists($array, $key)) {
  286. return $array[$key];
  287. }
  288. if (! str_contains($key, '.')) {
  289. return $array[$key] ?? value($default);
  290. }
  291. foreach (explode('.', $key) as $segment) {
  292. if (static::accessible($array) && static::exists($array, $segment)) {
  293. $array = $array[$segment];
  294. } else {
  295. return value($default);
  296. }
  297. }
  298. return $array;
  299. }
  300. /**
  301. * Check if an item or items exist in an array using "dot" notation.
  302. *
  303. * @param \ArrayAccess|array $array
  304. * @param string|array $keys
  305. * @return bool
  306. */
  307. public static function has($array, $keys)
  308. {
  309. $keys = (array) $keys;
  310. if (! $array || $keys === []) {
  311. return false;
  312. }
  313. foreach ($keys as $key) {
  314. $subKeyArray = $array;
  315. if (static::exists($array, $key)) {
  316. continue;
  317. }
  318. foreach (explode('.', $key) as $segment) {
  319. if (static::accessible($subKeyArray) && static::exists($subKeyArray, $segment)) {
  320. $subKeyArray = $subKeyArray[$segment];
  321. } else {
  322. return false;
  323. }
  324. }
  325. }
  326. return true;
  327. }
  328. /**
  329. * Determine if any of the keys exist in an array using "dot" notation.
  330. *
  331. * @param \ArrayAccess|array $array
  332. * @param string|array $keys
  333. * @return bool
  334. */
  335. public static function hasAny($array, $keys)
  336. {
  337. if (is_null($keys)) {
  338. return false;
  339. }
  340. $keys = (array) $keys;
  341. if (! $array) {
  342. return false;
  343. }
  344. if ($keys === []) {
  345. return false;
  346. }
  347. foreach ($keys as $key) {
  348. if (static::has($array, $key)) {
  349. return true;
  350. }
  351. }
  352. return false;
  353. }
  354. /**
  355. * Determines if an array is associative.
  356. *
  357. * An array is "associative" if it doesn't have sequential numerical keys beginning with zero.
  358. *
  359. * @param array $array
  360. * @return bool
  361. */
  362. public static function isAssoc(array $array)
  363. {
  364. return ! array_is_list($array);
  365. }
  366. /**
  367. * Determines if an array is a list.
  368. *
  369. * An array is a "list" if all array keys are sequential integers starting from 0 with no gaps in between.
  370. *
  371. * @param array $array
  372. * @return bool
  373. */
  374. public static function isList($array)
  375. {
  376. return array_is_list($array);
  377. }
  378. /**
  379. * Join all items using a string. The final items can use a separate glue string.
  380. *
  381. * @param array $array
  382. * @param string $glue
  383. * @param string $finalGlue
  384. * @return string
  385. */
  386. public static function join($array, $glue, $finalGlue = '')
  387. {
  388. if ($finalGlue === '') {
  389. return implode($glue, $array);
  390. }
  391. if (count($array) === 0) {
  392. return '';
  393. }
  394. if (count($array) === 1) {
  395. return end($array);
  396. }
  397. $finalItem = array_pop($array);
  398. return implode($glue, $array).$finalGlue.$finalItem;
  399. }
  400. /**
  401. * Key an associative array by a field or using a callback.
  402. *
  403. * @param array $array
  404. * @param callable|array|string $keyBy
  405. * @return array
  406. */
  407. public static function keyBy($array, $keyBy)
  408. {
  409. return Collection::make($array)->keyBy($keyBy)->all();
  410. }
  411. /**
  412. * Prepend the key names of an associative array.
  413. *
  414. * @param array $array
  415. * @param string $prependWith
  416. * @return array
  417. */
  418. public static function prependKeysWith($array, $prependWith)
  419. {
  420. return static::mapWithKeys($array, fn ($item, $key) => [$prependWith.$key => $item]);
  421. }
  422. /**
  423. * Get a subset of the items from the given array.
  424. *
  425. * @param array $array
  426. * @param array|string $keys
  427. * @return array
  428. */
  429. public static function only($array, $keys)
  430. {
  431. return array_intersect_key($array, array_flip((array) $keys));
  432. }
  433. /**
  434. * Select an array of values from an array.
  435. *
  436. * @param array $array
  437. * @param array|string $keys
  438. * @return array
  439. */
  440. public static function select($array, $keys)
  441. {
  442. $keys = static::wrap($keys);
  443. return static::map($array, function ($item) use ($keys) {
  444. $result = [];
  445. foreach ($keys as $key) {
  446. if (Arr::accessible($item) && Arr::exists($item, $key)) {
  447. $result[$key] = $item[$key];
  448. } elseif (is_object($item) && isset($item->{$key})) {
  449. $result[$key] = $item->{$key};
  450. }
  451. }
  452. return $result;
  453. });
  454. }
  455. /**
  456. * Pluck an array of values from an array.
  457. *
  458. * @param iterable $array
  459. * @param string|array|int|null $value
  460. * @param string|array|null $key
  461. * @return array
  462. */
  463. public static function pluck($array, $value, $key = null)
  464. {
  465. $results = [];
  466. [$value, $key] = static::explodePluckParameters($value, $key);
  467. foreach ($array as $item) {
  468. $itemValue = data_get($item, $value);
  469. // If the key is "null", we will just append the value to the array and keep
  470. // looping. Otherwise we will key the array using the value of the key we
  471. // received from the developer. Then we'll return the final array form.
  472. if (is_null($key)) {
  473. $results[] = $itemValue;
  474. } else {
  475. $itemKey = data_get($item, $key);
  476. if (is_object($itemKey) && method_exists($itemKey, '__toString')) {
  477. $itemKey = (string) $itemKey;
  478. }
  479. $results[$itemKey] = $itemValue;
  480. }
  481. }
  482. return $results;
  483. }
  484. /**
  485. * Explode the "value" and "key" arguments passed to "pluck".
  486. *
  487. * @param string|array $value
  488. * @param string|array|null $key
  489. * @return array
  490. */
  491. protected static function explodePluckParameters($value, $key)
  492. {
  493. $value = is_string($value) ? explode('.', $value) : $value;
  494. $key = is_null($key) || is_array($key) ? $key : explode('.', $key);
  495. return [$value, $key];
  496. }
  497. /**
  498. * Run a map over each of the items in the array.
  499. *
  500. * @param array $array
  501. * @param callable $callback
  502. * @return array
  503. */
  504. public static function map(array $array, callable $callback)
  505. {
  506. $keys = array_keys($array);
  507. try {
  508. $items = array_map($callback, $array, $keys);
  509. } catch (ArgumentCountError) {
  510. $items = array_map($callback, $array);
  511. }
  512. return array_combine($keys, $items);
  513. }
  514. /**
  515. * Run an associative map over each of the items.
  516. *
  517. * The callback should return an associative array with a single key/value pair.
  518. *
  519. * @template TKey
  520. * @template TValue
  521. * @template TMapWithKeysKey of array-key
  522. * @template TMapWithKeysValue
  523. *
  524. * @param array<TKey, TValue> $array
  525. * @param callable(TValue, TKey): array<TMapWithKeysKey, TMapWithKeysValue> $callback
  526. * @return array
  527. */
  528. public static function mapWithKeys(array $array, callable $callback)
  529. {
  530. $result = [];
  531. foreach ($array as $key => $value) {
  532. $assoc = $callback($value, $key);
  533. foreach ($assoc as $mapKey => $mapValue) {
  534. $result[$mapKey] = $mapValue;
  535. }
  536. }
  537. return $result;
  538. }
  539. /**
  540. * Run a map over each nested chunk of items.
  541. *
  542. * @template TKey
  543. * @template TValue
  544. *
  545. * @param array<TKey, array> $array
  546. * @param callable(mixed...): TValue $callback
  547. * @return array<TKey, TValue>
  548. */
  549. public static function mapSpread(array $array, callable $callback)
  550. {
  551. return static::map($array, function ($chunk, $key) use ($callback) {
  552. $chunk[] = $key;
  553. return $callback(...$chunk);
  554. });
  555. }
  556. /**
  557. * Push an item onto the beginning of an array.
  558. *
  559. * @param array $array
  560. * @param mixed $value
  561. * @param mixed $key
  562. * @return array
  563. */
  564. public static function prepend($array, $value, $key = null)
  565. {
  566. if (func_num_args() == 2) {
  567. array_unshift($array, $value);
  568. } else {
  569. $array = [$key => $value] + $array;
  570. }
  571. return $array;
  572. }
  573. /**
  574. * Get a value from the array, and remove it.
  575. *
  576. * @param array $array
  577. * @param string|int $key
  578. * @param mixed $default
  579. * @return mixed
  580. */
  581. public static function pull(&$array, $key, $default = null)
  582. {
  583. $value = static::get($array, $key, $default);
  584. static::forget($array, $key);
  585. return $value;
  586. }
  587. /**
  588. * Convert the array into a query string.
  589. *
  590. * @param array $array
  591. * @return string
  592. */
  593. public static function query($array)
  594. {
  595. return http_build_query($array, '', '&', PHP_QUERY_RFC3986);
  596. }
  597. /**
  598. * Get one or a specified number of random values from an array.
  599. *
  600. * @param array $array
  601. * @param int|null $number
  602. * @param bool $preserveKeys
  603. * @return mixed
  604. *
  605. * @throws \InvalidArgumentException
  606. */
  607. public static function random($array, $number = null, $preserveKeys = false)
  608. {
  609. $requested = is_null($number) ? 1 : $number;
  610. $count = count($array);
  611. if ($requested > $count) {
  612. throw new InvalidArgumentException(
  613. "You requested {$requested} items, but there are only {$count} items available."
  614. );
  615. }
  616. if (empty($array) || (! is_null($number) && $number <= 0)) {
  617. return is_null($number) ? null : [];
  618. }
  619. $keys = (new Randomizer)->pickArrayKeys($array, $requested);
  620. if (is_null($number)) {
  621. return $array[$keys[0]];
  622. }
  623. $results = [];
  624. if ($preserveKeys) {
  625. foreach ($keys as $key) {
  626. $results[$key] = $array[$key];
  627. }
  628. } else {
  629. foreach ($keys as $key) {
  630. $results[] = $array[$key];
  631. }
  632. }
  633. return $results;
  634. }
  635. /**
  636. * Set an array item to a given value using "dot" notation.
  637. *
  638. * If no key is given to the method, the entire array will be replaced.
  639. *
  640. * @param array $array
  641. * @param string|int|null $key
  642. * @param mixed $value
  643. * @return array
  644. */
  645. public static function set(&$array, $key, $value)
  646. {
  647. if (is_null($key)) {
  648. return $array = $value;
  649. }
  650. $keys = explode('.', $key);
  651. foreach ($keys as $i => $key) {
  652. if (count($keys) === 1) {
  653. break;
  654. }
  655. unset($keys[$i]);
  656. // If the key doesn't exist at this depth, we will just create an empty array
  657. // to hold the next value, allowing us to create the arrays to hold final
  658. // values at the correct depth. Then we'll keep digging into the array.
  659. if (! isset($array[$key]) || ! is_array($array[$key])) {
  660. $array[$key] = [];
  661. }
  662. $array = &$array[$key];
  663. }
  664. $array[array_shift($keys)] = $value;
  665. return $array;
  666. }
  667. /**
  668. * Shuffle the given array and return the result.
  669. *
  670. * @param array $array
  671. * @return array
  672. */
  673. public static function shuffle($array)
  674. {
  675. return (new Randomizer)->shuffleArray($array);
  676. }
  677. /**
  678. * Sort the array using the given callback or "dot" notation.
  679. *
  680. * @param array $array
  681. * @param callable|array|string|null $callback
  682. * @return array
  683. */
  684. public static function sort($array, $callback = null)
  685. {
  686. return Collection::make($array)->sortBy($callback)->all();
  687. }
  688. /**
  689. * Sort the array in descending order using the given callback or "dot" notation.
  690. *
  691. * @param array $array
  692. * @param callable|array|string|null $callback
  693. * @return array
  694. */
  695. public static function sortDesc($array, $callback = null)
  696. {
  697. return Collection::make($array)->sortByDesc($callback)->all();
  698. }
  699. /**
  700. * Recursively sort an array by keys and values.
  701. *
  702. * @param array $array
  703. * @param int $options
  704. * @param bool $descending
  705. * @return array
  706. */
  707. public static function sortRecursive($array, $options = SORT_REGULAR, $descending = false)
  708. {
  709. foreach ($array as &$value) {
  710. if (is_array($value)) {
  711. $value = static::sortRecursive($value, $options, $descending);
  712. }
  713. }
  714. if (! array_is_list($array)) {
  715. $descending
  716. ? krsort($array, $options)
  717. : ksort($array, $options);
  718. } else {
  719. $descending
  720. ? rsort($array, $options)
  721. : sort($array, $options);
  722. }
  723. return $array;
  724. }
  725. /**
  726. * Recursively sort an array by keys and values in descending order.
  727. *
  728. * @param array $array
  729. * @param int $options
  730. * @return array
  731. */
  732. public static function sortRecursiveDesc($array, $options = SORT_REGULAR)
  733. {
  734. return static::sortRecursive($array, $options, true);
  735. }
  736. /**
  737. * Conditionally compile classes from an array into a CSS class list.
  738. *
  739. * @param array $array
  740. * @return string
  741. */
  742. public static function toCssClasses($array)
  743. {
  744. $classList = static::wrap($array);
  745. $classes = [];
  746. foreach ($classList as $class => $constraint) {
  747. if (is_numeric($class)) {
  748. $classes[] = $constraint;
  749. } elseif ($constraint) {
  750. $classes[] = $class;
  751. }
  752. }
  753. return implode(' ', $classes);
  754. }
  755. /**
  756. * Conditionally compile styles from an array into a style list.
  757. *
  758. * @param array $array
  759. * @return string
  760. */
  761. public static function toCssStyles($array)
  762. {
  763. $styleList = static::wrap($array);
  764. $styles = [];
  765. foreach ($styleList as $class => $constraint) {
  766. if (is_numeric($class)) {
  767. $styles[] = Str::finish($constraint, ';');
  768. } elseif ($constraint) {
  769. $styles[] = Str::finish($class, ';');
  770. }
  771. }
  772. return implode(' ', $styles);
  773. }
  774. /**
  775. * Filter the array using the given callback.
  776. *
  777. * @param array $array
  778. * @param callable $callback
  779. * @return array
  780. */
  781. public static function where($array, callable $callback)
  782. {
  783. return array_filter($array, $callback, ARRAY_FILTER_USE_BOTH);
  784. }
  785. /**
  786. * Filter items where the value is not null.
  787. *
  788. * @param array $array
  789. * @return array
  790. */
  791. public static function whereNotNull($array)
  792. {
  793. return static::where($array, fn ($value) => ! is_null($value));
  794. }
  795. /**
  796. * If the given value is not an array and not null, wrap it in one.
  797. *
  798. * @param mixed $value
  799. * @return array
  800. */
  801. public static function wrap($value)
  802. {
  803. if (is_null($value)) {
  804. return [];
  805. }
  806. return is_array($value) ? $value : [$value];
  807. }
  808. }