Search code examples
phpimportalias

import and alias a static method from a class


I am trying to alias a static method from a utility/helper class, the documentation does not give anything regarding static methods and using those defined there doesn't work for static methods (as it seems so).

So say I have this class:

namespace App\Helpers;

class HTTP {

    public static function extract_path_from_url( string $url ) {
        $parsed_url = wp_parse_url( $url );
        if ( ! isset( $parsed_url['path'] ) ) {
            return false;
        }
        return (string) $parsed_url['path'];

    }

}

then trying to use it on a different file:

<?php

echo \App\Helpers\HTTP::extract_path_from_url( 'http://example.com/test' );

that one above works

but trying to alias it:

<?php

use \App\Helpers\HTTP\extract_path_from_url as extract_path;

echo extract_path( 'http://example.com/test' );

would output

Fatal error: Uncaught Error: Call to undefined function App\Helpers\HTTP\extract_path_from_url()

even:

<?php

use \App\Helpers\HTTP::extract_path_from_url as extract_path;

echo extract_path( 'http://example.com/test' );

shows this weird error:

Parse error: syntax error, unexpected '::' (T_PAAMAYIM_NEKUDOTAYIM)

Is this possible?

Regards,


Solution

  • Aliasing doesn't magically convert methods into functions, try this instead

    <?php
        use \App\Helpers\HTTP as extract_path;
        echo extract_path::extract_path_from_url( 'http://example.com/test' );
    

    Also (it should go without saying) when you alias this only affects the namespace and class name, not methods of the class. These are generally used for 1 of 2 things. Resolving naming conflicts

     use NamespaceOne\Someclass;
     use NamespaceTwo\Someclass as SecondClass;
    

    If these were both put without an alias then using

     Someclass::method()
    

    Would be ambiguous.

    The second thing they can be used for is if you need a lot of classes imported from one namespace. Such as this:

    use App\Exceptions\NoFile;
    use App\Exceptions\FileSize;
    use App\Exceptions\FileType;
    
    throw new NoFile();
    throw new FileSize();
    throw new FileType();
    

    Can be done this way:

    use App\Exceptions as E;
    
    throw new E\NoFile();
    throw new E\FileSize();
    throw new E\FileType();
    

    Which is not only shorter, but easier to maintain if you change the namespace you have to only change it for the alias and then all is good. So in short it's not really intended for what you want to use it for.

    Wrap it

    You can always make a wrapper for it:

    if(!function_exists('extract_path_from_url')){
         function extract_path_from_url($url){
            return \App\Helpers\HTTP::extract_path_from_url($url);
         }
    }
    

    And then call it to your hearts content. Performance wise you do have an extra call by wrapping it, but generally wrappers make it easier to maintain. For example if you rename that method or class, you can change it in the wrapper and everything is good. So there is an argument to be made for either option.

    You don't have to check if the function exists, but depending on how your overall system works it may not be a bad idea, so I included it in the example just for the sake of completeness. Personally in a case like this, I don't see any issue putting it right in the same file with the class, just remember to load it. If you are using autoloading the functions won't be included unless you manually load the file or otherwise force it to autoload. Assuming nothing else uses the class first, of course.

    One method I have used in the past that I really like, is to make a file named http_functions (classname + _functions) and then add a static method to the class that registers the functions:

      class HTTP {
          public static function register_functions(){
              require 'http_functions.php';
          }
      }
    

    Then when you call HTTP::register_functions() it autoloads HTTP class and includes all the functional wrappers. In fact I do this very thing in my really super awesome debug print class (queue shameless plug) https://github.com/ArtisticPhoenix/Debug

    Just some thoughts, enjoy!