Recently faced with such a problem a simple example:

<?php class a { protected static $self = false; protected function __construct() { } } class b extends a { protected static $self = false; public static function build(){ if(!self::$self){ self::$self = new self(); } return self::$self; } public function doSomeThing() { echo 2; } } class c1 extends a { protected static $self = false; public static function build(){ if(!self::$self){ self::$self = new self(); } return self::$self; } public function doSomeThingElse() { echo 3; } } b::build()->doSomeThing(); c1::build()->doSomeThingElse(); 

there is a duplicate code in the heirs

 protected static $self = false; public static function build(){ if(!self::$self){ self::$self = new self(); } return self::$self; } 

How can it be taken to the parent class a without disturbing the logic? For example, if we do not specify protected static $self = false; in the successor, we will receive other logic of behavior of the static method build()

  • Well, what's the problem to transfer the build method to class a? - u_mulder
  • You probably have a problem in that you don’t know about the static as a "synonym" of $this or self . In short, "later static binding" - ArchDemon pm
  • Well, the inheritance of singletons is something not entirely necessary. - u_mulder
  • I wrote a simple example in my task (what is acting as "class a" here) has the magic __get method - when it first accesses a property, it uses the unique methods of children to crawl into the database 1 time and write data to the class properties. And I’m doing this bunch of heirs, because the tables will change and the data retrieval requests will also change. Therefore, it will not be necessary to climb the entire project and change the access to the database in each section. - Mcile 2:57 pm
  • I need to keep the child object stored in protected static $ self, not the object of class a. I can use the traits, the magic property of CLASS , I did not understand how to put it into the parent class a. I also tried to write protected static $ class_name = CLASS ; transfer build () to parent and write $ class_name = self :: $ class_name in it; self :: $ self = new $ class_name (); But he swore that he could not take self :: $ class_name from the child - Mcile

1 answer 1

Hurray, found a way - got rid of the repeating method and the repeating property

 trait build{ public static function build(){ if(!isset($build_keeper[__CLASS__])){ $build_keeper[__CLASS__] = new self(); } return $build_keeper[__CLASS__]; } } class a { protected static $build_keeper = []; protected function __construct() { } } class b extends a { use build; public function doSomeThing() { echo 2; } } class c1 extends a { use build; public function doSomeThingElse() { echo 3; } } b::build()->doSomeThing(); c1::build()->doSomeThingElse(); 

really have to use the short line use build; but this is much better

@u_mulder suggested better answer

 <?php class a { protected static $build_keeper = []; public static function build(){ if(!isset(self::$build_keeper[static::class])){ self::$build_keeper[static::class] = new static(); } return self::$build_keeper[static::class]; } protected function __construct() { } } class b extends a { public function doSomeThing() { echo 2; } } class c1 extends a { public function doSomeThingElse() { echo 3; } } b::build()->doSomeThing(); c1::build()->doSomeThingElse(); 

Add a link to how it works

  • one
    Well, then why treit use in this case? Transfer build to the parent class and use new static() . - u_mulder
  • one
    A working example is 3v4l.org/VAP53 - u_mulder
  • @u_mulder thanks for the reply! Until he himself collided head-on with late static binding, he thought he knew about him. - Mcile