1  <?php
  2  /* Copyright (c) 2012, Geert Bergman (geert@scrivo.nl)
  3   * All rights reserved.
  4   *
  5   * Redistribution and use in source and binary forms, with or without
  6   * modification, are permitted provided that the following conditions are met:
  7   *
  8   * 1. Redistributions of source code must retain the above copyright notice,
  9   *    this list of conditions and the following disclaimer.
 10   * 2. Redistributions in binary form must reproduce the above copyright notice,
 11   *    this list of conditions and the following disclaimer in the documentation
 12   *    and/or other materials provided with the distribution.
 13   * 3. Neither the name of "Scrivo" nor the names of its contributors may be
 14   *    used to endorse or promote products derived from this software without
 15   *    specific prior written permission.
 16   *
 17   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 18   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 19   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 20   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 21   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 22   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 23   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 24   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 25   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 26   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 27   * POSSIBILITY OF SUCH DAMAGE.
 28   *
 29   * $Id: PdoConnection.php 866 2013-08-25 16:22:35Z geert $
 30   */
 31  
 32  /**
 33   * Implementation of the \Scrivo\PdoConnection class.
 34   */
 35  
 36  namespace Scrivo;
 37  
 38  /**
 39   * Class to manage the connection to the Scrivo database.
 40   *
 41   * This is simply a direct descendent of the \PDO class with a modified
 42   * constructor that uses a Scrivo configuration object to open the connection.
 43   * It also assures that the connection is configured correctly (uses exceptions
 44   * and UTF-8).
 45   *
 46   * It is possible to store data of several instances (sites) in a single
 47   * database. The instance data is identified by an instance id which is also
 48   * defined in the configuration file and present a property of this class.
 49   *
 50   * Furthermore, Scrivo uses object ids instead of auto-numbering. Ids within
 51   * a specific instance need to be unique. To achieve this this class also
 52   * deals with the generation of unique ids.
 53   *
 54   *
 55   */
 56  class PdoConnection extends \PDO {
 57  
 58      /**
 59       * The database instance id.
 60       * @var int
 61       */
 62      private $instId;
 63  
 64      /**
 65       * Construct a scrivo database connection using the setting in a Scrivo
 66       * config file. The following settings are used:
 67       *
 68       * * DB_HOST
 69       * * DB_NAME
 70       * * DB_USER
 71       * * DB_PASSWORD
 72       * * INSTANCE_ID
 73       *
 74       * @param Config $config A Scrivo config object that contains the database
 75       *   settings.
 76       */
 77      public function __construct(Config $config) {
 78  
 79          parent::__construct(
 80              "mysql:host={$config->DB_HOST};dbname={$config->DB_NAME}",
 81              $config->DB_USER$config->DB_PASSWORD,
 82              array(\PDO::ATTR_PERSISTENT => true));
 83          $this->setAttribute(
 84              \PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
 85          $this->exec("SET NAMES utf8");
 86  
 87          $this->instId $config->INSTANCE_ID;
 88  
 89      }
 90  
 91      /**
 92       * Get the database instance id.
 93       *
 94       * @return int The database instance id.
 95       */
 96      public function getInstanceId() {
 97          return $this->instId;
 98      }
 99  
100      /**
101       * Generate a new object id.
102       *
103       * For the generation of an object id in MySQL we use a table with one
104       * autoincrement column.
105       *
106       * TODO: setup a test to see how this holds in concurrency situations
107       *  and document it (the behavoir not the test).
108       *
109       * @return int A new object id.
110       */
111      public function generateId() {
112  
113          $this->exec("LOCK TABLES seq WRITE");
114          $this->exec("INSERT INTO seq VALUES ()");
115          $sth $this->prepare("SELECT LAST_INSERT_ID()");
116          $sth->execute();
117          $this->exec("UNLOCK TABLES");
118          $newId $sth->fetchColumn();
119  
120          $sth $this->prepare("DELETE FROM seq WHERE seq < :newID");
121          $sth->bindValue(":newID"$newId, \PDO::PARAM_INT);
122          $sth->execute();
123  
124          return intval($newId);
125      }
126  
127      /**
128       * Convenience method for setting the instance variable in an prepared
129       * statment. This variable is usually named ":instId", but you can use an
130       * alternative name.
131       *
132       * @param \PDOStatement $sth The statement for which to set the instance id.
133       * @param string $label An optional alternative label for the instance id
134       *     variable.
135       */
136      public function bindInstance(\PDOStatement $sth$label=":instId") {
137          $sth->bindValue($label$this->instId, \PDO::PARAM_INT);
138      }
139  
140      /**
141       * Implementation of the readable properties using the PHP magic
142       * method __get().
143       *
144       * @param string $field The name of the property to get.
145       *
146       * @return mixed The value of the requested property.
147       */
148      public function __get($field) {
149          if ($field == "instanceId") {
150              return $this->getInstanceId();
151          } else {
152              throw new \Scrivo\SystemException("Property $field not found");
153          }
154      }
155  
156      /**
157       * Overloaded version of PDO::prepare, just to be able to do some query
158       * logging.
159       *
160       * @param string $statement An SQL statement.
161       * @param array $options Driver options.
162       *
163       * @return \PDOStatement A PDO statement.
164       */
165      public function prepare($statement$options=array()) {
166          //error_log("Prepare: $statement");
167          return parent::prepare($statement$options);
168      }
169  
170  }
171  
172  ?>

Documentation generated by phpDocumentor 2.0.0a12 and ScrivoDocumentor on August 29, 2013