Location: PHPKode > scripts > Mysql Locker > mysql-locker/MysqlLocker.php
<?php
// +----------------------------------------------------------------------+
// | Simple and safe MySQL lock manager class for PHP5                    |
// | Copyright (C) 2005 Craig Manley                                      |
// +----------------------------------------------------------------------+
// | This library is free software; you can redistribute it and/or modify |
// | it under the terms of the GNU Lesser General Public License as       |
// | published by the Free Software Foundation; either version 2.1 of the |
// | License, or (at your option) any later version.                      |
// |                                                                      |
// | This library is distributed in the hope that it will be useful, but  |
// | WITHOUT ANY WARRANTY; without even the implied warranty of           |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU     |
// | Lesser General Public License for more details.                      |
// |                                                                      |
// | You should have received a copy of the GNU Lesser General Public     |
// | License along with this library; if not, write to the Free Software  |
// | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  |
// | USA                                                                  |
// |                                                                      |
// | LGPL license URL: http://opensource.org/licenses/lgpl-license.php    |
// +----------------------------------------------------------------------+
// | Author: Craig Manley                                                 |
// +----------------------------------------------------------------------+
//
// $Id: MysqlLocker.php,v 1.1 2005/02/14 23:49:33 cmanley Exp $
//


/**
 * @author    Craig Manley (freelance software developer)
 * @copyright Copyright © 2005, Craig Manley. All rights reserved.
 * @package   MysqlLocker
 * @version   $Revision: 1.1 $
 */


/**
 * This is a simple class for safely using MySQL locks.
 * Locks are created when you instantiate the class and are automatically released when
 * the object is destroyed. This occurs when the object is not longer referenced,
 * or when it goes out of scope. The latter also occurs when a PHP script dies or
 * when an exception occurs, and this is where this class is most useful because
 * it'll make sure that all existing locks are automatically released for you.
 *
 * <b>SYNOPSIS</b>
 * <pre>
 * require_once('MysqlLocker.php');
 *
 * // Create table locks
 * $locker = new MysqlLocker($link, array('Customers' => 'READ',
 *                                        'Articles'  => 'WRITE'));
 *
 * // Execute some tricky statements here...
 * // ... and then ...
 * throw new Exception('Nooooooooo!!!!');
 * // ... or ...
 * trigger_error('Oops something bad happened!', E_USER_ERROR);
 * // ... or ...
 * die("Uuuhghhgg!\n");
 *
 * // Locks are also released when $locker goes out of scope or if you explictly set it to null.
 * $locker = null;
 * </pre>
 *
 * @author    Craig Manley (freelance software developer)
 * @copyright Copyright © 2005, Craig Manley. All rights reserved.
 * @package   MysqlLocker
 * @version   $Revision: 1.1 $
 */
class MysqlLocker {

  // Private members
  private $dbh = null;
  private $option_debug = false;


  /**
   * Contructor. Locks the specified tables and keeps them locked for the life time of this object.
   *
   * @param resource $link mysql link resource connected to the database.
   * @param array $locks Associative array of tablename => locktype pairs.
   * @param array $options Optional associative array of options:
   * <pre>
   *    debug: if set and true, then debug messages are passed to the error_log() function.
   * </pre>
   * @return object
   */
  public function __construct($link = null, $locks = null, $options = null) {
    // Get parameter 1.
    if (!(isset($link) && is_resource($link) && (get_resource_type($link) == 'mysql link'))) {
      throw new Exception('First parameter is not a mysql link resource!');
    }
    $this->dbh = $link;
    // Get parameter 2.
    if (!isset($locks) && is_array($locks) && count($locks)) {
      throw new Exception('No table locks specified!');
    }
    $tables = array_keys($locks);
    if (!count($tables)) {
      throw new Exception('No table locks specified!');
    }
    // Get parameter 3.
    if (isset($options) && is_array($options)) {
      if (isset($options['debug']) && $options['debug']) {
        $this->option_debug = true;
      }
    }
    // Lock tables.
    $pairs = array();
    foreach ($tables as $table) {
      array_push($pairs, "$table " . $locks[$table]);
    }
    $sql = 'LOCK TABLES ' . implode(', ', $pairs);
    $this->option_debug && error_log(__METHOD__ . " locking tables with SQL \"$sql\".");
    if (!mysql_query($sql)) {
      throw new Exception('Error locking tables; code: ' . mysql_errno($dbh) . "; message: " . mysql_error($dbh));
    }
  }


  /**
   * Destructor. Unlocks the locked tables.
   */
  public function __destruct() {
    $dbh = $this->dbh;
    if (isset($dbh)) {
      $this->option_debug && error_log(__METHOD__ . ' unlocking tables.');
      if (!mysql_query('UNLOCK TABLES', $dbh)) {
        $this->option_debug && error_log(__METHOD__ . ' failed to unlock tables, attempting to reconnect to MySQL.');
      	if (mysql_ping($dbh)) {
      	  $this->option_debug && error_log(__METHOD__ . ' about to unlock tables (2nd attempt).');
      	  if (!mysql_query('UNLOCK TABLES', $dbh)) {
      	    trigger_error("Failed to unlock tables, even after reconnect.\nMySQL code: " . mysql_errno($dbh) . "\nMySQL reason: " . mysql_error($dbh), E_USER_WARNING); // this should never occur.
      	  }
        }
        else {
          trigger_error("Failed to unlock tables. Unable to reconnect to the MySQL server.\nMySQL code: " . mysql_errno($dbh) . "\nMySQL reason: " . mysql_error($dbh), E_USER_NOTICE); // not a warning because the locks have probably been released anyway due to the disconnect.
        }
      }
    }
  }
}


?>
Return current item: Mysql Locker