Reputation: 262
I have some PHP code similar to the following:
foreach ($settingsarray as $settingsfile)
{
include ($settingsfile);
// do stuff here
}
$settingsarray is an array of file names from a particular folder.
The problem is, that each $settingsfile defines constants (with the same names), which of course, can not be redefined.
What possible methods are there to prevent errors occurring in this situation?
Two options I can think of include, changing all the constants to variables and using PHP namespaces.
However, I'm not sure how I would go about using namespaces, it would require the declaration at the start of every $settingsfile? Is there a method of isolating constants, ariables and functions without using namespaces?
What I would really love, is to be able to do something as simple as:
foreach ($settingsarray as $settingsfile)
{
{//added braces to indicate where the isolation is
include ($settingsfile);
// do stuff here
}//what happens in here does not affect what happens outside of here
}
I should just note, this is part of a new feature, and is the only part of the code that loads all the $settingsfiles. The rest of the code only ever loads one file at a time. One reason I am using constants is so that I don't have to worry about defining variables "global" to be able to access them inside functions.
Upvotes: 2
Views: 2989
Reputation: 1005
My answer is somewhat complex, but should work for you quite nicely. I'm assuming you have a ton of these settings files, since you're so averse to changing each one individually.
If you're able to use namespaces, I'll assume you've already upgraded to PHP 5.3RC2. Copy the following into a .php file, and change the namespace to your liking:
<?php
namespace myapp\config;
function define($key, $val) {
Config::set($key, $val);
}
class Config {
private $vars = array();
// This class should not be instantiated
private function __construct() {}
public function set($key, $val) {
self::$vars[$key] = $val;
}
public function get($key) {
return isset(self::$vars[$key]) ? self::$vars[$key] : NULL;
}
}
?>
Include that in your code, and now making everything work is a simple matter of changing the
<?php
in your settings files to
<?php namespace myapp\config;
If you have a ton of them, a quick 'sed' command in your terminal should take care of it quite nicely, all in one fell swoop.
If I lost you on how to use my code, here's an example:
<?php
require_once('the_php_file_i_just_gave_you.php');
use \myapp\config\Config;
foreach ($settingsarray as $settingsfile) {
include ($settingsfile);
$varname = 'key';
echo "In this file, '$varname' equals: " . Config::get($varname);
}
?>
Good luck!
Upvotes: 4
Reputation: 694
A settings file should not contan PHP code. It should be some kind of "standard" format. http://www.php.net/parse_ini_file
If you routinely feel the need to "redefine constants" then something is amish in the application design.
Upvotes: 0
Reputation: 60276
You have a few options:
Use PHP Namespaces
Surprisingly, PHP actually does have support for namespaces. I was very surprised to find this since I have been working in PHP for years and have never heard of this feature. It is likely a newer feature and one that is not commonly used, so I would suggest not using this method
Use Class Constants
You could use classes and class constants to load your settings. Class constants are local to the defining class, so you will not need to worry about name collisions within the class. You would probably need to do more than include the file, but you could call a method on each class, such as defineConstants() or loadConfiguration() that would define the application constants, keeping the class constants for internal use.
Use Functions to Extend the Settings
Another idea is to create a settings array and separate functions to 'extend' those settings. That way you can over-write any configuration in subsequent functions without causing an error. Finally, if you want to put those in constants, you could loop over the array and use define() to define the constants.
There are many other ways to accomplish what you are trying to do, but these are just a few ideas.
Upvotes: 1
Reputation: 1020
not easy but you could read the php file with file_get_contents($settingsfile) then rewrite the constants, and eval the code.
$settingsstr = file_get_contents($settingsfile);
$settingsstr = preg_replace('/<\?\w*(.*)/', '\\1', $settingsstr);//get rid of the php open tag
$settingsstr = preg_replace('/define\("(\w+)"/', 'define("NAMESPACE_\\1"', $settingsstr);
eval($settingsstr);
Upvotes: 1
Reputation: 546233
Okay, so if I'm understanding you correctly, inside that loop you'd like to do things with the constants defined inside each $settingsfile
and then basically get rid of them after each loop?
Unlike variables, a constant is a value that, once set, cannot be changed or unset during the execution of your script src
Your only option is to change the define()
declarations to variables.
Upvotes: 1