3v4l.org

run code in 300+ PHP versions simultaneously
<?php function call_user_func_fixed() { // Not much point in writing all that logic out twice, just require that both fixer functions are present $args = func_get_args(); $callable = array_shift($args); return call_user_func_array_fixed($callable, $args); } function call_user_func_array_fixed($callable, $args) { $isStaticMethod = false; // Normalize the $callable and see if it looks like a static method if (is_object($callable) && $callable instanceof Closure) { $func = $callable; } else if (is_string($callable)) { $expr = '/^([a-z_\x7f-\xff][\w\x7f-\xff]*)::([a-z_\x7f-\xff][\w\x7f-\xff]*)$/i'; if (preg_match($expr, $callable, $matches)) { $func = array($matches[1], $matches[2]); $isStaticMethod = true; } else { $func = $callable; } } else if (is_array($callable) && isset($callable[0], $callable[1]) && count($callable) === 2) { if (is_object($callable[0])) { $func = $callable; } else if (is_string($callable[0])) { $func = $callable; $isStaticMethod = true; } } // If it's not a valid callable give up here if (!isset($callable) || (!$isStaticMethod && !is_callable($callable))) { trigger_error('call_user_func() expects parameter 1 to be a valid callback', E_USER_WARNING); return null; } // If it's not a static method use the regular mechanism if (!$isStaticMethod) { return call_user_func_array($func, $args); } // Get a reference to the target static method if possible try { if ($func[0] === 'self') { if (!$contextClass) { throw new Exception('Use of self in an invalid context'); } $class = new ReflectionClass($contextClass); $method = $class->getMethod($func[1]); if ($method->isPrivate()) { if ($method->getDeclaringClass()->getName() !== $contextClass || !method_exists($method, 'setAccessible')) { throw new Exception('Attempting to call private method in an invalid context'); } $method->setAccessible(true); } else if ($method->isProtected()) { if (!method_exists($method, 'setAccessible')) { throw new Exception('Attempting to call protected method in an invalid context'); } while ($class->getName() !== $contextClass) { $class = $class->getParentClass(); } if ($class->getName() !== $contextClass) { throw new Exception('Attempting to call protected method in an invalid context'); } $method->setAccessible(true); } } else if ($func[0] === 'static' && function_exists('get_called_class')) { $class = new ReflectionClass(get_called_class()); $method = $class->getMethod($func[1]); } else { $class = new ReflectionClass($func[0]); $method = $class->getMethod($func[1]); } // Invoke the method with the passed arguments and return the result return $method->invokeArgs(null, $args); } catch (Exception $e) { trigger_error('call_user_func*() expects parameter 1 to be a valid callback: ' . $e->getMessage(), E_USER_WARNING); return null; } // Invoke the method with the passed arguments and return the result return $method->invokeArgs(null, $args); } class Car { public function run() { return call_user_func_fixed('self::getName'); // should call toyota } private static function getName() { return 'Car'; } } class Toyota extends Car { public static function getName() { return 'Toyota'; } } $car = new Car(); echo $car->run(); //Car instead of Toyota $toyota = new Toyota(); echo $toyota->run(); //Car instead of Toyota
Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 62) Position 1 = -2
filename:       /in/BYIV2
function name:  (null)
number of ops:  13
compiled vars:  !0 = $car, !1 = $toyota
line      #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
  112     0  E >   NEW                                              $2      'Car'
          1        DO_FCALL                                      0          
          2        ASSIGN                                                   !0, $2
  113     3        INIT_METHOD_CALL                                         !0, 'run'
          4        DO_FCALL                                      0  $5      
          5        ECHO                                                     $5
  115     6        NEW                                              $6      'Toyota'
          7        DO_FCALL                                      0          
          8        ASSIGN                                                   !1, $6
  116     9        INIT_METHOD_CALL                                         !1, 'run'
         10        DO_FCALL                                      0  $9      
         11        ECHO                                                     $9
         12      > RETURN                                                   1

