Restrict what can create a PHP Class

2019-04-07 11:29发布

问题:

I got two classes, "A" and "B". In the application logic no one is allowed to create an object of class "B", except for class "A". But, since I dont want to have the two classes in the same file I cant restrict it with the "private" properity.

Is it possible to create this kind of restriction? If someone other then "A" tries to create an object of class "B", you say piss off!?

回答1:

This is as hacky as it get's and you should not use it. I only post it, because I like hacky things ;) Furthermore this will throw an error if E_STRICT error reporting is enabled:

class B
{
    private function __construct() {}

    public function getInstance() {
        if (!isset($this) || !$this instanceof A) {
            throw new LogicException('Construction of B from a class other than A is not permitted.');
        }

        return new self;
    }
}

class A
{
    function someMethod() {
        $b = B::getInstance(); // note that I'm calling the non-static method statically!
    }
}

The reason why this works is a "feature" which may be seen in the second example of this manual page.



回答2:

You could inspect the backtrace:

class B
{
    public function __construct()
    {
        $chain = debug_backtrace();
        $caller = $chain[1]['class'];

        if ('A' != $caller) {
            throw new Exception('Illegal instantiation');
        }
    }
}


回答3:

In the constructor of B, require that A be passed in. When you then want to get B from A, just create a B and pass in A. When new B is called, it will require A be passed in.

class A
{
    private $b;

    private function getB()
    {
        if (null === $this->b)
        {
            $this->b    = new B($this);
        }

        return $this->b;
    }
}

class B
{
    public function __construct(A $a)
    {

    }
}


回答4:

Maybe you want to use something like this:

class A
{
        protected function __construct ()
        {
        }
}

class B extends A
{
        public function __construct ()
        {
                $a = new A();
        }
}

$b = new B();


回答5:

Use get_called_class to find out which class tries to instantiate an object:

class B
{
        public function __construct ()
        {
                if(get_called_class() != 'A') {
                    //booboo
                }
        }
}