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"]);