За последние 24 часа нас посетили 8029 программистов и 475 роботов. Сейчас ищут 343 программиста ...

Конструктор php кода, json строкой

Тема в разделе "Решения, алгоритмы", создана пользователем MouseZver, 19 мар 2020.

  1. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    6.547
    Симпатии:
    1.040
    Адрес:
    Лень
    Выкладываю кусочек тематики, над чем сейчас и работаю. Возможно вам будет это интересно, а так показать возможность данной реализации.

    Для примера, взял пару строк пхп кода по которому постараюсь объяснить, как это все работает.
    PHP:
    1. $container -> get( \Commands :: class ) -> typeChat( $container -> get( \Commands :: class ) -> getParseTags()['type'], static function ( Container $container ): void
    2. {
    3.     $container -> get( \Commands :: class ) -> randomMessageSend( 'offline' );
    4. } );
    5.  
    6. $container -> get( \Commands :: class ) -> typeChat( 'Normal' );
    7.  
    8. $container -> get( \Commands :: class ) -> arr -> one -> {2} -> three;
    Теперь попробуйте каждый элемент аргументировать в виде json строки. Да, будет начало что-то вроде {"var":{"name":"container","result":{......}}} - но это будет слишком низкоуровневый контент.
    Что у меня вышло с многоразовыми переделками:
    PHP:
    1. [
    2.     {
    3.         "method":[
    4.             {"container":"Commands"},
    5.             "typeChat",
    6.             [
    7.                 {
    8.                     "get_results_for_keys":[
    9.                         {
    10.                             "method":[
    11.                                 {
    12.                                     "container":"Commands"
    13.                                 },
    14.                                 "getParseTags"
    15.                             ]
    16.                         },
    17.                         ["type"]
    18.                     ]
    19.                 },
    20.                 {
    21.                     "callable":{
    22.                         "method":[
    23.                             {
    24.                                 "container":"Commands"
    25.                             },
    26.                             "randomMessageSend",
    27.                             ["offline"]
    28.                         ]
    29.                     }
    30.                 }
    31.             ]
    32.         ]
    33.     },
    34.     {
    35.         "method":[
    36.             {
    37.                 "container":"Commands"
    38.             },
    39.             "typeChat",
    40.             ["Normal"]
    41.         ]
    42.     },
    43.     {
    44.         "get_results_for_keys":[
    45.             {"container":"Commands"},
    46.             ["arr","one",2,"three"]
    47.         ]
    48.     }
    49. ]

    Т.е. каждый пак/строк кода, представлен в такой архитектуре:
    PHP:
    1. [
    2.     {
    3.         1 пак
    4.     },
    5.     {
    6.         2 пак
    7.     },
    8.     {
    9.         3 пак
    10.     }
    11. ]
    Актуально рабочая/тестовая версия
    http://sandbox.onlinephpfunctions.com/code/bdc5e6b8c1a2d743473b0588ae94bed66f2ac882

    По выше перечисленной ссылке с 69 строки, представлен анонимный класс, который собирает так называемую Паутину "callable мап схему" и после дергает, в нужном местоположении, свой пакет завернутого кода.
    Структура самого класса без пользовательских fun_<name> методов:
    PHP:
    1. new class ( ...$args )
    2. {
    3.     private $container;
    4.  
    5.     # здесь составляется вся схема с вложенными Closure функциями и его аргументов, все.
    6.    # вложения во вложенном
    7.    protected $passage = [];
    8.  
    9.     # тестовая переменная для удобного просмотра содержимого и в дальнейшем правка архитектуры.
    10.    public $passage_test = [];
    11.  
    12.     # Сохраняем в переменную декодированный массив, входящего json списка
    13.    protected $constructor;
    14.  
    15.     # Регистрируем имена для пользовательских методов fun_<name>()
    16.    protected $register_fun = [
    17.         'container',
    18.         'method',
    19.         'get_results_for_keys',
    20.         'callable',
    21.     ];
    22.  
    23.     public function __construct ( Container $container )
    24.     {
    25.         $this -> container = $container;
    26.     }
    27.  
    28.     /*
    29.         - импортируем и проверяем json перед использованием
    30.     */
    31.     public function import( string $string ): bool
    32.     {
    33.         $this -> constructor = json_decode ( $string, true ) ?: [];
    34.      
    35.         return json_last_error () === JSON_ERROR_NONE;
    36.     }
    37.  
    38.     /*
    39.         - Собираем мап схему без запуска и выводим.
    40.     */
    41.     public function handle()
    42.     {
    43.         $this -> passage( $this -> constructor );
    44.      
    45.         return $this -> passage;
    46.     }
    47.  
    48.     /*
    49.         - Рекурсивное прохождение
    50.     */
    51.     protected function passage( array $a )
    52.     {
    53.         $passage = &$this -> passage;
    54.      
    55.         $this -> passage = &$passage[];
    56.      
    57.         $passage_test = &$this -> passage_test; // тест
    58.      
    59.         $this -> passage_test = &$passage_test[]; // тест
    60.      
    61.         # пример:
    62.        # {"container":"Commands"}
    63.        foreach ( $a AS $key => $iteration )
    64.         {
    65.             # Сверяем ключ со списком регистрации имен - container - yes
    66.            if ( in_array ( $key, $this -> register_fun, true ) )
    67.             {
    68.                 $this -> {'fun_' . $key}();
    69.              
    70.                 //$this -> passage( $iteration );
    71.             }
    72.          
    73.             # Commands - set arguments
    74.            if ( is_string ( $iteration ) || is_numeric ( $iteration ) )
    75.             {
    76.                 $this -> passage[] = static function ( Container $container ) use ( $iteration ): string
    77.                 {
    78.                     return $iteration;
    79.                 };
    80.              
    81.                 $this -> passage_test[] = $iteration; // тест
    82.             }
    83.             else #{"name...":[{"container":"Commands"}]}
    84.            {
    85.                 $this -> passage( $iteration ); # [{"container":"Commands"}]
    86.            }
    87.         }
    88.      
    89.         $this -> passage = &$passage;
    90.      
    91.         $this -> passage_test = &$passage_test; // test
    92.     }
    93.  
    94.     /*
    95.         по запуску схемы, содержимое метода рекурсивно ищет и запускает аргументы callable or пакеты кода key *main
    96.         {
    97.             *main ( get_map ),
    98.             0_arguments - {
    99.                 *main ( get_map ),
    100.                 0_arguments - {
    101.                     *main ( get_map ),
    102.                     0_arguments - {
    103.                         closure - values,
    104.                         closure - values,
    105.                         closure - values
    106.                     }
    107.                 }
    108.             }
    109.         }
    110.     */
    111.     protected function get_map(): callable
    112.     {
    113.         return static function ( Container $container, callable $map, $passage )
    114.         {
    115.             if ( is_callable ( $passage ) )
    116.             {
    117.                 return $passage( $container );
    118.             }
    119.             elseif ( isset ( $passage['*main'] ) )
    120.             {
    121.                 return $passage['*main']( $container );
    122.             }
    123.          
    124.             $a = [];
    125.          
    126.             foreach ( $passage AS $p )
    127.             {
    128.                 $a[] = $map( $container, $map, $p );
    129.             }
    130.          
    131.             return $a;
    132.         };
    133.     }
    134. };
    Пользовательский метод в классе (в качестве шаблона) выглядит так:
    PHP:
    1. protected function fun_<name>()
    2. {
    3.     $passage = &$this -> passage;
    4.  
    5.     $passage_test = &$this -> passage_test; // test
    6.  
    7.     $passage_test['main'] = 'fun_<name>'; // test
    8.  
    9.     $map = $this -> get_map();
    10.  
    11.     $passage['*main'] = static function ( Container $container ) use ( &$passage, $map )
    12.     {
    13.         var_dump('<name>'); // тест
    14.      
    15.         # тело пхп кода
    16.    
    17.         return ...;
    18.     };
    19. }
    По json`у - разработав некие правила, допустим:
    Чтоб собрать обычный метод, нужно следовать по такому шаблону
    PHP:
    1. {
    2.   "method":[
    3.   {<this>},
    4.   <name>,
    5.   [<arguments>] or []
    6.   ]
    7. }
    его реализация:
    PHP:
    1. protected function fun_method()
    2. {
    3.     $passage = &$this -> passage;
    4.  
    5.     $passage_test = &$this -> passage_test;
    6.  
    7.     $passage_test['main'] = 'fun_method';
    8.  
    9.     $map = $this -> get_map();
    10.  
    11.     $passage['*main'] = static function ( Container $container ) use ( &$passage, $map )
    12.     {
    13.         var_dump('method');
    14.  
    15.         $_this = $map( $container, $map, $passage[0][0] );
    16.  
    17.         $_name = $map( $container, $map, $passage[0][1] );
    18.  
    19.         $args = ( isset ( $passage[0][2] ) ? $map( $container, $map, $passage[0][2] ) : [] );
    20.  
    21.         //var_dump ( $_name, $args );
    22.  
    23.         return $_this -> {$_name}( ...$args );
    24.     };
    25. }

    Для всего творения, мне нужно было задействовать сторонние классы, для действительного факта об работоспособности конструктора. Поэтому по ссылке (выше) присутствует лишний код.


    Контейнер
    PHP:
    1. final class Container
    2. {
    3.     private $container = [];
    4.  
    5.     public function set( string $name, callable $func ): void
    6.     {
    7.         if ( isset ( $this -> container[$name] ) )
    8.         {
    9.             throw new \Error( $name . ' already exists!' );
    10.         }
    11.      
    12.         $this -> container[$name] = $func;
    13.     }
    14.  
    15.     public function get( string $name )
    16.     {
    17.         if ( ! isset ( $this -> container[$name] ) )
    18.         {
    19.             return null;
    20.         }
    21.      
    22.         if ( $this -> container[$name] instanceof \Closure )
    23.         {
    24.             return $this -> container[$name] = $this -> container[$name]( $this );
    25.         }
    26.      
    27.         return $this -> container[$name];
    28.     }
    29. }
    Произвольный класс с методами
    PHP:
    1. class Commands
    2. {
    3.     public function __construct ( Container $container )
    4.     {
    5.         $this -> container = $container;
    6.      
    7.         $this -> arr = json_decode ( '{"one":{"2":{"three":111}}}' );
    8.     }
    9.  
    10.     public function typeChat( $a, $b = null )
    11.     {
    12.         var_dump ( "typeChat -- {$a}" );
    13.      
    14.         if ( $b )
    15.         {
    16.             var_dump ( $b( $this -> container ) );
    17.         }
    18.     }
    19.  
    20.     public function getParseTags()
    21.     {
    22.         return ['type'=>666];
    23.     }
    24.  
    25.     public function randomMessageSend( string $string )
    26.     {
    27.         return "randomMessageSend -- {$string}";
    28.     }
    29. }

    PHP:
    1. $c = new Container;
    2.  
    3. $c -> set( \Commands :: class, static function ( Container $container )
    4. {
    5.     return new Commands( $container );
    6. } );
    7.  
    8. $b = $a( $c );
    9.  
    10. /*
    11.     new main обворачивать в {}
    12. */
    13.  
    14. $str = '
    15. [
    16.    {
    17.        "method":[
    18.            {
    19.                "container":"Commands"
    20.            },
    21.            "randomMessageSend",
    22.            [
    23.                {
    24.                    "get_results_for_keys":[
    25.                        {
    26.                            "method":[
    27.                                {
    28.                                    "container":"Commands"
    29.                                },
    30.                                "getParseTags"
    31.                            ]
    32.                        },
    33.                        ["type"]
    34.                    ]
    35.                }
    36.            ]
    37.        ]
    38.    }
    39. ]';
    40.  
    41. if ( $b -> import( $str ) )
    42. {
    43.     $res = $b -> handle();
    44.  
    45.     //print_r ( $b -> passage_test );
    46.  
    47.     foreach ( $res AS $_2 )
    48.     {
    49.         foreach ( $_2 AS $_3 )
    50.         {
    51.             print_r ($_3['*main']($c));
    52.         }
    53.     }
    54. }
    55. else
    56. {
    57.     echo 'Не корректный json';
    58. }
    Да, запуск схемы простенький (два foreach), т.к. полноценно еще не создано ни-че-го.
    Про $b -> passage_test верху описывал, что выводит.

    Результат будет ввиде Debugs
    PHP:
    1. string(6) "method"
    2. string(9) "container"
    3. string(20) "get_results_for_keys"
    4. string(6) "method"
    5. string(9) "container"
    6. randomMessageSend -- 666
    $b -> passage_test
    PHP:
    1.     [0] => Array(
    2.         [0] => Array(
    3.             [main] => fun_method
    4.             [0] => Array(
    5.                 [0] => Array(
    6.                     [main] => fun_container
    7.                     [0] => Commands
    8.                 )
    9.                 [1] => randomMessageSend
    10.                 [2] => Array(
    11.                     [0] => Array(
    12.                         [main] => fun_get_results_for_keys
    13.                         [0] => Array(
    14.                             [0] => Array(
    15.                                 [main] => fun_method
    16.                                 [0] => Array(
    17.                                     [0] => Array(
    18.                                         [main] => fun_container
    19.                                         [0] => Commands
    20.                                     )
    21.                                     [1] => getParseTags
    22.                                 )
    23.                             )
    24.                             [1] => Array (
    25.                                 [0] => type
    26.                             )
    27.                         )
    28.                     )
    29.                 )
    30.             )
    31.         )
    32.     )
    33. )

    Пишу для нейросети API "команды" и развитие.
     
    #1 MouseZver, 19 мар 2020
    Последнее редактирование модератором: 19 мар 2020
  2. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    6.547
    Симпатии:
    1.040
    Адрес:
    Лень
    PHP:
    1. $commands = $container -> get( \Commands :: class );
    2.  
    3. [ 'type' => $type, 'name' => $name, 'message' => $message ] = $commands -> getParseTags();
    4.  
    5. $commands -> reloadDaemon( static function ( Container $container ) use ( $type, $name ): void
    6. {
    7.     $container -> get( \Commands :: class ) -> setParseTag( 'name', $name );
    8.    
    9.     $container -> get( \Commands :: class ) -> typeChat( $type, static function ( Container $container ): void
    10.     {
    11.         $container -> get( \Commands :: class ) -> write2chat( 'Команда принята' );
    12.     } );
    13. } );
    14.  
    15. $systems = $container -> get( \Systems :: class );
    16.  
    17. $values = $commands -> getValues();
    18.  
    19. $time = strtotime ( "+{$values[1]} seconds" );
    PHP:
    1. [
    2.     {"copy":["Commands",{"container":"Commands"}]},
    3.     {"copy":["Systems",{"container":"Systems"}]},
    4.     {
    5.         "copy":[
    6.             "history_tags",
    7.             {
    8.                 "method":[
    9.                     {"paste":"Commands"},
    10.                     "getParseTags"
    11.                 ]
    12.             }
    13.         ]
    14.     },
    15.     {
    16.         "method":[
    17.             {"paste":"Commands"},
    18.             "reloadDaemon",
    19.             [
    20.                 {
    21.                     "callable":[
    22.                         {
    23.                             "method":[
    24.                                 {"paste":"Commands"},
    25.                                 "setParseTag",
    26.                                 [
    27.                                     "name",
    28.                                     {
    29.                                         "get_results_for_keys":[
    30.                                             {"paste":"history_tags"},
    31.                                             ["name"]
    32.                                         ]
    33.                                     }
    34.                                 ]
    35.                             ]
    36.                         },
    37.                         {
    38.                             "method":[
    39.                                 {"paste":"Commands"},
    40.                                 "typeChat",
    41.                                 [
    42.                                     {
    43.                                         "get_results_for_keys":[
    44.                                             {"paste":"history_tags"},
    45.                                             ["type"]
    46.                                         ]
    47.                                     },
    48.                                     {
    49.                                         "callable":{
    50.                                             "method":[
    51.                                                 {"paste":"Commands"},
    52.                                                 "write2chat",
    53.                                                 ["Команда принята"]
    54.                                             ]
    55.                                         }
    56.                                     }
    57.                                 ]
    58.                             ]
    59.                         }
    60.                     ]
    61.                 }
    62.             ]
    63.         ]
    64.     },
    65.     {"copy":["getValues",{
    66.         "method":[
    67.             {"paste":"Commands"},
    68.             "getValues"
    69.         ]
    70.     }]},
    71.     {"copy":["time",{
    72.         "function":[
    73.             "strtotime",
    74.             [
    75.                 {
    76.                     "function":[
    77.                         "sprintf",
    78.                         [
    79.                             "+%s seconds",
    80.                             {
    81.                                 "get_results_for_keys":[
    82.                                     {"paste":"getValues"},
    83.                                     [1]
    84.                                 ]
    85.                             }
    86.                         ]
    87.                     ]
    88.                 }
    89.             ]
    90.         ]
    91.     }]}
    92. ]
     
  3. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    6.547
    Симпатии:
    1.040
    Адрес:
    Лень
    PHP:
    1. /*
    2.     - {"logical_operators":["operator",{value1},{value2}]}
    3. */
    4. protected function fun_logical_operators( &$passage )
    5. {
    6.     $this -> passage_test['main'] = __FUNCTION__;
    7.  
    8.     $map = $this -> get_map();
    9.  
    10.     $passage['*main'] = static function ( Container $container ) use ( &$passage, $map ): bool
    11.     {
    12.         var_dump('logical_operators');
    13.      
    14.         $logic = $map( $container, $map, $passage[0][0] );
    15.      
    16.         $a = [
    17.             [ $container, $map, $passage[0][1] ],
    18.             [ $container, $map, $passage[0][2] ?? [] ]
    19.         ];
    20.      
    21.         switch ( $logic )
    22.         {
    23.             case '==':
    24.                 return $map( ...$a[0] ) == $map( ...$a[1] );
    25.             break;
    26.             case '===':
    27.                 return $map( ...$a[0] ) === $map( ...$a[1] );
    28.             break;
    29.             case '!=':
    30.                 return $map( ...$a[0] ) != $map( ...$a[1] );
    31.             break;
    32.             case '<>':
    33.                 return $map( ...$a[0] ) <> $map( ...$a[1] );
    34.             break;
    35.             case '!==':
    36.                 return $map( ...$a[0] ) !== $map( ...$a[1] );
    37.             break;
    38.             case '<':
    39.                 return $map( ...$a[0] ) < $map( ...$a[1] );
    40.             break;
    41.             case '>':
    42.                 return $map( ...$a[0] ) > $map( ...$a[1] );
    43.             break;
    44.             case '<=':
    45.                 return $map( ...$a[0] ) <= $map( ...$a[1] );
    46.             break;
    47.             case '>=':
    48.                 return $map( ...$a[0] ) >= $map( ...$a[1] );
    49.             break;
    50.             case '<=>':
    51.                 return $map( ...$a[0] ) <=> $map( ...$a[1] );
    52.             break;
    53.             # -----------------------------
    54.            case 'xor':
    55.                 return $map( ...$a[0] ) XOR $map( ...$a[1] );
    56.             break;
    57.             case '!':
    58.                 return ! $map( ...$a[0] );
    59.             break;
    60.             case '&&':
    61.                 return $map( ...$a[0] ) && $map( ...$a[1] );
    62.             break;
    63.             case '||':
    64.                 return $map( ...$a[0] ) || $map( ...$a[1] );
    65.             break;
    66.         }
    67.     };
    68. }
    PHP:
    1. [
    2.     {"logical_operators":["&&",2,{"logical_operators":["!==",2,"2"]}]}
    3. ]
    true

    P.s: Структура класса изменена
     
  4. Awilum

    Awilum Активный пользователь

    С нами с:
    15 ноя 2009
    Сообщения:
    291
    Симпатии:
    20
    Адрес:
    Russian Federation
    почему JSON ?

    JSON
    Код (Text):
    1. [
    2.     {"copy":["Commands",{"container":"Commands"}]},
    3.     {"copy":["Systems",{"container":"Systems"}]},
    4.     {
    5.         "copy":[
    6.             "history_tags",
    7.             {
    8.                 "method":[
    9.                     {"paste":"Commands"},
    10.                     "getParseTags"
    11.                 ]
    12.             }
    13.         ]
    14.     },
    15.     {
    16.         "method":[
    17.             {"paste":"Commands"},
    18.             "reloadDaemon",
    19.             [
    20.                 {
    21.                     "callable":[
    22.                         {
    23.                             "method":[
    24.                                 {"paste":"Commands"},
    25.                                 "setParseTag",
    26.                                 [
    27.                                     "name",
    28.                                     {
    29.                                         "get_results_for_keys":[
    30.                                             {"paste":"history_tags"},
    31.                                             ["name"]
    32.                                         ]
    33.                                     }
    34.                                 ]
    35.                             ]
    36.                         },
    37.                         {
    38.                             "method":[
    39.                                 {"paste":"Commands"},
    40.                                 "typeChat",
    41.                                 [
    42.                                     {
    43.                                         "get_results_for_keys":[
    44.                                             {"paste":"history_tags"},
    45.                                             ["type"]
    46.                                         ]
    47.                                     },
    48.                                     {
    49.                                         "callable":{
    50.                                             "method":[
    51.                                                 {"paste":"Commands"},
    52.                                                 "write2chat",
    53.                                                 ["Команда принята"]
    54.                                             ]
    55.                                         }
    56.                                     }
    57.                                 ]
    58.                             ]
    59.                         }
    60.                     ]
    61.                 }
    62.             ]
    63.         ]
    64.     },
    65.     {"copy":["getValues",{
    66.         "method":[
    67.             {"paste":"Commands"},
    68.             "getValues"
    69.         ]
    70.     }]},
    71.     {"copy":["time",{
    72.         "function":[
    73.             "strtotime",
    74.             [
    75.                 {
    76.                     "function":[
    77.                         "sprintf",
    78.                         [
    79.                             "+%s seconds",
    80.                             {
    81.                                 "get_results_for_keys":[
    82.                                     {"paste":"getValues"},
    83.                                     [1]
    84.                                 ]
    85.                             }
    86.                         ]
    87.                     ]
    88.                 }
    89.             ]
    90.         ]
    91.     }]}
    92. ]
    YAML
    Код (Text):
    1. ---
    2. - copy:
    3.   - Commands
    4.   - container: Commands
    5. - copy:
    6.   - Systems
    7.   - container: Systems
    8. - copy:
    9.   - history_tags
    10.   - method:
    11.     - paste: Commands
    12.     - getParseTags
    13. - method:
    14.   - paste: Commands
    15.   - reloadDaemon
    16.   - - callable:
    17.       - method:
    18.         - paste: Commands
    19.         - setParseTag
    20.         - - name
    21.           - get_results_for_keys:
    22.             - paste: history_tags
    23.             - - name
    24.       - method:
    25.         - paste: Commands
    26.         - typeChat
    27.         - - get_results_for_keys:
    28.             - paste: history_tags
    29.             - - type
    30.           - callable:
    31.               method:
    32.               - paste: Commands
    33.               - write2chat
    34.               - - Команда принята
    35. - copy:
    36.   - getValues
    37.   - method:
    38.     - paste: Commands
    39.     - getValues
    40. - copy:
    41.   - time
    42.   - function:
    43.     - strtotime
    44.     - - function:
    45.         - sprintf
    46.         - - "+%s seconds"
    47.           - get_results_for_keys:
    48.             - paste: getValues
    49.             - - 1
     
    MouseZver нравится это.
  5. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    6.547
    Симпатии:
    1.040
    Адрес:
    Лень
    Изначально Yaml не подходил в одной разработке. Нужно в одну строку все писать (доступен буфер обмена копи/паст)