BMLT Root Server
c_comdef_dbsingleton.class.php
Go to the documentation of this file.
1 <?php
2 
3 defined('BMLT_EXEC') or die('Cannot Execute Directly'); // Makes sure that this file is in the correct context.
4 
5 /**
6  \file c_comdef_dbsingleton.class.php
7 
8  \version 1.0
9 
10  \brief Wrapper class for a MySQL PDO object
11 
12  Singleton class accessed via static methods
13 
14  Based on code written by C. Drozdowski
15 
16  Call to c_comdef_dbsingleton::init() to populate connection params must be made BEFORE
17  any attempts to connect to or query a database.
18 
19  c_comdef_dbsingleton::connect() may be called to explicitly connect to database (though
20  not required- see next statement).
21 
22  Both c_comdef_dbsingleton::preparedQuery() and c_comdef_dbsingleton::preparedExec() allow
23  "lazy loading" of the connection. That is, they'll try to connect if there isn't
24  already a connection made via c_comdef_dbsingleton:connect() method.
25 
26  Typical usage:
27 
28  \code
29  c_comdef_dbsingleton::init('host', 'database', 'user', 'password');
30  c_comdef_dbsingleton::connect();
31  $array = c_comdef_dbsingleton::preparedQuery('SELECT * FROM foo WHERE bar = :bar', array(':bar' => 'baz'));
32  \endcode
33 
34  Lazy loading usage:
35 
36  \code
37  c_comdef_dbsingleton::init('host', 'database', 'user', 'password');
38  $array = c_comdef_dbsingleton::preparedQuery('SELECT * FROM foo WHERE bar = :bar', array(':bar' => 'baz'));
39  \endcode
40 
41  Adding connection charset:
42 
43  \code
44  c_comdef_dbsingleton::init('host', 'database', 'user', 'password', 'latin1');
45  \endcode
46 
47  Internal instance of PDO is available via c_comdef_dbsingleton::pdoInstance() method.
48 
49  See PDO documentation for more info about connections and prepared statements
50 
51  This file is part of the Basic Meeting List Toolbox (BMLT).
52 
53  Find out more at: https://bmlt.app
54 
55  BMLT is free software: you can redistribute it and/or modify
56  it under the terms of the MIT License.
57 
58  BMLT is distributed in the hope that it will be useful,
59  but WITHOUT ANY WARRANTY; without even the implied warranty of
60  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
61  MIT License for more details.
62 
63  You should have received a copy of the MIT License along with this code.
64  If not, see <https://opensource.org/licenses/MIT>.
65  */
66 /// \brief This class provides a genericized interface to the <a href="http://us.php.net/pdo">PHP PDO</a> toolkit. It is a completely static class.
67 // phpcs:disable PSR1.Classes.ClassDeclaration.MissingNamespace
68 // phpcs:disable Squiz.Classes.ValidClassName.NotCamelCaps
70 // phpcs:enable PSR1.Classes.ClassDeclaration.MissingNamespace
71 // phpcs:enable Squiz.Classes.ValidClassName.NotCamelCaps
72 {
73  /// \brief Internal PDO object
74  private static $pdo = null;
75 
76  /// \brief Connection database driver type param
77  private static $driver = null;
78 
79  /// \brief Connection host param
80  private static $host = null;
81 
82  /// \brief Connection database param
83  private static $database = null;
84 
85  /// \brief Connection user param
86  private static $user = null;
87 
88  /// \brief Connection password param
89  private static $password = null;
90 
91  /// \brief Connection charset param
92  private static $charset = null;
93 
94  /// \brief Default fetch mode for internal PDOStatements
95  private static $fetchMode = PDO::FETCH_ASSOC;
96 
97  /**
98  \brief Private constructor (prevents direct creation of object)
99  */
100  private function __construct()
101  {
102  }
103 
104  /**
105  \brief Initializes connection param class members.
106 
107  Must be called BEFORE any attempts to connect to or query a database.
108 
109  Will destroy previous connection (if one exists).
110  */
111  public static function init(
112  $driver, ///< database server type (ex: 'mysql')
113  $host, ///< database server host
114  $database, ///< database name
115  $user = null, ///< user, optional
116  $password = null, ///< password, optional
117  $charset = null ///< connection charset, optional
118  ) {
119  if (self::$pdo instanceof pdo) {
120  self::$pdo = null;
121  }
122 
123  self::$driver = (string) $driver;
124  self::$host = (string) $host;
125  self::$database = (string) $database;
126 
127  if (!is_null($user)) {
128  self::$user = (string) $user;
129  }
130 
131  if (!is_null($password)) {
132  self::$password = (string) $password;
133  }
134 
135  if (!is_null($charset)) {
136  self::$charset = $charset;
137  }
138  }
139 
140 
141  /**
142  \brief Create internal PDO object thus connecting to database using connection
143  param class members (passed in from previous call to c_comdef_dbsingleton::init())
144 
145  Will destroy previous connection (if one exists) before reconnecting
146 
147  \throws Exception thrown if internal PDO object cannot be created
148  e.g. wrong connection param(s)
149  */
150  public static function connect()
151  {
152  if (self::$pdo instanceof pdo) {
153  self::$pdo = null;
154  }
155 
156  try {
157  $dsn = self::$driver . ':host=' . self::$host . ';dbname=' . self::$database;
158  self::$pdo = new PDO($dsn, self::$user, self::$password, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES 'utf8'"));
159  self::$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
160  self::$pdo->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
161  self::$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
162  if (strlen(self::$charset) > 0) {
163  self::preparedExec('SET NAMES :charset', array(':charset' => self::$charset));
164  }
165 
166  /// For security purposes, once we connect, we get rid of all the info, and a new init needs to be called.
167 
168  self::$driver = null;
169  self::$host = null;
170  self::$database = null;
171  self::$user = null;
172  self::$password = null;
173  self::$charset = null;
174  } catch (PDOException $exception) {
175  throw new Exception(__METHOD__ . '() ' . $exception->getMessage());
176  }
177  }
178 
179  /**
180  \brief Returns whether internal PDO object is instantiated and thus connected
181 
182  \returns true if connected.
183  */
184  public static function isConnected()
185  {
186  if (self::$pdo instanceof PDO) {
187  return true;
188  } else {
189  return false;
190  }
191  }
192 
193  /**
194  \brief Provides access to internal PDO object in case this classes functionality is not enough
195 
196  \returns the PDO object
197 
198  \throws Exception thrown if internal PDO object not instantiated
199  */
200  public static function pdoInstance(
201  $do_connect = false ///< Set this to true to force a connection if one does not yet exist. Default is false.
202  ) {
203  if (!self::isConnected() && $do_connect) {
204  self::connect();
205  }
206 
207  if (self::$pdo instanceof PDO) {
208  return self::$pdo;
209  } else {
210  throw new Exception(__METHOD__ . '() internal PDO object not instantiated');
211  }
212  }
213 
214  /**
215  \brief Wrapper for preparing and executing a PDOStatement that returns a resultset
216  e.g. SELECT SQL statements.
217 
218  Returns a multidimensional array depending on internal fetch mode setting (self::$fetchMode)
219  See PDO documentation about prepared queries.
220 
221  If there isn't already a database connection, it will "lazy load" the connection.
222 
223  Fetching key pairs- when $fetchKeyPair is set to TRUE, it will force the returned
224  array to be a one-dimensional array indexed on the first column in the query.
225  Note- query may contain only two columns or an exception/error is thrown.
226  See PDO::PDO::FETCH_KEY_PAIR for more details
227 
228  \returns associative array of results.
229  \throws Exception thrown if internal PDO exception is thrown
230  */
231  public static function preparedQuery(
232  $sql, ///< same as kind provided to PDO::prepare()
233  $params = array(), ///< same as kind provided to PDO::prepare()
234  $fetchKeyPair = false ///< See description in method documentation
235  ) {
236 
237  if (!self::$pdo instanceof PDO) {
238  self::connect();
239  }
240 
241  try {
242  $stmt = self::$pdo->prepare($sql);
243  $stmt->setFetchMode(self::$fetchMode);
244  $stmt->execute($params);
245 
246  if ($fetchKeyPair) {
247  return $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
248  } else {
249  return $stmt->fetchAll();
250  }
251  } catch (PDOException $exception) {
252  throw new Exception(__METHOD__ . '() ' . $exception->getMessage());
253  }
254  }
255 
256  /**
257  \brief Wrapper for preparing and executing a PDOStatement that does not return a resultset
258  e.g. INSERT or UPDATE SQL statements
259 
260  See PDO documentation about prepared queries.
261 
262  If there isn't already a database connection, it will "lazy load" the connection.
263 
264  \throws Exception thrown if internal PDO exception is thrown
265  \returns true if execution is successful.
266  */
267  public static function preparedExec(
268  $sql, ///< same as kind provided to PDO::prepare()
269  $params = array() ///< same as kind provided to PDO::prepare()
270  ) {
271  if (!self::$pdo instanceof PDO) {
272  self::connect();
273  }
274 
275  try {
276  $stmt = self::$pdo->prepare($sql);
277 
278  return $stmt->execute($params);
279  } catch (PDOException $exception) {
280  throw new Exception(__METHOD__ . '() ' . $exception->getMessage());
281  }
282  }
283 
284  /**
285  \brief Wrapper for PDO::lastInsertId()
286 
287  \returns the ID of the last INSERT
288  \throws Exception thrown if internal PDO object not instantiated
289  */
290  public static function lastInsertId()
291  {
292  if (!self::$pdo instanceof PDO) {
293  throw new Exception(__METHOD__ . '() internal PDO object not instantiated');
294  }
295 
296  return self::$pdo->lastInsertId();
297  }
298 
299  public static function beginTransaction()
300  {
301  if (!self::$pdo instanceof PDO) {
302  self::connect();
303  }
304 
305  return self::$pdo->beginTransaction();
306  }
307 
308  public static function rollBack()
309  {
310  return self::$pdo->rollBack();
311  }
312 
313  public static function commit()
314  {
315  return self::$pdo->commit();
316  }
317 }
__construct()
Private constructor (prevents direct creation of object)
static preparedExec($sql, $params=array())
Wrapper for preparing and executing a PDOStatement that does not return a resultset e...
static lastInsertId()
Wrapper for PDO::lastInsertId()
static preparedQuery($sql, $params=array(), $fetchKeyPair=false)
Wrapper for preparing and executing a PDOStatement that returns a resultset e.g. SELECT SQL statement...
static pdoInstance($do_connect=false)
Provides access to internal PDO object in case this classes functionality is not enough.
This class provides a genericized interface to the PHP PDO toolkit. It is a completely static class...
static init($driver, $host, $database, $user=null, $password=null, $charset=null)
Initializes connection param class members.
defined('BMLT_EXEC') or define('BMLT_EXEC'
Definition: index.php:3
static isConnected()
Returns whether internal PDO object is instantiated and thus connected.
static connect()
Create internal PDO object thus connecting to database using connection param class members (passed i...