Advertisement
BakirovRoman

Why not need make ArrayHelper final in Yii3

Sep 8th, 2021
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 9.25 KB | None | 0 0
  1. <?php
  2.  
  3. /**
  4.  * https://t.me/yii3ru/63240
  5.  *
  6.  * Почему не стоит финализировать ArrayHelper
  7.  * https://github.com/yiisoft/arrays/blob/edec11c95cbc3ee5b6b1b9739a7405a5a325b731/src/ArrayHelper.php
  8.  */
  9. namespace app\commands;
  10.  
  11. use yii\console\Controller;
  12. use yii\helpers\ArrayHelper as BaseArrayHelper;
  13.  
  14. class ExtnArrayHelper extends BaseArrayHelper
  15. {
  16.     public static function getColumnByPriority(array $array, array $columnNames, $keepKeys = true): array
  17.     {
  18.         return self::getColumn(
  19.             $array,
  20.             function ($element) use ($columnNames) {
  21.                 foreach ($columnNames as $column) {
  22.                     if ($value = self::getValue($element, $column)) {
  23.                         return $value;
  24.                     }
  25.                 }
  26.                 return null;
  27.             },
  28.             $keepKeys
  29.         );
  30.     }
  31. }
  32.  
  33. class OrphArrayHelper
  34. {
  35.     public static function columnByPriority(...$columnNames): \Closure
  36.     {
  37.         return function ($element) use ($columnNames) {
  38.             foreach ($columnNames as $column) {
  39.                 if ($value = BaseArrayHelper::getValue($element, $column)) {
  40.                     return $value;
  41.                 }
  42.             }
  43.             return null;
  44.         };
  45.     }
  46.  
  47.     public static function getColumnByPriority(array $array, array $name, bool $keepKeys = true): array
  48.     {
  49.         return BaseArrayHelper::getColumn($array, self::columnByPriority(...$name), $keepKeys);
  50.     }
  51. }
  52.  
  53. /**
  54.  * @method getColumn($array, $name, $keepKeys = true)
  55.  */
  56. class TrueArrayHelper
  57. {
  58.     public static function __callStatic($name, $arguments)
  59.     {
  60.         if (method_exists(BaseArrayHelper::class, $name)) {
  61.             return BaseArrayHelper::$name(...$arguments);
  62.         }
  63.         throw new \Exception("Static method $name not found.");
  64.     }
  65.  
  66.     private static function columnByPriority(...$columnNames): \Closure
  67.     {
  68.         return function ($element) use ($columnNames) {
  69.             foreach ($columnNames as $column) {
  70.                 if ($value = BaseArrayHelper::getValue($element, $column)) {
  71.                     return $value;
  72.                 }
  73.             }
  74.             return null;
  75.         };
  76.     }
  77.  
  78.     public static function getColumnByPriority(array $array, array $name, bool $keepKeys = true): array
  79.     {
  80.         return BaseArrayHelper::getColumn($array, self::columnByPriority(...$name), $keepKeys);
  81.     }
  82. }
  83.  
  84. class DebugController extends Controller
  85. {
  86.     public function actionIndex()
  87.     {
  88.         # Пусть есть исходный массив
  89.        $input = [
  90.             ['english' => 'First', 'russian' => 'Первый', 'deutsch' => 'Zuerst'],
  91.             ['russian' => 'Второй'],
  92.             ['russian' => 'Третий', 'deutsch' => 'Dritter'],
  93.             [],
  94.         ];
  95.  
  96.         # Пусть необходимо получить 2 результата
  97.        $outputFirstGood = [
  98.             'Zuerst',
  99.             null,
  100.             'Dritter',
  101.             null
  102.         ];
  103.         $outputSecondGood = [
  104.             'First',
  105.             'Второй',
  106.             'Dritter',
  107.             null
  108.         ];
  109.  
  110.         # Пример решения в Yii2 через наследование.
  111.        #
  112.        # Лаконично, через наследование, где 1 новый класс с 1 новой функцией (или несколькими, если есть еще необходимость).
  113.        # Где разработчик всегда знает что для решения задач проекта необходимо использовать ExtnArrayHelper
  114.        # Ну или расширять его по мере необходимости 1 раз в несколько месяцев
  115.        $out_1 = ExtnArrayHelper::getColumn($input, 'deutsch');
  116.         $out_2 = ExtnArrayHelper::getColumnByPriority($input, ['english', 'deutsch', 'russian']);
  117.         # Длина строки 98
  118.  
  119.         # Примеры решения если от BaseArrayHelper нельзя наследовать
  120.        #
  121.        # Получение только немецкого языка будет происходить стандартно через BaseArrayHelper
  122.        $yi311 = BaseArrayHelper::getColumn($input, 'deutsch');
  123.         #
  124.        # А вот получение приоритетной выборки можно сделать тремя разными способами
  125.        #
  126.        #
  127.        # 1) Через 1 новый класс c одной новой функцией, возвращающей \Closure
  128.        # нужную только для того что-бы результат её работы
  129.        # был вставлен во второй параметр BaseArrayHelper::getColumn что на мой взляд излишне усложнено.
  130.        # Всем разработчикам нужно будет помнить что для решения задачи приоритетного получения колонки,
  131.        # при отсутствии нужной, нужную \Closure для второго параметра BaseArrayHelper::getColumn
  132.        # надо брать из другого класса OrphArrayHelper
  133.        # Дополенение:
  134.        # Например, новые разработчики, ранее знакомые с Yii будут знать про BaseArrayHelper::getColumn,
  135.        # и станут еспользовать его при повторном решении этой простой задачи,
  136.        # и я очень сомневаюсь что они будут искать / найдут
  137.        # OrphArrayHelper::anyColumn для того чтобы вставить результат её работы
  138.        # во второй параметр BaseArrayHelper::getColumn
  139.        # они скорее всего напишут что-то своё и всегда с наибольшей вероятностью что с ошибкой
  140.        $yi321 = BaseArrayHelper::getColumn($input, OrphArrayHelper::columnByPriority('english', 'deutsch', 'russian'));
  141.         # Длина строки 121
  142.        #
  143.        #
  144.        # 2) Использовать OrphArrayHelper::getColumnByPriority как обёртку над BaseArrayHelper
  145.        $yi322 = OrphArrayHelper::getColumnByPriority($input, ['english', 'deutsch', 'russian']);
  146.         # Длина строки 98. Как и раньше, но нужно держать в памяти что для одной задачи надо использовать
  147.        # BaseArrayHelper а для другой OrphArrayHelper, хотя они очень близки по смыслу.
  148.        # Что не решает проблему описанную в дополенении.
  149.        #
  150.        #
  151.        # 3) Извернуться через магию чтобы обойти final =)
  152.        $yi323 = TrueArrayHelper::getColumnByPriority($input, ['english', 'deutsch', 'russian']);
  153.         # Длина строки 98.
  154.        $yi312 = TrueArrayHelper::getColumn($input, 'deutsch');
  155.         # Решит проблему дополнения, но магия не лучший вариант + необходимо описать все методы BaseArrayHelper в phpDoc =)))
  156.        #
  157.        #
  158.        # P.S. Програмисты ленивые. А final, на мой взгляд,
  159.        # в классе https://github.com/yiisoft/arrays/blob/edec11c95cbc3ee5b6b1b9739a7405a5a325b731/src/ArrayHelper.php
  160.        # излишний и усложняющий разработку там где это не надо, без профита.
  161.        #
  162.        #
  163.        # P.S.S.
  164.        # BaseArrayHelper (Yii ArrayHelper finalized in future / Yii3),
  165.        # OrphArrayHelper (Orphan),
  166.        # TrueArrayHelper (Very Funny Class),
  167.        # ExtnArrayHelper (Extended)
  168.        # названия классов равной длины используются для наглядности для демонстрации проблемы в одном файле.
  169.        # В реальных условиях я предпочитаю использовать только \app\Helpers\ArrayHelper::class унаследованный от \yii\helpers\ArrayHelper
  170.        # но возможно сообщество со мной не согласится
  171.  
  172.         if (
  173.             $outputFirstGood === $out_1
  174.             && $outputFirstGood === $yi311
  175.             && $outputFirstGood === $yi312
  176.         ) {
  177.             print_r($outputFirstGood);
  178.         }
  179.         /**
  180.          * Array
  181.          * (
  182.          *     [0] => Zuerst
  183.          *     [1] =>
  184.          *     [2] => Dritter
  185.          *     [3] =>
  186.          * )
  187.          */
  188.  
  189.         if (
  190.             $outputSecondGood === $out_2
  191.             && $outputSecondGood === $yi321
  192.             && $outputSecondGood === $yi322
  193.             && $outputSecondGood === $yi323
  194.         ) {
  195.             print_r($outputSecondGood);
  196.         }
  197.         /**
  198.          * Array
  199.          * (
  200.          *     [0] => First
  201.          *     [1] => Второй
  202.          *     [2] => Dritter
  203.          *     [3] =>
  204.          * )
  205.          */
  206.     }
  207. }
  208.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement