mirror of
https://github.com/atlanticbiomedical/portal-legacy.git
synced 2025-07-02 01:47:28 -04:00
587 lines
17 KiB
PHP
587 lines
17 KiB
PHP
![]() |
<?php
|
|||
|
|
|||
|
/*
|
|||
|
* $Id: Propel.php 601 2007-03-07 13:23:12Z hans $
|
|||
|
*
|
|||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|||
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|||
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|||
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||
|
*
|
|||
|
* This software consists of voluntary contributions made by many individuals
|
|||
|
* and is licensed under the LGPL. For more information please see
|
|||
|
* <http://propel.phpdb.org>.
|
|||
|
*/
|
|||
|
|
|||
|
include_once 'propel/PropelException.php';
|
|||
|
include_once 'propel/adapter/DBAdapter.php';
|
|||
|
|
|||
|
/**
|
|||
|
* Propel's main resource pool and initialization & configuration class.
|
|||
|
*
|
|||
|
* This static class is used to handle Propel initialization and to maintain all of the
|
|||
|
* open database connections and instantiated database maps.
|
|||
|
*
|
|||
|
* @author Hans Lellelid <hans@xmpl.rg> (Propel)
|
|||
|
* @author Daniel Rall <dlr@finemaltcoding.com> (Torque)
|
|||
|
* @author Magn<EFBFBD>s <EFBFBD><EFBFBD>r Torfason <magnus@handtolvur.is> (Torque)
|
|||
|
* @author Jason van Zyl <jvanzyl@apache.org> (Torque)
|
|||
|
* @author Rafal Krzewski <Rafal.Krzewski@e-point.pl> (Torque)
|
|||
|
* @author Martin Poeschl <mpoeschl@marmot.at> (Torque)
|
|||
|
* @author Henning P. Schmiedehausen <hps@intermeta.de> (Torque)
|
|||
|
* @author Kurt Schrader <kschrader@karmalab.org> (Torque)
|
|||
|
* @version $Revision: 601 $
|
|||
|
* @package propel
|
|||
|
*/
|
|||
|
class Propel {
|
|||
|
|
|||
|
/**
|
|||
|
* A constant for <code>default</code>.
|
|||
|
*/
|
|||
|
const DEFAULT_NAME = "default";
|
|||
|
|
|||
|
/**
|
|||
|
* A constant defining 'System is unusuable' logging level
|
|||
|
*/
|
|||
|
const LOG_EMERG = 0;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant defining 'Immediate action required' logging level
|
|||
|
*/
|
|||
|
const LOG_ALERT = 1;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant defining 'Critical conditions' logging level
|
|||
|
*/
|
|||
|
const LOG_CRIT = 2;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant defining 'Error conditions' logging level
|
|||
|
*/
|
|||
|
const LOG_ERR = 3;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant defining 'Warning conditions' logging level
|
|||
|
*/
|
|||
|
const LOG_WARNING = 4;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant defining 'Normal but significant' logging level
|
|||
|
*/
|
|||
|
const LOG_NOTICE = 5;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant defining 'Informational' logging level
|
|||
|
*/
|
|||
|
const LOG_INFO = 6;
|
|||
|
|
|||
|
/**
|
|||
|
* A constant defining 'Debug-level messages' logging level
|
|||
|
*/
|
|||
|
const LOG_DEBUG = 7;
|
|||
|
|
|||
|
/**
|
|||
|
* The Propel version.
|
|||
|
*/
|
|||
|
const VERSION = '1.2.1';
|
|||
|
|
|||
|
/**
|
|||
|
* The db name that is specified as the default in the property file
|
|||
|
*/
|
|||
|
private static $defaultDBName;
|
|||
|
|
|||
|
/**
|
|||
|
* The global cache of database maps
|
|||
|
*/
|
|||
|
private static $dbMaps = array();
|
|||
|
|
|||
|
/**
|
|||
|
* The cache of DB adapter keys
|
|||
|
*/
|
|||
|
private static $adapterMap;
|
|||
|
|
|||
|
/**
|
|||
|
* The logging category.
|
|||
|
*/
|
|||
|
private static $category;
|
|||
|
|
|||
|
/**
|
|||
|
* Propel-specific configuration.
|
|||
|
*/
|
|||
|
private static $configuration;
|
|||
|
|
|||
|
/**
|
|||
|
* flag to set to true once this class has been initialized
|
|||
|
*/
|
|||
|
private static $isInit = false;
|
|||
|
|
|||
|
/**
|
|||
|
* @var Log
|
|||
|
*/
|
|||
|
private static $logger = null;
|
|||
|
|
|||
|
/**
|
|||
|
* Store mapbuilder classnames for peers that have been referenced prior
|
|||
|
* to Propel being initialized. This can happen if the OM Peer classes are
|
|||
|
* included before the Propel::init() method has been called.
|
|||
|
*/
|
|||
|
private static $mapBuilders = array();
|
|||
|
|
|||
|
/**
|
|||
|
* Cache of established connections (to eliminate overhead).
|
|||
|
* @var array
|
|||
|
*/
|
|||
|
private static $connectionMap = array();
|
|||
|
|
|||
|
/**
|
|||
|
* initialize Propel
|
|||
|
* @return void
|
|||
|
* @throws PropelException Any exceptions caught during processing will be
|
|||
|
* rethrown wrapped into a PropelException.
|
|||
|
*/
|
|||
|
public static function initialize() {
|
|||
|
|
|||
|
if (self::$configuration === null) {
|
|||
|
throw new PropelException("Propel cannot be initialized without "
|
|||
|
. "a valid configuration. Please check the log files "
|
|||
|
. "for further details.");
|
|||
|
}
|
|||
|
|
|||
|
self::configureLogging();
|
|||
|
|
|||
|
// Now that we have dealt with processing the log properties
|
|||
|
// that may be contained in the configuration we will make the
|
|||
|
// configuration consist only of the remaining propel-specific
|
|||
|
// properties that are contained in the configuration. First
|
|||
|
// look for properties that are in the "propel" namespace.
|
|||
|
$originalConf = self::$configuration;
|
|||
|
self::$configuration = isset(self::$configuration['propel']) ? self::$configuration['propel'] : null;
|
|||
|
|
|||
|
if (empty(self::$configuration)) {
|
|||
|
// Assume the original configuration already had any
|
|||
|
// prefixes stripped.
|
|||
|
self::$configuration = $originalConf;
|
|||
|
}
|
|||
|
|
|||
|
// reset the connection map (this should enable runtime changes of connection params)
|
|||
|
self::$connectionMap = array();
|
|||
|
|
|||
|
self::initAdapters(self::$configuration);
|
|||
|
|
|||
|
self::$isInit = true;
|
|||
|
|
|||
|
// map builders may be registered w/ Propel before Propel has
|
|||
|
// been initialized; in this case they are stored in a static
|
|||
|
// var of this class & now can be propertly initialized.
|
|||
|
foreach(self::$mapBuilders as $mbClass) {
|
|||
|
BasePeer::getMapBuilder($mbClass);
|
|||
|
}
|
|||
|
|
|||
|
// now that the pre-loaded map builders have been propertly initialized
|
|||
|
// empty the array.
|
|||
|
// any further mapBuilders will be build by the generated MapBuilder classes.
|
|||
|
self::$mapBuilders = array();
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Setup the adapters needed. An adapter must be defined for each database connection.
|
|||
|
* Generally the adapter will be the same as the PEAR phpname; e.g. for MySQL, use the
|
|||
|
* 'mysql' adapter.
|
|||
|
* @param array $configuration the Configuration representing the properties file
|
|||
|
* @throws PropelException Any exceptions caught during processing will be
|
|||
|
* rethrown wrapped into a PropelException.
|
|||
|
*/
|
|||
|
private static function initAdapters($configuration) {
|
|||
|
|
|||
|
self::$adapterMap = array();
|
|||
|
|
|||
|
$c = isset($configuration['datasources']) ? $configuration['datasources'] : null;
|
|||
|
|
|||
|
if (!empty($c)) {
|
|||
|
try {
|
|||
|
foreach($c as $handle => $properties) {
|
|||
|
if (is_array($properties) && isset($properties['adapter'])) {
|
|||
|
$db = DBAdapter::factory($properties['adapter']);
|
|||
|
// register the adapter for this name
|
|||
|
self::$adapterMap[$handle] = $db;
|
|||
|
}
|
|||
|
}
|
|||
|
} catch (Exception $e) {
|
|||
|
throw new PropelException("Unable to initialize adapters.", $e);
|
|||
|
}
|
|||
|
} else {
|
|||
|
self::log("There were no adapters in the configuration.", self::LOG_WARNING);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* configure propel
|
|||
|
*
|
|||
|
* @param string $config Path (absolute or relative to include_path) to config file.
|
|||
|
* @return void
|
|||
|
* @throws PropelException If configuration file cannot be opened. (E_WARNING probably will also be raised in PHP)
|
|||
|
*/
|
|||
|
public static function configure($configFile)
|
|||
|
{
|
|||
|
self::$configuration = include($configFile);
|
|||
|
if (self::$configuration === false) {
|
|||
|
throw new PropelException("Unable to open configuration file: " . var_export($configFile, true));
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Initialization of Propel with a properties file.
|
|||
|
*
|
|||
|
* @param string $c The Propel configuration file path.
|
|||
|
* @return void
|
|||
|
* @throws PropelException Any exceptions caught during processing will be
|
|||
|
* rethrown wrapped into a PropelException.
|
|||
|
*/
|
|||
|
public static function init($c)
|
|||
|
{
|
|||
|
self::configure($c);
|
|||
|
self::initialize();
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Determine whether Propel has already been initialized.
|
|||
|
*
|
|||
|
* @return boolean True if Propel is already initialized.
|
|||
|
*/
|
|||
|
public static function isInit()
|
|||
|
{
|
|||
|
return self::$isInit;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Sets the configuration for Propel and all dependencies.
|
|||
|
*
|
|||
|
* @param array $c the Configuration
|
|||
|
* @return void
|
|||
|
*/
|
|||
|
public static function setConfiguration($c)
|
|||
|
{
|
|||
|
self::$configuration = $c;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Get the configuration for this component.
|
|||
|
*
|
|||
|
* @return the Configuration
|
|||
|
*/
|
|||
|
public static function getConfiguration()
|
|||
|
{
|
|||
|
return self::$configuration;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Configure the logging for this subsystem.
|
|||
|
* The logging system is only configured if there is a 'log'
|
|||
|
* section in the passed-in runtime configuration.
|
|||
|
* @return void
|
|||
|
*/
|
|||
|
protected static function configureLogging() {
|
|||
|
if (self::$logger === null) {
|
|||
|
if (isset(self::$configuration['log']) && is_array(self::$configuration['log']) && count(self::$configuration['log'])) {
|
|||
|
include_once 'Log.php'; // PEAR Log class
|
|||
|
$c = self::$configuration['log'];
|
|||
|
// array casting handles bug in PHP5b2 where the isset() checks
|
|||
|
// below may return true if $c is not an array (e.g. is a string)
|
|||
|
|
|||
|
$type = isset($c['type']) ? $c['type'] : 'file';
|
|||
|
$name = isset($c['name']) ? $c['name'] : './propel.log';
|
|||
|
$ident = isset($c['ident']) ? $c['ident'] : 'propel';
|
|||
|
$conf = isset($c['conf']) ? $c['conf'] : array();
|
|||
|
$level = isset($c['level']) ? $c['level'] : PEAR_LOG_DEBUG;
|
|||
|
|
|||
|
self::$logger = Log::singleton($type, $name, $ident, $conf, $level);
|
|||
|
} // if isset()
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Override the configured logger.
|
|||
|
*
|
|||
|
* This is primarily for things like unit tests / debugging where
|
|||
|
* you want to change the logger without altering the configuration file.
|
|||
|
*
|
|||
|
* You can use any logger class that implements the propel.logger.BasicLogger
|
|||
|
* interface. This interface is based on PEAR::Log, so you can also simply pass
|
|||
|
* a PEAR::Log object to this method.
|
|||
|
*
|
|||
|
* @param object $logger The new logger to use. ([PEAR] Log or BasicLogger)
|
|||
|
* @return void
|
|||
|
*/
|
|||
|
public static function setLogger($logger)
|
|||
|
{
|
|||
|
self::$logger = $logger;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Returns true if a logger, for example PEAR::Log, has been configured,
|
|||
|
* otherwise false.
|
|||
|
*
|
|||
|
* @return boolean True if Propel uses logging
|
|||
|
*/
|
|||
|
public static function hasLogger()
|
|||
|
{
|
|||
|
return self::$logger !== null;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Get the configured logger.
|
|||
|
* @return object Configured log class ([PEAR] Log or BasicLogger).
|
|||
|
*/
|
|||
|
public static function logger()
|
|||
|
{
|
|||
|
return self::$logger;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Logs a message
|
|||
|
* If a logger has been configured, the logger will be used, otherwrise the
|
|||
|
* logging message will be discarded without any further action
|
|||
|
*
|
|||
|
* @param string $message The message that will be logged.
|
|||
|
* @param string $level The logging level.
|
|||
|
* @return boolean True if the message was logged successfully or no logger was used.
|
|||
|
*/
|
|||
|
public static function log($message, $level = self::LOG_DEBUG)
|
|||
|
{
|
|||
|
if(self::hasLogger())
|
|||
|
{
|
|||
|
$logger = self::logger();
|
|||
|
switch($level)
|
|||
|
{
|
|||
|
case self::LOG_EMERG:
|
|||
|
return $logger->log($message, $level);
|
|||
|
case self::LOG_ALERT:
|
|||
|
return $logger->alert($message);
|
|||
|
case self::LOG_CRIT:
|
|||
|
return $logger->crit($message);
|
|||
|
case self::LOG_ERR:
|
|||
|
return $logger->err($message);
|
|||
|
case self::LOG_WARNING:
|
|||
|
return $logger->warning($message);
|
|||
|
case self::LOG_NOTICE:
|
|||
|
return $logger->notice($message);
|
|||
|
case self::LOG_INFO:
|
|||
|
return $logger->info($message);
|
|||
|
default:
|
|||
|
return $logger->debug($message);
|
|||
|
}
|
|||
|
}
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Returns the database map information. Name relates to the name
|
|||
|
* of the connection pool to associate with the map.
|
|||
|
*
|
|||
|
* The database maps are "registered" by the generated map builder classes.
|
|||
|
*
|
|||
|
* @param string $name The name of the database corresponding to the DatabaseMapto retrieve.
|
|||
|
* @return DatabaseMap The named <code>DatabaseMap</code>.
|
|||
|
* @throws PropelException - if database map is null or propel was not initialized properly.
|
|||
|
*/
|
|||
|
public static function getDatabaseMap($name = null) {
|
|||
|
|
|||
|
if ($name === null) {
|
|||
|
$name = self::getDefaultDB();
|
|||
|
if ($name === null) {
|
|||
|
throw new PropelException("DatabaseMap name was null!");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// CACHEHOOK - this would be a good place
|
|||
|
// to add shared memory caching options (database
|
|||
|
// maps should be a pretty safe candidate for shared mem caching)
|
|||
|
|
|||
|
if (isset(self::$dbMaps[$name])) {
|
|||
|
$map = self::$dbMaps[$name];
|
|||
|
} else {
|
|||
|
$map = self::initDatabaseMap($name);
|
|||
|
}
|
|||
|
|
|||
|
return $map;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Creates and initializes the mape for the named database.
|
|||
|
*
|
|||
|
* The database maps are "registered" by the generated map builder classes
|
|||
|
* by calling this method and then adding the tables, etc. to teh DatabaseMap
|
|||
|
* object returned from this method.
|
|||
|
*
|
|||
|
* @param string $name The name of the database to map.
|
|||
|
* @return DatabaseMap The desired map.
|
|||
|
* @throws PropelException Any exceptions caught during processing will be
|
|||
|
* rethrown wrapped into a PropelException.
|
|||
|
*/
|
|||
|
private static function initDatabaseMap($name)
|
|||
|
{
|
|||
|
$map = new DatabaseMap($name);
|
|||
|
self::$dbMaps[$name] = $map;
|
|||
|
return $map;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Register a MapBuilder
|
|||
|
*
|
|||
|
* @param string $className the MapBuilder
|
|||
|
*/
|
|||
|
public static function registerMapBuilder($className)
|
|||
|
{
|
|||
|
self::$mapBuilders[] = $className;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Returns the specified property of the given database, or the empty
|
|||
|
* string if no value is set for the property.
|
|||
|
*
|
|||
|
* @param string $db The name of the database whose property to get.
|
|||
|
* @param string $prop The name of the property to get.
|
|||
|
* @return mixed The property's value.
|
|||
|
*/
|
|||
|
private static function getDatabaseProperty($db, $prop)
|
|||
|
{
|
|||
|
return isset(self::$configuration['datasources'][$db][$prop]) ? self::$configuration['datasources'][$db][$prop] : null;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
*
|
|||
|
* @param string $name The database name.
|
|||
|
* @return Connection A database connection
|
|||
|
* @throws PropelException - if no conneciton params, or SQLException caught when trying to connect.
|
|||
|
*/
|
|||
|
public static function getConnection($name = null) {
|
|||
|
|
|||
|
if ($name === null) {
|
|||
|
$name = self::getDefaultDB();
|
|||
|
}
|
|||
|
|
|||
|
$con = isset(self::$connectionMap[$name]) ? self::$connectionMap[$name] : null;
|
|||
|
|
|||
|
if ($con === null) {
|
|||
|
|
|||
|
$dsn = isset(self::$configuration['datasources'][$name]['connection']) ? self::$configuration['datasources'][$name]['connection'] : null;
|
|||
|
if ($dsn === null) {
|
|||
|
throw new PropelException("No connection params set for " . $name);
|
|||
|
}
|
|||
|
|
|||
|
include_once 'creole/Creole.php';
|
|||
|
|
|||
|
// if specified, use custom driver
|
|||
|
if (isset(self::$configuration['datasources'][$name]['driver'])) {
|
|||
|
Creole::registerDriver($dsn['phptype'], self::$configuration['datasources'][$name]['driver']);
|
|||
|
}
|
|||
|
|
|||
|
try {
|
|||
|
$con = Creole::getConnection($dsn);
|
|||
|
} catch (SQLException $e) {
|
|||
|
throw new PropelException($e);
|
|||
|
}
|
|||
|
self::$connectionMap[$name] = $con;
|
|||
|
}
|
|||
|
|
|||
|
return $con;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Returns database adapter for a specific connection pool.
|
|||
|
*
|
|||
|
* @param string $name A database name.
|
|||
|
* @return DBAdapter The corresponding database adapter.
|
|||
|
* @throws PropelException - if unable to find DBdapter for specified db.
|
|||
|
*/
|
|||
|
public static function getDB($name = null)
|
|||
|
{
|
|||
|
if ($name === null) {
|
|||
|
$name = self::getDefaultDB();
|
|||
|
}
|
|||
|
if (!isset(self::$adapterMap[$name])) {
|
|||
|
throw new PropelException("Unable to load DBAdapter for database '" . var_export($name, true) . "' (check your runtime properties file!)");
|
|||
|
}
|
|||
|
return self::$adapterMap[$name];
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Returns the name of the default database.
|
|||
|
*
|
|||
|
* @return string Name of the default DB
|
|||
|
*/
|
|||
|
public static function getDefaultDB()
|
|||
|
{
|
|||
|
if (self::$configuration === null) {
|
|||
|
return self::DEFAULT_NAME;
|
|||
|
} elseif (self::$defaultDBName === null) {
|
|||
|
// Determine default database name.
|
|||
|
self::$defaultDBName = isset(self::$configuration['datasources']['default']) ? self::$configuration['datasources']['default'] : self::DEFAULT_NAME;
|
|||
|
}
|
|||
|
return self::$defaultDBName;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Include once a file specified in DOT notation and reutrn unqualified clasname.
|
|||
|
*
|
|||
|
* Package notation is expected to be relative to a location
|
|||
|
* on the PHP include_path. The dot-path classes are used as a way
|
|||
|
* to represent both classname and filesystem location; there is
|
|||
|
* an inherent assumption about filenaming. To get around these
|
|||
|
* naming requirements you can include the class yourself
|
|||
|
* and then just use the classname instead of dot-path.
|
|||
|
*
|
|||
|
* @param string $class dot-path to clas (e.g. path.to.my.ClassName).
|
|||
|
* @return string unqualified classname
|
|||
|
*/
|
|||
|
public static function import($path) {
|
|||
|
|
|||
|
// extract classname
|
|||
|
if (($pos = strrpos($path, '.')) === false) {
|
|||
|
$class = $path;
|
|||
|
} else {
|
|||
|
$class = substr($path, $pos + 1);
|
|||
|
}
|
|||
|
|
|||
|
// check if class exists
|
|||
|
if (class_exists($class, false)) {
|
|||
|
return $class;
|
|||
|
}
|
|||
|
|
|||
|
// turn to filesystem path
|
|||
|
$path = strtr($path, '.', DIRECTORY_SEPARATOR) . '.php';
|
|||
|
|
|||
|
// include class
|
|||
|
$ret = include_once($path);
|
|||
|
if ($ret === false) {
|
|||
|
throw new PropelException("Unable to import class: " . $class . " from " . $path);
|
|||
|
}
|
|||
|
|
|||
|
// return qualified name
|
|||
|
return $class;
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
* Closes any associated resource handles.
|
|||
|
*
|
|||
|
* This method frees any database connection handles that have been
|
|||
|
* opened by the getConnection() method.
|
|||
|
*
|
|||
|
* @return void
|
|||
|
*/
|
|||
|
public static function close()
|
|||
|
{
|
|||
|
foreach(self::$connectionMap as $conn) {
|
|||
|
$conn->close();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|