Function call_user_func_fixed:
Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 62) Position 1 = -2
filename:       /in/BYIV2
function name:  call_user_func_fixed
number of ops:  12
compiled vars:  !0 = $args, !1 = $callable
line      #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
    6     0  E >   FUNC_GET_ARGS                                    ~2      
          1        ASSIGN                                                   !0, ~2
    7     2        INIT_FCALL                                               'array_shift'
          3        SEND_REF                                                 !0
          4        DO_ICALL                                         $4      
          5        ASSIGN                                                   !1, $4
    9     6        INIT_FCALL_BY_NAME                                       'call_user_func_array_fixed'
          7        SEND_VAR_EX                                              !1
          8        SEND_VAR_EX                                              !0
          9        DO_FCALL                                      0  $6      
         10      > RETURN                                                   $6
   10    11*     > RETURN                                                   null

End of function call_user_func_fixed

Function call_user_func_array_fixed:
Finding entry points
Branch analysis from position: 0
2 jumps found. (Code = 46) Position 1 = 5, Position 2 = 7
Branch analysis from position: 5
2 jumps found. (Code = 43) Position 1 = 8, Position 2 = 10
Branch analysis from position: 8
1 jumps found. (Code = 42) Position 1 = 50
Branch analysis from position: 50
2 jumps found. (Code = 47) Position 1 = 53, Position 2 = 61
Branch analysis from position: 53
2 jumps found. (Code = 46) Position 1 = 55, Position 2 = 60
Branch analysis from position: 55
2 jumps found. (Code = 43) Position 1 = 62, Position 2 = 67
Branch analysis from position: 62
1 jumps found. (Code = 62) Position 1 = -2
Branch analysis from position: 67
2 jumps found. (Code = 43) Position 1 = 69, Position 2 = 74
Branch analysis from position: 69
1 jumps found. (Code = 62) Position 1 = -2
Branch analysis from position: 74
2 jumps found. (Code = 43) Position 1 = 77, Position 2 = 150
Branch analysis from position: 77
2 jumps found. (Code = 43) Position 1 = 79, Position 2 = 83
Branch analysis from position: 79
1 jumps found. (Code = 108) Position 1 = -2
Branch analysis from position: 83
2 jumps found. (Code = 43) Position 1 = 96, Position 2 = 117
Branch analysis from position: 96
2 jumps found. (Code = 47) Position 1 = 102, Position 2 = 108
Branch analysis from position: 102
2 jumps found. (Code = 43) Position 1 = 109, Position 2 = 113
Branch analysis from position: 109
1 jumps found. (Code = 108) Position 1 = -2
Branch analysis from position: 113
1 jumps found. (Code = 42) Position 1 = 149
Branch analysis from position: 149
1 jumps found. (Code = 42) Position 1 = 182
Branch analysis from position: 182
1 jumps found. (Code = 62) Position 1 = -2
Branch analysis from position: 108
Branch analysis from position: 117
2 jumps found. (Code = 43) Position 1 = 120, Position 2 = 149
Branch analysis from position: 120
2 jumps found. (Code = 43) Position 1 = 126, Position 2 = 130
Branch analysis from position: 126
1 jumps found. (Code = 108) Position 1 = -2
Branch analysis from position: 130
1 jumps found. (Code = 42) Position 1 = 134
Branch analysis from position: 134
2 jumps found. (Code = 44) Position 1 = 138, Position 2 = 131
Branch analysis from position: 138
2 jumps found. (Code = 43) Position 1 = 142, Position 2 = 146
Branch analysis from position: 142
1 jumps found. (Code = 108) Position 1 = -2
Branch analysis from position: 146
1 jumps found. (Code = 42) Position 1 = 182
Branch analysis from position: 182
Branch analysis from position: 131
2 jumps found. (Code = 44) Position 1 = 138, Position 2 = 131
Branch analysis from position: 138
Branch analysis from position: 131
Branch analysis from position: 149
Branch analysis from position: 150
2 jumps found. (Code = 46) Position 1 = 153, Position 2 = 157
Branch analysis from position: 153
2 jumps found. (Code = 43) Position 1 = 158, Position 2 = 170
Branch analysis from position: 158
1 jumps found. (Code = 42) Position 1 = 182
Branch analysis from position: 182
Branch analysis from position: 170
1 jumps found. (Code = 62) Position 1 = -2
Branch analysis from position: 157
Branch analysis from position: 60
Branch analysis from position: 61
Branch analysis from position: 10
2 jumps found. (Code = 43) Position 1 = 12, Position 2 = 28
Branch analysis from position: 12
2 jumps found. (Code = 43) Position 1 = 19, Position 2 = 26
Branch analysis from position: 19
1 jumps found. (Code = 42) Position 1 = 27
Branch analysis from position: 27
1 jumps found. (Code = 42) Position 1 = 50
Branch analysis from position: 50
Branch analysis from position: 26
1 jumps found. (Code = 42) Position 1 = 50
Branch analysis from position: 50
Branch analysis from position: 28
2 jumps found. (Code = 46) Position 1 = 30, Position 2 = 35
Branch analysis from position: 30
2 jumps found. (Code = 46) Position 1 = 32, Position 2 = 34
Branch analysis from position: 32
2 jumps found. (Code = 46) Position 1 = 36, Position 2 = 39
Branch analysis from position: 36
2 jumps found. (Code = 43) Position 1 = 40, Position 2 = 50
Branch analysis from position: 40
2 jumps found. (Code = 43) Position 1 = 43, Position 2 = 45
Branch analysis from position: 43
1 jumps found. (Code = 42) Position 1 = 50
Branch analysis from position: 50
Branch analysis from position: 45
2 jumps found. (Code = 43) Position 1 = 48, Position 2 = 50
Branch analysis from position: 48
2 jumps found. (Code = 47) Position 1 = 53, Position 2 = 61
Branch analysis from position: 53
Branch analysis from position: 61
Branch analysis from position: 50
Branch analysis from position: 50
Branch analysis from position: 39
Branch analysis from position: 34
Branch analysis from position: 35
Branch analysis from position: 7
Found catch point at position: 188
Branch analysis from position: 188
2 jumps found. (Code = 107) Position 1 = 189, Position 2 = -2
Branch analysis from position: 189
1 jumps found. (Code = 62) Position 1 = -2
filename:       /in/BYIV2
function name:  call_user_func_array_fixed
number of ops:  203
compiled vars:  !0 = $callable, !1 = $args, !2 = $isStaticMethod, !3 = $func, !4 = $expr, !5 = $matches, !6 = $contextClass, !7 = $class, !8 = $method, !9 = $e
line      #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   12     0  E >   RECV                                             !0      
          1        RECV                                             !1      
   14     2        ASSIGN                                                   !2, <false>
   17     3        TYPE_CHECK                                  256  ~11     !0
          4      > JMPZ_EX                                          ~11     ~11, ->7
          5    >   INSTANCEOF                                       ~12     !0, 'Closure'
          6        BOOL                                             ~11     ~12
          7    > > JMPZ                                                     ~11, ->10
   18     8    >   ASSIGN                                                   !3, !0
          9      > JMP                                                      ->50
   19    10    >   TYPE_CHECK                                   64          !0
         11      > JMPZ                                                     ~14, ->28
   20    12    >   ASSIGN                                                   !4, '%2F%5E%28%5Ba-z_%5Cx7f-%5Cxff%5D%5B%5Cw%5Cx7f-%5Cxff%5D%2A%29%3A%3A%28%5Ba-z_%5Cx7f-%5Cxff%5D%5B%5Cw%5Cx7f-%5Cxff%5D%2A%29%24%2Fi'
   21    13        INIT_FCALL                                               'preg_match'
         14        SEND_VAR                                                 !4
         15        SEND_VAR                                                 !0
         16        SEND_REF                                                 !5
         17        DO_ICALL                                         $16     
         18      > JMPZ                                                     $16, ->26
   22    19    >   FETCH_DIM_R                                      ~17     !5, 1
         20        INIT_ARRAY                                       ~18     ~17
         21        FETCH_DIM_R                                      ~19     !5, 2
         22        ADD_ARRAY_ELEMENT                                ~18     ~19
         23        ASSIGN                                                   !3, ~18
   23    24        ASSIGN                                                   !2, <true>
         25      > JMP                                                      ->27
   25    26    >   ASSIGN                                                   !3, !0
         27    > > JMP                                                      ->50
   27    28    >   TYPE_CHECK                                  128  ~23     !0
         29      > JMPZ_EX                                          ~23     ~23, ->35
         30    >   ISSET_ISEMPTY_DIM_OBJ                         0  ~24     !0, 0
         31      > JMPZ_EX                                          ~24     ~24, ->34
         32    >   ISSET_ISEMPTY_DIM_OBJ                         0  ~25     !0, 1
         33        BOOL                                             ~24     ~25
         34    >   BOOL                                             ~23     ~24
         35    > > JMPZ_EX                                          ~23     ~23, ->39
         36    >   COUNT                                            ~26     !0
         37        IS_IDENTICAL                                     ~27     ~26, 2
         38        BOOL                                             ~23     ~27
         39    > > JMPZ                                                     ~23, ->50
   28    40    >   FETCH_DIM_R                                      ~28     !0, 0
         41        TYPE_CHECK                                  256          ~28
         42      > JMPZ                                                     ~29, ->45
   29    43    >   ASSIGN                                                   !3, !0
         44      > JMP                                                      ->50
   30    45    >   FETCH_DIM_R                                      ~31     !0, 0
         46        TYPE_CHECK                                   64          ~31
         47      > JMPZ                                                     ~32, ->50
   31    48    >   ASSIGN                                                   !3, !0
   32    49        ASSIGN                                                   !2, <true>
   37    50    >   ISSET_ISEMPTY_CV                                 ~35     !0
         51        BOOL_NOT                                         ~36     ~35
         52      > JMPNZ_EX                                         ~36     ~36, ->61
         53    >   BOOL_NOT                                         ~37     !2
         54      > JMPZ_EX                                          ~37     ~37, ->60
         55    >   INIT_FCALL                                               'is_callable'
         56        SEND_VAR                                                 !0
         57        DO_ICALL                                         $38     
         58        BOOL_NOT                                         ~39     $38
         59        BOOL                                             ~37     ~39
         60    >   BOOL                                             ~36     ~37
         61    > > JMPZ                                                     ~36, ->67
   38    62    >   INIT_FCALL                                               'trigger_error'
         63        SEND_VAL                                                 'call_user_func%28%29+expects+parameter+1+to+be+a+valid+callback'
         64        SEND_VAL                                                 512
         65        DO_ICALL                                                 
   39    66      > RETURN                                                   null
   43    67    >   BOOL_NOT                                         ~41     !2
         68      > JMPZ                                                     ~41, ->74
   44    69    >   INIT_USER_CALL                                0          'call_user_func_array', !3
         70        SEND_ARRAY                                               !1
         71        CHECK_UNDEF_ARGS                                         
         72        DO_FCALL                                      0  $42     
         73      > RETURN                                                   $42
   49    74    >   FETCH_DIM_R                                      ~43     !3, 0
         75        IS_IDENTICAL                                             ~43, 'self'
         76      > JMPZ                                                     ~44, ->150
   50    77    >   BOOL_NOT                                         ~45     !6
         78      > JMPZ                                                     ~45, ->83
   51    79    >   NEW                                              $46     'Exception'
         80        SEND_VAL_EX                                              'Use+of+self+in+an+invalid+context'
         81        DO_FCALL                                      0          
         82      > THROW                                         0          $46
   54    83    >   NEW                                              $48     'ReflectionClass'
         84        SEND_VAR_EX                                              !6
         85        DO_FCALL                                      0          
         86        ASSIGN                                                   !7, $48
   55    87        INIT_METHOD_CALL                                         !7, 'getMethod'
         88        CHECK_FUNC_ARG                                           
         89        FETCH_DIM_FUNC_ARG                               $51     !3, 1
         90        SEND_FUNC_ARG                                            $51
         91        DO_FCALL                                      0  $52     
         92        ASSIGN                                                   !8, $52
   57    93        INIT_METHOD_CALL                                         !8, 'isPrivate'
         94        DO_FCALL                                      0  $54     
         95      > JMPZ                                                     $54, ->117
   58    96    >   INIT_METHOD_CALL                                         !8, 'getDeclaringClass'
         97        DO_FCALL                                      0  $55     
         98        INIT_METHOD_CALL                                         $55, 'getName'
         99        DO_FCALL                                      0  $56     
        100        IS_NOT_IDENTICAL                                 ~57     !6, $56
        101      > JMPNZ_EX                                         ~57     ~57, ->108
   59   102    >   INIT_FCALL                                               'method_exists'
        103        SEND_VAR                                                 !8
        104        SEND_VAL                                                 'setAccessible'
        105        DO_ICALL                                         $58     
        106        BOOL_NOT                                         ~59     $58
        107        BOOL                                             ~57     ~59
        108    > > JMPZ                                                     ~57, ->113
   60   109    >   NEW                                              $60     'Exception'
        110        SEND_VAL_EX                                              'Attempting+to+call+private+method+in+an+invalid+context'
        111        DO_FCALL                                      0          
        112      > THROW                                         0          $60
   63   113    >   INIT_METHOD_CALL                                         !8, 'setAccessible'
        114        SEND_VAL_EX                                              <true>
        115        DO_FCALL                                      0          
        116      > JMP                                                      ->149
   64   117    >   INIT_METHOD_CALL                                         !8, 'isProtected'
        118        DO_FCALL                                      0  $63     
        119      > JMPZ                                                     $63, ->149
   65   120    >   INIT_FCALL                                               'method_exists'
        121        SEND_VAR                                                 !8
        122        SEND_VAL                                                 'setAccessible'
        123        DO_ICALL                                         $64     
        124        BOOL_NOT                                         ~65     $64
        125      > JMPZ                                                     ~65, ->130
   66   126    >   NEW                                              $66     'Exception'
        127        SEND_VAL_EX                                              'Attempting+to+call+protected+method+in+an+invalid+context'
        128        DO_FCALL                                      0          
        129      > THROW                                         0          $66
   69   130    > > JMP                                                      ->134
   70   131    >   INIT_METHOD_CALL                                         !7, 'getParentClass'
        132        DO_FCALL                                      0  $68     
        133        ASSIGN                                                   !7, $68
   69   134    >   INIT_METHOD_CALL                                         !7, 'getName'
        135        DO_FCALL                                      0  $70     
        136        IS_NOT_IDENTICAL                                         !6, $70
        137      > JMPNZ                                                    ~71, ->131
   72   138    >   INIT_METHOD_CALL                                         !7, 'getName'
        139        DO_FCALL                                      0  $72     
        140        IS_NOT_IDENTICAL                                         !6, $72
        141      > JMPZ                                                     ~73, ->146
   73   142    >   NEW                                              $74     'Exception'
        143        SEND_VAL_EX                                              'Attempting+to+call+protected+method+in+an+invalid+context'
        144        DO_FCALL                                      0          
        145      > THROW                                         0          $74
   76   146    >   INIT_METHOD_CALL                                         !8, 'setAccessible'
        147        SEND_VAL_EX                                              <true>
        148        DO_FCALL                                      0          
        149    > > JMP                                                      ->182
   78   150    >   FETCH_DIM_R                                      ~77     !3, 0
        151        IS_IDENTICAL                                     ~78     ~77, 'static'
        152      > JMPZ_EX                                          ~78     ~78, ->157
        153    >   INIT_FCALL                                               'function_exists'
        154        SEND_VAL                                                 'get_called_class'
        155        DO_ICALL                                         $79     
        156        BOOL                                             ~78     $79
        157    > > JMPZ                                                     ~78, ->170
   79   158    >   NEW                                              $80     'ReflectionClass'
        159        GET_CALLED_CLASS                                 ~81     
        160        SEND_VAL_EX                                              ~81
        161        DO_FCALL                                      0          
        162        ASSIGN                                                   !7, $80
   80   163        INIT_METHOD_CALL                                         !7, 'getMethod'
        164        CHECK_FUNC_ARG                                           
        165        FETCH_DIM_FUNC_ARG                               $84     !3, 1
        166        SEND_FUNC_ARG                                            $84
        167        DO_FCALL                                      0  $85     
        168        ASSIGN                                                   !8, $85
        169      > JMP                                                      ->182
   82   170    >   NEW                                              $87     'ReflectionClass'
        171        CHECK_FUNC_ARG                                           
        172        FETCH_DIM_FUNC_ARG                               $88     !3, 0
        173        SEND_FUNC_ARG                                            $88
        174        DO_FCALL                                      0          
        175        ASSIGN                                                   !7, $87
   83   176        INIT_METHOD_CALL                                         !7, 'getMethod'
        177        CHECK_FUNC_ARG                                           
        178        FETCH_DIM_FUNC_ARG                               $91     !3, 1
        179        SEND_FUNC_ARG                                            $91
        180        DO_FCALL                                      0  $92     
        181        ASSIGN                                                   !8, $92
   87   182    >   INIT_METHOD_CALL                                         !8, 'invokeArgs'
        183        SEND_VAL_EX                                              null
        184        SEND_VAR_EX                                              !1
        185        DO_FCALL                                      0  $94     
        186      > RETURN                                                   $94
        187*       JMP                                                      ->197
   88   188  E > > CATCH                                       last         'Exception'
   89   189    >   INIT_FCALL                                               'trigger_error'
        190        INIT_METHOD_CALL                                         !9, 'getMessage'
        191        DO_FCALL                                      0  $95     
        192        CONCAT                                           ~96     'call_user_func%2A%28%29+expects+parameter+1+to+be+a+valid+callback%3A+', $95
        193        SEND_VAL                                                 ~96
        194        SEND_VAL                                                 512
        195        DO_ICALL                                                 
   90   196      > RETURN                                                   null
   94   197*       INIT_METHOD_CALL                                         !8, 'invokeArgs'
        198*       SEND_VAL_EX                                              null
        199*       SEND_VAR_EX                                              !1
        200*       DO_FCALL                                      0  $98     
        201*       RETURN                                                   $98
   95   202*     > RETURN                                                   null

