2

Okay, so this has been baking my noodle for a little while now. I have a class with a method that defines a globally accessible function. My question is: how is it possible for an internal class method to define a function that is accessible at the global scope?

Here's a sample:

class MyClass 
{

    // ... accessors, constuctors other methods, et al... 

    // The method in question:
    private function myPrivateMethod()
    {
        if( !function_exists( 'someArbitraryFunction' ) )
        {
            function someArbitraryFunction( $args )
            {
                return "Hello, {$args} world!";
            }
        }            
    } 
}

The class is instantiated as usual, and very early on in the application, but it is instantiated within another class's method. It's a shallow scope-chain, but nested enough that it doesn't make sense (to me) why it would be accessible outside of the application. This goes against my understanding of encapsulation, some insight would be much appreciated.

user916011
  • 505
  • 5
  • 8

1 Answers1

3

Functions declared will always have a global scope. This is not JavaScript.

See:

class MyClass 
{

    // ... accessors, constuctors other methods, et al... 

    // The method in question:
    private function myPrivateMethod()
    {
        if( !function_exists( 'someArbitraryFunction' ) )
        {
            function someArbitraryFunction( $args )
            {
                return "Hello, {$args} world!";
            }
        }            
    } 

    public function run(){
        $this->myPrivateMethod();
    }
}

var_dump(function_exists('someArbitraryFunction')); // false
$obj = new MyClass();
$obj->run();
var_dump(function_exists('someArbitraryFunction')); // true

Being a language from a C/C++ background, there is a distinct behaviour between functions and methods. In PHP, functions do not obey the access modifiers.

Regardless of where they are written in the code, once the execution runs through the declaration, it becomes defined.

If you need a function to obey scoping, which I highly recommend because you get to utilize the GC of variables better, you can use Closures in >= PHP 5.3:

class MyClass{

    private $myArbitraryMethod;

    private function myPrivateMethod(){
        $this->myArbitraryMethod = function($args){

        }
    }

}
mauris
  • 42,982
  • 15
  • 99
  • 131
  • I just saw this [related post](http://stackoverflow.com/questions/4747908/scope-of-declared-function-within-a-function?rq=1), which judging from the documentation, is by design... and I get why it works now, but it seems wrong. – user916011 Oct 24 '12 at 03:09
  • It isn't. Simply think of functions as global functions. If you need functions to obey scoping, I recommend Closures in PHP 5.3. – mauris Oct 24 '12 at 03:11
  • Thanks, I think that's what caught me by surprise. I get it now, and I can see how this can be abused quickly. – user916011 Oct 24 '12 at 03:14
  • Great! I'm glad you got it clarified. (: – mauris Oct 24 '12 at 03:15