Home > Blockchain >  Is it possible to 'auto-declare' a parent class property for every child class?
Is it possible to 'auto-declare' a parent class property for every child class?

Time:03-30

Suppose I've got a library class and an autoloader that includes any class that starts with MyLibrary_ from the classes directory:

spl_autoload_register(
    function ($classname) {

        if(class_exists($classname)) return;

        if(strpos($classname, 'MyLibrary_') !== 0) return;

        //if such class exists, include it
        $class_file = __DIR__.'/classes/'.$classname.'.php';
        if(file_exists($class_file)){
            include $class_file;
        }
    }
);
if(!class_exists('Someprefix_MyLibrary')){
    class Someprefix_MyLibrary{}
}
$mylibrary = new Someprefix_MyLibrary;

Then, in the /classes/strings.php file there is a child class MyLibrary_strings:

class MyLibrary_strings extends Someprefix_MyLibrary{

   public punction __construct(){
       $this->strings = new self(); //not declared in parent class
   }

   //make first letter capital in a multi-byte string
    public function mb_ucfirst($string, $encoding){
        $firstChar = mb_substr($string, 0, 1, $encoding);
        $then = mb_substr($string, 1, null, $encoding);
        return mb_strtoupper($firstChar, $encoding) . $then;
    }
}

I would like to do something like:

$new_string = $mylibrary->strings->mb_ucfirst('somestring');

Unless I declare public $strings in parent class, my IDE warns me that a property has been declared dynamically, and in other child classes, the strings property will be marked as not found. What I want is to automatically include a parent property for each file that has been placed into the classes directory OR for every child class of Someprefix_MyLibrary, without having to manually declare every property.

Is it possible to do it, and how?

CodePudding user response:

You can achieve this using the __get magic method in php like so.

In your parent class, add a __get method:

class Someprefix_MyLibrary{
 
    public function __get(string $name)
    {
        return $this->{$name} = null;
    }
}

And call any undeclared property you need for example in your child class:

class MyLibrary_strings extends  Someprefix_MyLibrary{
 
    public function undeclaredProperty(){
        return $this->string;
    }

}

Note: Thus, when calling any undeclared property, we will fall into the __get magic method, where we will declare it and return it.

CodePudding user response:

Have you thought about using namespaces and static methods instead?

You would have to change your auto-loading, but something like:

// MyLibrary_Strings.php
namespace MyLibrary {
    class Strings {
        public static function mb_ucfirst($string, $encoding) {
            $firstChar = mb_substr($string, 0, 1, $encoding);
            $then = mb_substr($string, 1, null, $encoding);
            return mb_strtoupper($firstChar, $encoding) . $then;
        }
    }
}

// MyLibrary_Arrays.php
namespace MyLibrary {
    class Arrays {
        public static function first($array) {
            return $array[0];
        }
    }
}

// some other code
$result = MyLibrary\String::mb_ucfirst($string, $encoding);
$first_item = MyLibrary\Array::first(["a", "b", "c"]);
  • Related