1

If I am designing a framework with PHP and in my framework there is a A class and a AManager class.

What can I do to let all the A object methods or class methods can only be called within AManager methods?

Such as:

class A {
  public function __construct() {
    if( the calling environment is not within AManager Object Method )
      throw new Exception("error")
    else
      init..
  }
}

I have tried to use __callStatic and debug_backtrace of A like:

private static function create($a,$b) {
  echo "in create";
  new Logger($a,$b);
}
public function __callStatic($name, $arguments) {
  $array = debug_backtrace(); // check environment
  var_dump($array);
  return;
  call_user_func_array([Logger::class,$name],$arguments);
}

but the backtrace only shows __callStatic.

So is there any method to deal my requirement?

Manav
  • 553
  • 7
  • 18
Anon
  • 214
  • 1
  • 11
  • Could you not make the methods of `A` protected and extend the class with `AManager` ? It's not *exactly* what you're after but... – CD001 Jul 20 '18 at 08:10

2 Answers2

0

Make AManager extend A and then make your A::__construct to be protected. This means no one can initiate this class (means no new A()) except for classes that extend A.

Then in AManager have factory function:

class AManager extends A {
    protected static $instance;

    public static function factory() {
        if (empty(self::$instance)) {
            self::$instance = new A();
        }

        return self::$instance;
    }
}
Justinas
  • 41,402
  • 5
  • 66
  • 96
0

OH . That's my mistake. It works with [__callStatic,debug_backtrace,call_user_func_array] on A.

Such as:

class A{
   private static $_mfriends = [AManager::class];

   private function __callStatic($name, $arguments){
       $array = debug_backtrace();
       if(count($array) >= 2){
           if(get_class($array[1]["object"]) === self::$_mfriends[0]){
                call_user_func_array([A::class,$name],$arguments);
           }
       }
       throw new Exception("denied!");
   }
   private function __construct(){
      echo "on A constructing.\n";
   }
   // if using direct new A() method instead of create(),will cause compile problem.
   private static function create(){
       return new A();
   }
}

class AManager{
    function createA(){
       return A::create();
    }
}
Anon
  • 214
  • 1
  • 11
  • I've marked the *question* as a duplicate, but this answer - with a bit more explanation - might be worth adding to [the existing question](https://stackoverflow.com/questions/317835/php-equivalent-of-friend-or-internal). – IMSoP Jul 20 '18 at 08:34