views:

34

answers:

2

I would like to prevent foo() from being executed by any other class than B. How can I check which class created object A?

<?php
class A
{
    public function foo()
    {
        if (.... B )    // what should be on the dotts?
           echo 'I\'m created by class B, which is fine';
        else
           echo 'Execution of foo() is not allowed';
    }
}

class B
{
    public function go()
    {
        $a = new A;
        $a->foo();
    }
}

class C
{
    public function go()
    {
        $a = new A;
        $a->foo();
    }
}

$b = new B;
$b->go();  // result: I\'m created by class B, which is fine

$c = New C;
$c->go();  // result: 'Execution of foo() is not allowed'
A: 

Declare foo in class B instead and make it private and, optionally, final. Why would want to define in A a method that can only be called by B?

Artefacto
The example I gave is of course a simplification of reality. I'm using the Yii framework that uses a Model class having a method save().To solve a problem of having multiple dependent classes I'm using a Facade design patron. The Facade class does validation and is calling methods of classes it is hiding from the rest of the world. Now I need to prevent that the save methodes of the classes contained by the Facade class can use by any other class than the Facade class. The rest of the methods are public so to speak.Making the save() methods private is no option, because they are public
donnut
@donnut Can't you just not leak the object instances used by the façade to the outside?
Artefacto
@Artefacto This would mean to restrict the complete object the façade is using instead of only one of it's methods. The class may be used in other situations, except of this one method (save()).
donnut
+3  A: 

A commonly asked question (e.g. http://stackoverflow.com/questions/3308406/how-to-get-called-function-name-in-construct-without-debug-backtrace), but in a well-designed application it shouldn't be necessary for a class to know where it's being called from, or to prevent being instantiated when requested.

If you need this type of restriction, then make your class a private attribute of the main class that is permitted to access it.

If you absolutely have to do it, pass the caller through as an argument to the method in preference to the horrendously inefficient debug_backtrace method.

Mark Baker
I can not restrict the method as it is declared public in the framework I'm using.Your last option seems the only feasible one, although I need to overload the method to add an extra argument, but at least 'foo()' can remain public.
donnut
I agree with this. Either pass in the invoker to the constructor and store it inside the instance to check on it later or pass it with the method calls.
Gordon