[PHP-NOTES] note 130646 added to language.oop5.overloading

[email protected] ("[email protected]") Mon, 09 Feb 2026 07:16:34 +0000
Newsgroups php.notes
Message-ID <[email protected]>
I find function overriding/overloading very helpful in non-OO code, and therefore present the following for your use:
(you can drop the pipes for nested calls in pre 8.5)
<?php
function overload( $p, $f, $override=false ) { 
    $types = str_replace( [ '(', ')','{','}' ], [ ',', '',',','' ], $p )
        |> ( fn($x) => explode( ',', $x ) )
        |> ( fn($x) => array_map( 'trim', $x ) )
        |> array_filter(...);    
    if ( is_callable( $types[0] ) && 
            ! isset( $GLOBALS[ $types[0].'_overloaded' ] ) ) 
        throw new Exception(
                   'overload function name not allowed:' . $types[0] );
    $fn = '_';
    if ( array_last( $types ) === '...' ) { 
               $fn = '.'; array_pop( $types ); }
    $fn .= strtolower( join( '_', $types ) );// function signature    
    if ( isset( $GLOBALS[$fn] ) && ! $override ) 
        throw new Exception (
                   'overload function already exists:' . $p );    
    $GLOBALS[ $fn ] = $f; 
    if ( ! is_callable( $types[0] ) ) {
        $fx = <<<'router'
             function {fn}( ...$p ) {
                $vt = []; foreach ( $p as $pp ) 
                                    $vt[] = gettype( $pp );
                $fn = '_{fn}_' . join( '_', $vt );                                        
                for (;;) {
                    if ( isset( $GLOBALS[ $fn ] ) ) {
                        try { 
                              return $GLOBALS[ $fn ]( ...$p ); 
                        } 
                        catch ( Exception $x) { 
                            throw new Exception(
                               'overload function:' + 
                               $fn + ': ' + 
                               $x->getMessage() ); 
                        }
                    }
                    $fn[0] = '.'; //degenerate signature
                    if ( ( $i = strrpos( $fn, '_' ) ) === false ) 
                                               break;
                    $fn = substr( $fn, 0, $i );
                }
                throw new Exception(
                                     'no overload: {fn}(' .  join( ', ', $vt) . ')' );
            };
        router;
        eval( str_replace( '{fn}', $types[0], $fx ) );
        $GLOBALS[ $types[0].'_overloaded' ] = true; 
    }            
    return true;
 }

//use:
    overload( 'add( integer, integer, integer )', 
        fn($a,$b,$c) => ($a + $b + $c).' from 3i form' );    
    overload( 'add( integer, ... )',
        fn(...$i) => array_reduce( $i, fn($I, $i) => $I += $i, 0 ) .
                  ' from integer degen form' );    
    overload( 'add( string, ... )',
        fn(...$s) => array_reduce( $s, fn($a, $s) => $a .= $s, '' ) .' from string degen form' );
    
    echo add( 1, 2 ) . '<br>';
    echo add( 1, 2, 3 ) . '<br>';
    echo add( '3', '+', 5, '=', 8);
?>
------------------------------------------------
output:
3 from integer degen form
6 from 3i form
3+5=8 from string degen form
----
Server IP: 206.189.2.9
Probable Submitter: 105.214.75.153
----
Manual Page -- https://php.net/manual/en/language.oop5.overloading.php
Edit        -- https://main.php.net/note/edit/130646
Del: integrated  -- https://main.php.net/note/delete/130646/integrated
Del: useless     -- https://main.php.net/note/delete/130646/useless
Del: bad code    -- https://main.php.net/note/delete/130646/bad+code
Del: spam        -- https://main.php.net/note/delete/130646/spam
Del: non-english -- https://main.php.net/note/delete/130646/non-english
Del: in docs     -- https://main.php.net/note/delete/130646/in+docs
Del: other reasons-- https://main.php.net/note/delete/130646
Reject      -- https://main.php.net/note/reject/130646
Search      -- https://main.php.net/manage/user-notes.php