End of function call_user_func_array_fixed

Class Car:
Function run:
Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 62) Position 1 = -2
filename:       /in/BYIV2
function name:  run
number of ops:  5
compiled vars:  none
line      #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   99     0  E >   INIT_FCALL                                               'call_user_func_fixed'
          1        SEND_VAL                                                 'self%3A%3AgetName'
          2        DO_FCALL                                      0  $0      
          3      > RETURN                                                   $0
  100     4*     > RETURN                                                   null

End of function run

Function getname:
Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 62) Position 1 = -2
filename:       /in/BYIV2
function name:  getName
number of ops:  2
compiled vars:  none
line      #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
  102     0  E > > RETURN                                                   'Car'
  103     1*     > RETURN                                                   null

End of function getname

End of class Car.

Class Toyota:
Function getname:
Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 62) Position 1 = -2
filename:       /in/BYIV2
function name:  getName
number of ops:  2
compiled vars:  none
line      #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
  108     0  E > > RETURN                                                   'Toyota'
  109     1*     > RETURN                                                   null

End of function getname

Function run:
Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 62) Position 1 = -2
filename:       /in/BYIV2
function name:  run
number of ops:  5
compiled vars:  none
line      #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   99     0  E >   INIT_FCALL                                               'call_user_func_fixed'
          1        SEND_VAL                                                 'self%3A%3AgetName'
          2        DO_FCALL                                      0  $0      
          3      > RETURN                                                   $0
  100     4*     > RETURN                                                   null

End of function run

End of class Toyota.

Generated using Vulcan Logic Dumper, using php 8.0.0


preferences:
157.29 ms | 1414 KiB | 27 Q