Version: current

      1 <?php
      2 /**
      3  * Global database interface, complete with static methods.
      4  * Use this class for interacting with the database.
      5  * @package sapphire
      6  * @subpackage model
      7  */
      8 class DB {
      9     /**
     10      * This constant was added in SilverStripe 2.4 to indicate that SQL-queries
     11      * should now use ANSI-compatible syntax.  The most notable affect of this
     12      * change is that table and field names should be escaped with double quotes
     13      * and not backticks
     14      */
     15     const USE_ANSI_SQL = true;
     16
     17
     18     /**
     19      * The global database connection.
     20      * @var SS_Database
     21      */
     22     private static $connections = array();
     23
     24     /**
     25      * The last SQL query run.
     26      * @var string
     27      */
     28     public static $lastQuery;
     29
     30     /**
     31      * Internal flag to keep track of when db connection was attempted.
     32      */
     33     private static $connection_attempted = false;
     34
     35     /**
     36      * Set the global database connection.
     37      * Pass an object that's a subclass of SS_Database.  This object will be used when {@link DB::query()}
     38      * is called.
     39      * @param $connection The connecton object to set as the connection.
     40      * @param $name The name to give to this connection.  If you omit this argument, the connection
     41      * will be the default one used by the ORM.  However, you can store other named connections to
     42      * be accessed through DB::getConn($name).  This is useful when you have an application that
     43      * needs to connect to more than one database.
     44      */
     45     static function setConn(SS_Database $connection, $name = 'default') {
     46         self::$connections[$name] = $connection;
     47     }
     48
     49     /**
     50      * Get the global database connection.
     51      * @param $name An optional name given to a connection in the DB::setConn() call.  If omitted,
     52      * the default connection is returned.
     53      * @return SS_Database
     54      */
     55     static function getConn($name = 'default') {
     56         if(isset(self::$connections[$name])) {
     57             return self::$connections[$name];
     58         }
     59     }
     60
     61     /**
     62      * Set an alternative database to use for this browser session.
     63      * This is useful when using testing systems other than SapphireTest; for example, Windmill.
     64      * Set it to null to revert to the main database.
     65      */
     66     static function set_alternative_database_name($dbname) {
     67         $_SESSION["alternativeDatabaseName"] = $dbname;
     68     }
     69
     70     /**
     71      * Get the name of the database in use
     72      */
     73     static function get_alternative_database_name() {
     74         return $_SESSION["alternativeDatabaseName"];
     75     }
     76
     77     /**
     78      * Connect to a database.
     79      * Given the database configuration, this method will create the correct subclass of SS_Database,
     80      * and set it as the global connection.
     81      * @param array $database A map of options. The 'type' is the name of the subclass of SS_Database to use. For the rest of the options, see the specific class.
     82      */
     83     static function connect($databaseConfig) {
     84         // This is used by TestRunner::startsession() to test up a test session using an alt
     85         if(isset($_SESSION["alternativeDatabaseName"]) && $dbname = $_SESSION["alternativeDatabaseName"]) $databaseConfig['database'] = $dbname;
     86
     87         if(!isset($databaseConfig['type']) || empty($databaseConfig['type'])) {
     88             user_error("DB::connect: Not passed a valid database config", E_USER_ERROR);
     89         }
     90
     91         self::$connection_attempted = true;
     92
     93         $dbClass = $databaseConfig['type'];
     94         $conn = new $dbClass($databaseConfig);
     95
     96         self::setConn($conn);
     97     }
     98
     99     /**
    100      * Returns true if a database connection has been attempted.
    101      * In particular, it lets the caller know if we're still so early in the execution pipeline that
    102      * we haven't even tried to connect to the database yet.
    103      */
    104     public static function connection_attempted() {
    105         return self::$connection_attempted;
    106     }
    107
    108     /**
    109      * Build the connection string from input.
    110      * @param array $parameters The connection details.
    111      * @return string $connect The connection string.
    112      **/
    113     public static function getConnect($parameters) {
    114         return self::getConn()->getConnect($parameters);
    115     }
    116
    117     /**
    118      * Execute the given SQL query.
    119      * @param string $sql The SQL query to execute
    120      * @param int $errorLevel The level of error reporting to enable for the query
    121      * @return SS_Query
    122      */
    123     static function query($sql, $errorLevel = E_USER_ERROR) {
    124         self::$lastQuery = $sql;
    125
    126         return self::getConn()->query($sql, $errorLevel);
    127     }
    128
    129     /**
    130      * Execute a complex manipulation on the database.
    131      * A manipulation is an array of insert / or update sequences.  The keys of the array are table names,
    132      * and the values are map containing 'command' and 'fields'.  Command should be 'insert' or 'update',
    133      * and fields should be a map of field names to field values, including quotes.  The field value can
    134      * also be a SQL function or similar.
    135      * @param array $manipulation
    136      */
    137     static function manipulate($manipulation) {
    138         self::$lastQuery = $manipulation;
    139         return self::getConn()->manipulate($manipulation);
    140     }
    141
    142     /**
    143      * Get the autogenerated ID from the previous INSERT query.
    144      * @return int
    145      */
    146     static function getGeneratedID($table) {
    147         return self::getConn()->getGeneratedID($table);
    148     }
    149
    150     /**
    151      * Check if the connection to the database is active.
    152      * @return boolean
    153      */
    154     static function isActive() {
    155         if($conn = self::getConn()) return $conn->isActive();
    156         else return false;
    157     }
    158
    159     /**
    160      * Create the database and connect to it. This can be called if the
    161      * initial database connection is not successful because the database
    162      * does not exist.
    163      * @param string $connect Connection string
    164      * @param string $username SS_Database username
    165      * @param string $password SS_Database Password
    166      * @param string $database SS_Database to which to create
    167      * @return boolean Returns true if successful
    168      */
    169     static function createDatabase($connect, $username, $password, $database) {
    170         return self::getConn()->createDatabase($connect, $username, $password, $database);
    171     }
    172
    173     /**
    174      * Create a new table.
    175      * @param $tableName The name of the table
    176      * @param $fields A map of field names to field types
    177      * @param $indexes A map of indexes
    178      * @param $options An map of additional options.  The available keys are as follows:
    179      *   - 'MSSQLDatabase'/'MySQLDatabase'/'PostgreSQLDatabase' - database-specific options such as "engine" for MySQL.
    180      *   - 'temporary' - If true, then a temporary table will be created
    181      * @return The table name generated.  This may be different from the table name, for example with temporary tables.
    182      */
    183     static function createTable($table, $fields = null, $indexes = null, $options = null) {
    184         return self::getConn()->createTable($table, $fields, $indexes, $options);
    185     }
    186
    187     /**
    188      * Create a new field on a table.
    189      * @param string $table Name of the table.
    190      * @param string $field Name of the field to add.
    191      * @param string $spec The field specification, eg 'INTEGER NOT NULL'
    192      */
    193     static function createField($table, $field, $spec) {
    194         return self::getConn()->createField($table, $field, $spec);
    195     }
    196
    197     /**
    198      * Generate the following table in the database, modifying whatever already exists
    199      * as necessary.
    200      * @param string $table The name of the table
    201      * @param string $fieldSchema A list of the fields to create, in the same form as DataObject::$db
    202      * @param string $indexSchema A list of indexes to create.  The keys of the array are the names of the index.
    203      * @param boolean $hasAutoIncPK A flag indicating that the primary key on this table is an autoincrement type
    204      * The values of the array can be one of:
    205      *   - true: Create a single column index on the field named the same as the index.
    206      *   - array('fields' => array('A','B','C'), 'type' => 'index/unique/fulltext'): This gives you full
    207      *     control over the index.
    208      * @param string $options SQL statement to append to the CREATE TABLE call.
    209      */
    210     static function requireTable($table, $fieldSchema = null, $indexSchema = null, $hasAutoIncPK=true, $options = null, $extensions=null) {
    211         return self::getConn()->requireTable($table, $fieldSchema, $indexSchema, $hasAutoIncPK, $options, $extensions);
    212     }
    213
    214     /**
    215      * Generate the given field on the table, modifying whatever already exists as necessary.
    216      * @param string $table The table name.
    217      * @param string $field The field name.
    218      * @param string $spec The field specification.
    219      */
    220     static function requireField($table, $field, $spec) {
    221         return self::getConn()->requireField($table, $field, $spec);
    222     }
    223
    224     /**
    225      * Generate the given index in the database, modifying whatever already exists as necessary.
    226      * @param string $table The table name.
    227      * @param string $index The index name.
    228      * @param string|boolean $spec The specification of the index. See requireTable() for more information.
    229      */
    230     static function requireIndex($table, $index, $spec) {
    231         return self::getConn()->requireIndex($table, $index, $spec);
    232     }
    233
    234     /**
    235      * If the given table exists, move it out of the way by renaming it to _obsolete_(tablename).
    236      * @param string $table The table name.
    237      */
    238     static function dontRequireTable($table) {
    239         return self::getConn()->dontRequireTable($table);
    240     }
    241
    242     /**
    243      * See {@link SS_Database->dontRequireField()}.
    244      *
    245      * @param string $table The table name.
    246      * @param string $fieldName
    247      */
    248     static function dontRequireField($table, $fieldName) {
    249         return self::getConn()->dontRequireField($table, $fieldName);
    250     }
    251
    252     /**
    253      * Checks a table's integrity and repairs it if necessary.
    254      * @var string $tableName The name of the table.
    255      * @return boolean Return true if the table has integrity after the method is complete.
    256      */
    257     static function checkAndRepairTable($table) {
    258         return self::getConn()->checkAndRepairTable($table);
    259     }
    260
    261     /**
    262      * Return the number of rows affected by the previous operation.
    263      * @return int
    264      */
    265     static function affectedRows() {
    266         return self::getConn()->affectedRows();
    267     }
    268
    269     /**
    270      * Returns a list of all tables in the database.
    271      * The table names will be in lower case.
    272      * @return array
    273      */
    274     static function tableList() {
    275         return self::getConn()->tableList();
    276     }
    277
    278     /**
    279      * Get a list of all the fields for the given table.
    280      * Returns a map of field name => field spec.
    281      * @param string $table The table name.
    282      * @return array
    283      */
    284     static function fieldList($table) {
    285         return self::getConn()->fieldList($table);
    286     }
    287
    288     /**
    289      * Enable supression of database messages.
    290      */
    291     static function quiet() {
    292         return self::getConn()->quiet();
    293     }
    294
    295     /**
    296      * Show a message about database alteration.
    297      */
    298     static function alteration_message($message,$type="") {
    299         return self::getConn()->alterationMessage($message, $type);
    300     }
    301
    302 }
    303 ?>

[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -