skip to Main Content

Is there a PHP namespace extension that allows you to import/use/alias functions as if it was extended directly into the class rather your typical namespace’d silo?

main.php

<?php 
namespace api;

class main extends core{
  print $this->whoami; // prints computer
}

core.php i.e. class core holding basic functions / standards:

<?php 
namespace api;

class core{
  function __construct(){
    $this->whoami = "computer";
  }
}

I want to add modular like classes and or functions that can be directly access from the class i.e.,

function-addon.php:

<?php 
namespace api;
    
function abc($a){
 print $a;
}

function-class.php

<?php 
namespace api;

class tools{
  function tool_a( $a ){
     return $a;
  }  
}

with main.php looking like this (non working sample below):

<?php 
namespace api;

use function apiabc as abc; 
use apitools as tools;

class main extends core{
  print $this->whoami; // prints computer
  
  print $this->abc(5); // print 5 (desired access)
  
  print tools::tool_a(10); //print 10

}

The goal is "$this->abc" access and not i.e., tools:tool_a.

3

Answers


  1. Chosen as BEST ANSWER

    As I experiment I have a working solution, but I'm not a huge fan of yet as it doesn't use namespaces / aliases.

    <?php 
    namespace api;
    
    require("function-addon.php");
    
    class main extends core{
    }
    

    function-addon.php:

    <?php 
        
    function abc($a){
     print $a;
    }
    

    Which would then allow the following to work:

    <?php 
    namespace api;
    
    require("function-addon.php");
    
    class main extends core{
      
       function __call( $func, $arg ){
         return $this->func($arg);
       }
    
    }
    

    The above allows the magic __call function access the locally referenced function-addon.php file.


  2. The solution here is PHP Traits (https://www.php.net/manual/en/language.oop5.traits.php)

    Per @nice_dev reference, a PHP trait implements a way to reuse code.

    function-addon.php:

    <?php
    namespace api;
    
    trait tools{
      function abc($a;){
       return $a;
      }
    }
    

    Which would then allow the following to work:

    <?php 
    namespace api;
    
    require("function-addon.php");
    
    class main extends core{
    
       use tools;
      
       function __construct(){
          $this->abc(5); //returns 5
       }
    
    }
    

    Make sure you use namespace in your traits!

    Login or Signup to reply.
  3. Since you’re working all within in the same namespace, you don’t actually need any imports.

    Assuming you’re using composer, note that psr-4 doesn’t work on autoloading functions. But you can specify "files" to be autoloaded in your composer.json file.

    For example you can use:

    {
      "autoload": {
        "psr-4": {
          "api\": "api"
        },
        "files": ["api/abc.php"]
      }
    }
    

    Now that we got that out of the way,
    Let’s say your main file is /index.php:

    <?php
    
    use apimain;
    
    require __DIR__ . '/vendor/autoload.php';
    
    echo main::abc(5); // 5
    $main = new main();
    $main->abc(6); // 6
    echo $main->whoami; // computer
    

    The main file would look something like this /api/main.php:

    <?php
    namespace api;
    
    class main extends core {
        public function __call($name, $arguments)
        {
            if(function_exists(__NAMESPACE__.'\'.$name)) {
                return call_user_func_array(__NAMESPACE__.'\'.$name, $arguments);
            }
        }
        public static function __callStatic($name, $arguments)
        {
            if(function_exists(__NAMESPACE__.'\'.$name)) {
                return call_user_func_array(__NAMESPACE__.'\'.$name, $arguments);
            }
        }
    }
    

    core would look like this: /api/core.php:

    <?php
    namespace api;
    
    class core{
        function __construct(){
            $this->whoami = "computer";
        }
    }
    

    abc.php like this /api/abc.php:

    <?php
     namespace api;
    
     function abc($a){
         print $a;
     }
    

    But note that if you need to "import" from another namespace, then you’ll probably run into trouble since you need a way to specify which namespace to import from. The imports list, to the best of my knowledge, is a shorthand to save you from typing out the full namespace of whatever you’re "importing". But at runtime, the imports list no longer exists, and you can’t, for example, use eval in order to take advantage of the import to turn a string like "abc" into "apiabc". You’d need another way to do this.

    I’m not much of a fan of __call, and __callStatic, I’d sooner define the methods you’re importing.

    A good way to do this is through a trait.
    Then when you import, you can use a trait, and it will be part of the class.

    For example:

    /api/xyz.php:

    <?php
    namespace api;
    
    trait xyz
    {
        function xyz($a)
        {
            print $a;
        }
    }
    

    Then you’d use it like so /api/main.php:

    <?php
    namespace api;
    
    class main extends core {
    
        use xyz;
    }
    

    Then index.php: /index.php

    <?php
    
    use apimain;
    
    require __DIR__ . '/vendor/autoload.php';
    
    $main = new main();
    $main->xyz(7); // 7
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search