Documentation
Installation and Configuration
Before you get started, you may want to check out the requirements
DStruct needs to be one layer below your Document Root. Typically, this would mean placing the DStruct folder in a directory called 'lib', 'library', 'src' or similar. For the purposes of this documentation, we will be call our directory 'lib' and put DStruct in there. The files we will publish on the web will be in a directory called 'public'. An example structure is below:
[Document Root]
-->lib
   -->DStruct
      -->auth
      -->....
      -->tree
      -->inc_bootstrap.php
   -->SomeOtherPackage
   -->MyClassFilesEtc
-->public
   -->index.php
			
			
				Next. make a copy of the clsPrefs.Template.php file in the prefs folder of DStruct and rename it
				clsPrefs.php. Open this in your preferred editor and take a look - all the configuration
				for DStruct is in this file. The only thing you
				need to do to start with is go to the constant APP_NAME and change it to something else representative
				of your project.
			
That's it. You're installed and ready to go.
Getting Started
<?php
// include the bootstrap at the top of each of your scripts (but not in your Class files etc)
require_once '../lib/DStruct/inc_bootstrap.php';
// the bootstrap does a number of things, including registering the autoloader
// ... our classes are now available without using require() etc
$myobj = new MyClass;
// This includes our static helper classes. Validate a UK Postcode:
$valid = Validate::isPostcode('W1C 8QT');
var_dump($valid); // = true
?>
			
			The Autoloader and Writing Your Own Classes
The DStruct bootstrap registers an autoloader. If you want, the autoloader can be used to load your own classes.
				To use the autoloader, you need to follow a few basic rules. Your classes need to be put
				in individual files which start with 'cls', then have the name of the class (case sensitive)
				and finally .php. So for example clsMyClass.php.
			
				Your class needs to be put in a sub-directory of the directory in
				which you placed DStruct. So, for the example in the Installation and Configuration
				section, valid directories would include
				[approot]/lib/myclasses/ or [approot]/lib/mypackage/classes/ etc.
			
				Finally, you need to include the path to your classes in the autoloader_directories
				array created in the Prefs::__construct() method. An example is shown below:
			
// in the Prefs::__construct() method, you could change this:
------------------
// Directories in 'lib' to be scanned by the autoloader should be put here
$this->props['autoloader_directories'] = array(
    'DStruct/dstruct_common',
    // snip ....
    'DStruct/tree'
);
------------------
// to this:
------------------
// Directories in 'lib' to be scanned by the autoloader should be put here
$this->props['autoloader_directories'] = array(
    'DStruct/dstruct_common',
    // snip ....
    'DStruct/tree',
    'mypackage/classes' // added path to project classes
);
			The autoloader searches the directories for the class in the order they are listed in the array, so you can change the order to optimise for your particular application. The returns for doing this are limit though, as the results will usually be cached...
The results are also cached (if any default cache is available). If you change the paths to your files, or to DStruct, you may need to clear the cache to get the autoloader to find the files.
Connecting to a database
Database Access
Caching
DStruct uses caching where possible, so it is important to set up the cache options in your Prefs file correctly. It is also highly advised that you use APC on your server as this greatly increases the speed of PHP.
This is a simple example of how to use the cache object which is generated by the bootstrap to cache within your scripts:
<?php
// include the bootstrap at the top of each of your scripts (but not in your Class files etc)
require_once '../lib/DStruct/inc_bootstrap.php';
// the bootstrap does a number of things, including adding a default cache
$prefs = Prefs::getInstance(); // Prefs is a singleton class containing our preferences
$cache = $prefs->get('cache'); // Fetch the cache object created by the bootstrap
if ($cache->hasServer()) { // the cache is available
    $my_data = $cache->get('my_data'); // attempt to get data from cache
    if ($my_data == false) { // if cache did not already contain our data...
        $my_data = 'foobar'; // set our data
        $cache->set('my_data', $my_data); // put our data in cache for retrieval next time
    }
    echo $my_data; // do something with our data
} else {
    echo 'No cache available!';
}
?>
			You are not limited to only using the default cache...
<?php
// include the bootstrap at the top of each of your scripts (but not in your Class files etc)
require_once '../lib/DStruct/inc_bootstrap.php';
// create a cache object manually...
$cache = APCCache::getInstance(); // APCCache impliments DStructCacheInterface, so has a standard set of methods
if ($cache->hasServer()) {
    // ... and so on like the previous example 
			
			The ObjWatcher Class and Why You Should Use It
				The ObjWatcher class tracks instances of objects in your system to prevent
				bugs which can be caused by multiple instances of the same object in your script.
			
				In the the next example, we will show how a bug could be introduced into your system, and
				the example following will show how the ObjWatcher class can be used to prevent
				the issue. Finally, we will take a look at how the ObjWatcher was used.
			
<?php
// include the bootstrap at the top of each of your scripts (but not in your Class files etc)
require_once '../lib/DStruct/inc_bootstrap.php';
$a = Employee::loadByID(12); // load employee 12
$a->setName('Joe'); // set his name
// load employee 12 in a DIFFERENT object!
// we now have two objects with the same ID in the script.
$b = Employee::loadByID(12);
$b->setName('Brian'); // we haven't realised and set the name for employee 12 again.
// What is the correct name for employee 12???
// If, for instance, we saved the object to the database, the name for employee 12 could depend
// on the order in which we saved the objects.
$b->save();
$a->save();
// Let's fetch our data from the database again.
$c = Employee::loadByID(12);
// Name of employee 12 is now Joe, even though the last name we gave to the employee was Brian.
echo $c->getName(); // echos Joe
?>
			
				Let's try that again, but this time, the loadByID() method will
				be using ObjWatcher. 
			
<?php
// include the bootstrap at the top of each of your scripts (but not in your Class files etc)
require_once '../lib/DStruct/inc_bootstrap.php';
$a = Employee::loadByID(12); // load employee 12
$a->setName('Joe'); // set his name
// load employee 12 in a DIFFERENT object!
// In this example, loadByID is using the ObjWatcher and returns the SAME object (an object
// instance of class Employee with the ID of 12).
$b = Employee::loadByID(12);
$b->setName('Brian'); // Set the name for employee 12 again.
// As the objects are both the same object, the worst we will do by saving them is to do two
// identical saves to the database.
$b->save();
$a->save();
// Let's fetch our data from the database again.
$c = Employee::loadByID(12);
// The name is now the last one set for Employee 12, regardless of our objects.
echo $c->getName(); // echos Brian
?>
			
				So, what was the difference between the classes? As we have seen, the difference is in
				the Employee::loadByID() method. Below is a closer look at the code for both
				methods.
			
// Original class method without ObjWatcher...
public static loadByID($id) {
    $obj = new __CLASS__; // create Employee object
    $obj->loadDataFromDatabase($id); // load data from the database
    return $obj; // return the populated object
}
// Method using ObjWatcher
public static loadByID($id) {
    // The first thing we do is check with the ObjWatcher whether there is an object of type Employee
    // with the id we are looking for. If we find it, just return that object
    if ($obj = ObjWatcher::exists(__CLASS__, $id)) {return $obj;}
    $obj = new __CLASS__; // If we didn't find that object, we create a new one
    ObjWatcher::add($obj); // and then add it to the ObjWatcher
    $obj->loadDataFromDatabase($id); // load data from the database
    return $obj; // return the populated object
}