views:

492

answers:

7

I have a program that I use on several sites. It uses require('config.php'); to set any site dependant variables like mysql connect info, paths, etc.

Let's say that I use one of these site-dependant variables in a function, like $backup_path.

This variable was initially declared in config.php, and does not appear in the main program file.

I need to access this variable in function makebackup($table_name); (also in a separate functions.php file).

Is it better to say

makebackup('my_table');

and then use "global $backup_path" inside the function, or is it better to call the function using

makebackup('my_table',$backup_path);

The argument for the first is that it keeps the main program flow simple and easy to understand, without clutter.

The argument for the second is that it might not be obvious that the variable $backup_path exists after some time has passed, and debugging or reworking could be difficult.

Is one or the other of these techniques "standard" among professional programmers? Or should I be using $_SESSION to declare these global variables?

+1  A: 

I'm think you must use Singleton of Factory class config for this purposes.

function makebackup($table)
{
   $backup_path = ConfigFactory().getConfig($some_site_specific_data).getBackupPath()
   mysqldump($table, $backup_path)
}
Alexey Sviridov
Can you provide a link so I can find out more?
Andrew Swift
I do like the idea of using a getBackupPath() function to find this info. That way it's more modular and you can change the internals of getBackupPath() later if you need to.
Nathan Long
@Anrew Singleton and Factory - most popular design patterns (http://en.wikipedia.org/wiki/Design_pattern_%28computer_science%29)Singleton - http://en.wikipedia.org/wiki/Singleton_pattern#PHPFactory - http://en.wikipedia.org/wiki/Factory_pattern#PHP
Alexey Sviridov
+1  A: 

Passing references around is far easier to test (you can give mock configuration objects). Globals less so. You can assert that the reference is not null on the method. I would call testability best practice.

Joe
+4  A: 

The second alternative,

makebackup('my_table', $backup_path);

is a reusable function and therefore generally preferable. The extra argument is not a big price for reusability.

If you are entirely sure that you'll ever use that function in that particular application only, and for $backup_path only, then maybe consider the global alternative. Even then it's good to check that the global variable actually exists. And be aware that it's extremely difficult to get rid of globals once you start using them.

Joonas Pulakka
I like this option because right up front, you can see that the global variable is being used.
Nathan Long
+1  A: 

Remember that you can set a default value for your function:

function makebackup($table, $dir = CONFIG_BACKUP_PATH)

That way you won't have to supply the variable in the default case, you can simply assume that the configured backup path is the default.

This assumes that you are using constants, not global variables.

Vegard Larsen
I am using this solution and it works perfectly.
Andrew Swift
+1  A: 

Label that global variable

Personally, I have also taken to marking global variables very clearly. If I must use them, I want to be clear about them.

So here, I'd rename $backup_path to $GLOBAL_backup_path. Every time I saw it, I'd know to be careful with it.

Nathan Long
A: 

Not sure there's really a 'right' way to do it, but another option would be something like this:

function makebackup($table, $backup_path = '') {
    if ( $backup_path == '' ) {
        if ( isset($GLOBALS['backup_path']) ) {
            $backup_path = $GLOBALS['backup_path'];
        }
        else {
            die('No backup path provided');
        }
    }
 }

That way you can either pass in the value (for testing and future use) or if you don't pass it in, then the function will look for a possible global variable.

Vex
+1  A: 

An alternative option is using php constants with define().

Your config.php will set constants for every parameter (mysql connection, css style, wathever). Then you will not need to pass variables to functions nor using global.

One downside is that you can define only booleans, floats, strings or integers, no complex data structures.

Anonymous