How to ease the way of storing configuration parameters

Status
Not open for further replies.

Baljeet

Member
Jan 31, 2011
76
0
Hello everyone.

I'm been building a system of my own for a while now, and thaught of sharing some code with you. I'm building some kind of community, with users and stuff.
In most systems, you need to have configuration parameters, that you can easily change, and especially if more people will be administrating the site, so you can build a web form to handle the parameters.

Another usage of this code I will show you, is to store unlimited amount of facts of a user, no need to create another field in the user table!

First, I have an MySQL Table to store my configuration in:

[highlight="sql"]
CREATE TABLE `base_config` (
`scope` bigint(20) unsigned NOT NULL DEFAULT '0',
`module` bigint(20) unsigned NOT NULL DEFAULT '0',
`var` varchar(50) NOT NULL DEFAULT '',
`value` varchar(250) DEFAULT NULL,
PRIMARY KEY (`scope`,`var`,`module`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
[/highlight]
This table has those 4 fields,
  • Scope - This is either a user id or the system
  • Module - as I have built a module based system, this can be used for any modules own' purposes, this is which module that has this particular information. if not used, just use 0, or remove it from everywhere.
  • Var - name of the variable you're looking for
  • Value - value of the variable stored

I have choosen to store max 250 chars in these values. this can of course be altered after own wishes.

Then, we need some PHP code to handle this table, I have choosen to do this as a class as it gets to be a solid configuration item, with no need to interfere with.

The only thing to think about is the database. I have created a special class just to keep an database connection opened, how you solve it, is up to you. I continously use the OOP version of mysqli.

This is my database class:
PHP:
final class db {
	protected static $_dbase = null;
	public function getInstance() {
		if (self::$_dbase === null) {
			self::$_dbase = new mysqli('db_host', 'db_user',
 				'db_password', 'db_name');
			if (mysqli_connect_errno()) {
				echo "Database Connection Error: " .
 					mysqli_connect_error();
				exit(1);
			}
		}
		return self::$_dbase;
	}

	protected function __construct() {}
	protected function __clone() {}
	protected function __destruct() {
		self::$_dbase->close();
	}
}

First, we declare the class and it's member variables. I declare them as protected, if we want to inherit this class some time.

PHP:
class Config {
	protected $module;
	protected $user;
	protected $conf;
	protected $scope;
  • module - will keep information about which module the instance will work for.
  • user - will hold all data for the logged in user
  • conf - will hold all module system data
  • scope - will keep which user we work with


Now, we start creating an constructor, that is an function (method) that is ran when we create an instance for the class, and initiates the whole thing
PHP:
	public function __construct($module, $scope = 0) {
		$this->module = $module;
		$this->scope = $scope;
		$this->load();
	}
We take two parameters to create the class, we need to specify which module and which user we will handle, we store that in the member variables, then we call the load function, wich comes next.

PHP:
	public function load() {
		$db = db::getInstance();
		if ($result = $db->query("SELECT * FROM base_config WHERE scope = '0' AND module='" .
			$this->module . "'")) {
			while ($row = $result->fetch_assoc()) {
				$this->conf[$row['var']] = $row['value'];
			}
			$result->close();
		}
Now, we load everything with scope 0, which means module system specific variables and store them in our array $conf. We let the method continue:
PHP:
		if ($this->scope != 0) {
			if ($result = $db->query("SELECT * FROM base_config WHERE scope = '" . $this->
				scope . "' AND module = '" . $this->module . "'")) {
				while ($row = $result->fetch_assoc()) {
					$this->user[$row['var']] = $row['value'];
				}
				$result->close();
			}
		}
	}
So, if we have a user logged in, ie, scope set to something else but 0, we load as we did above, but into the user member instead.
Now, we have all configuration needed for this run in memory.

we declare a save method, to save modified variables.
PHP:
	public function save() {
		$db = db::getInstance();
		$db->autocommit(false);
We get our db connection, and turn off autocommit, to be able to not modify the database until all changes are done

we continue with saving the user variables:
PHP:
		if ($this->scope != 0) {
			$res = $db->query("DELETE FROM base_config WHERE scope = '" . $this->scope .
				"' AND module = '" . $this->module . "'");
			$stat = $db->prepare("INSERT INTO base_config VALUES ('" . $this->scope . "', '" .
				$this->module . "', ?, ?)");

			$stat->bind_param("ss", $var, $value);

			foreach ((array )$this->user as $var => $value) {

				$stat->execute();
			}
			$db->commit();
		}
First, we delete all of the data connected to this module and user, if a parameter was removed, then we reapply those in the stored variable

and we repeat it all with the system parameters
PHP:
		$res = $db->query("DELETE FROM base_config WHERE scope = '0' AND module = '" . $this->
			module . "'");
		$stat = $db->prepare("INSERT INTO base_config VALUES ('0', '" . $this->module .
			"', ?, ?)");
		$stat->bind_param("ss", $var, $value);
		foreach ((array )$this->conf as $var => $value) {
			$stat->execute();
		}
		$db->commit();
now, we turn autocommit back on so everything is back to normal
PHP:
		$db->autocommit(true);
	}
So, that was that method, so we save the data. now, we go more to the usage interface of the class

Here is how we read out variables:
PHP:
	public function getVar($var) {
		if (isset($this->user[$var])) {
			return $this->user[$var];
		} else {
			return $this->conf[$var];
		}
	}
If the user has it's own variable of the same name, use that instead of the system variable. this can be used for example background colors or themes or other things

now, we want to be able to change a value:
PHP:
	public function setVar($var, $value, $scope = 0) {
		if (!$scope) {
			$this->conf[$var] = $value;
		} else {
			$this->user[$var] = $value;
		}
	}
Don't forget to do a save(); when all variables are modified!

if we wnat to remove it we use this unset, but here, we need to specify if we want to unset it from the user scope or the module scope
PHP:
	public function unsetVar($var, $scope = 0) {
		if (!$scope) {
			unset($this->conf[$var]);
		} else {
			unset($this->user[$var]);
		}
	}

If we ever wants to know which scope this is set up to, this reads it out.
PHP:
	public function getScope() {
		return $this->scope;
	}

And this reads out which module...
PHP:
	public function getModule() {
		return $this->module;
	}

At times, you might want all your variables in an array, so I built this one. I need to typecast the members to array, if someone of them are empty.
PHP:
	public function getArray() {
		return array_merge((array )$this->conf, (array )$this->user);
	}
}

end of class

All Credits goes to one who really made this...
 
Status
Not open for further replies.

Users who are viewing this thread

Top