File private variables in PHP

Is it possible to define private variables in a PHP script so that those variables are only visible in that single PHP script and nowhere else? I want to have an include file that does something without polluting the global namespace. It should work with PHP 5.2, so PHP namespaces are not an option. And there is no OOP here, so I'm not looking for private members of the class. I'm looking for "multiple global" variables that are global in the current script, but nowhere else.

In C, I could do it with a static keyword, but is there something similar in PHP?

Here's a quick example of a "common.php" script:

$dir = dirname(__FILE__);
set_include_path($dir . PATH_SEPARATOR . get_include_path());
// Do more stuff with the $dir variable

      

When I include this file in some script, then the $ dir variable is visible in all other scripts as well, and I don't want that. So how can I prevent this from happening?

+2


source to share


5 answers


There are several things you could do to save $dir

from subsequent files

Example 1

set_include_path(dirname(__FILE__) . PATH_SEPARATOR . get_include_path());

      

This is most obvious.

Example 2

$dir = dirname(__FILE__);
set_include_path($dir . PATH_SEPARATOR . get_include_path());
// work with $dir
unset($dir);

      

Just discard the variable after you define and use it. Note that this will disable any named variable in $dir

use prior to this script being enabled.

Example 3



define('DIR_THIS', dirname(__FILE__));

set_include_path(DIR_THIS . PATH_SEPARATOR . get_include_path());

      

I would prefer to override a global constant like this.

Example 4

function my_set_include_path {
  $dir = dirname(__FILE__);
  set_include_path($dir . PATH_SEPARATOR . get_include_path());
  // Do more stuff with the $dir variable
  $my_other_var = 'is trapped within this function';
}

my_set_include_path();

      

You can define as many variables inside this function and not affect the global namespace.

Conclusion

The first method is the easiest way to solve this problem, however, since you want to use $dir

it again , this may not be ideal. The last example will at least contain $dir

(and any others defined in this function) from the global namespace.

+7


source


The only way you're going to accomplish anything close to what you want is to wrap everything in that included file in a function and call it. If the file needs to be executed itself, you can still do

<?php
run_myfile()
function run_myfile() {
...
}
?>

      



There is no general way to make a variable a file-only scope outside of namespaces, classes, or functions.

+6


source


Ok, I probably get for this, but if you are completely desperate to use the Registry to do this, I hacked a little one that does no classes (since I assume there is no OOP here, so I am not looking for private members of the class, hence you don't want to do it with OOP at all)

function &registry_get_instance()
{
    static $data = array();
    return $data;
}

      

static $data

variable is internally stored inside the function scope, so you can call the function wherever you want and always get the same content. The decisive point is the return by reference , for example

$registry = &registry_get_instance();     // get $data array by reference
$registry['foo'] = 'bar';                 // set something to $data
unset($registry);                         // delete global reference to $data
print_r(&registry_get_instance());        // show $data 

      

Obviously, you must still have $ registry as a variable in the global scope when calling this method from the global scope. This way, you can add a few more functions to make the registry more usable, for example. to set data to the registry:

function registry_set($key, $value) 
{
    $registry = &registry_get_instance();
    $registry[$key] = $value;
}

      

and to get it:

function registry_get($key)
{
    $registry = &registry_get_instance();
    if(array_key_exists($key, $registry)) {
        return $registry[$key];
    } else {
        trigger_error(sprintf(
            'Undefined Index: %s', htmlentities($key)
        ), E_USER_NOTICE);
    }
}

      

and to check if a key exists:

function registry_isset($key)
{
    $registry = &registry_get_instance();
    return array_key_exists($key, $registry);
}

      

which you could use like this:

registry_set('foo', 'bar');         // setting something to the registry
var_dump( registry_isset('foo') );  // check foo is in the registry now
echo registry_get('foo');           // prints 'bar'
echo registry_get('punt');          // raises Notice

      

You can populate the registry from the include file with an additional method like this:

function registry_load_file($file)
{
    if(!is_readable(realpath($file))) {
        return trigger_error(sprintf(
            'File is not readable: %s', htmlentities($file)
        ), E_USER_WARNING);
    }
    $config = include $file;
    if(!is_array($config)) {
        return trigger_error(sprintf(
            'Expected file %s to return an array', htmlentities($file))
        , E_USER_WARNING);
    }
    $registry = &registry_get_instance();
    $registry += $config;
}

      

with an included file that should return an array:

// config.php
return array(
    'setting1' => 'something'
);

      

and then you can do

registry_load_from_file('config.php');  // add the contents of config to registry
print_r(registry_get_instance());       // show content of registry

      

Of course there are now six functions in the global scope just to not have a global variable. Don't know if it's worth it, especially since I'm considering static

in functions and all this reference information a dubious practice.

Let's take this as a proof of concept :)

+1


source


Why not just put everything in a static class? Then you only have one "variable" which can conflict with the global namespace.

class MyClass {
    public static $myvar = 1;
    public static $myvar2 = "xyz";

    public static function myfunction() {
        self::$myvar++;
        self::$myvar2 = "abc";
    }
}
// References to class items, if needed
MyClass::myfunction();
MyClass::$myvar += 3;

      

0


source


If the problem you are trying is simply:

$dir = dirname(__FILE__);
set_include_path($dir . PATH_SEPARATOR . get_include_path());
// Do more stuff with the $dir variable

      

Then the solution would be to change the inclusion path with respect to '.' in your settings. For instance. edit:

include_path=includes:/usr/local/php

      

to

include_path=./includes:/usr/local/php

      

Note that the script is out of scope other than where you explicitly include / require it (as the _once check applies globally), but I would highly recommend against include include / require from within the function - its much more transparent, nested / required at the top of the script.

I think the problem you are trying to solve is based on a false premise and you should look for another way to fix it. If you want the code in the included file to behave differently depending on what includes it, then really you should split it into 2 separate files - or maybe even 3 - 2 for different types of behavior and 1 for ordinary.

FROM.

-1


source







All Articles