用 PHP编写简单MySQL Bridge |
发布: 2013-07-23 22:37 |
许多虚拟主机空间提供MySQL服务,但不提供外部访问服务。 如果需要外部依旧能够使用MySQL服务,需要在虚拟主机上安装一个桥接程序。 当然这种桥接程序提供的是另一套接口了,而不是直接走的mysql协议了。 其他使用这个服务的程序需要改到这套接口调用上。 桥接程序不复杂,最简单的情况下只需要提供一个query接口即可。 拿PHP为例,定义简单接口,实例MySQL服务的桥接接口程序。 服务器端程序pmp.php,定义了一个有两个参数的query接口, /** * @param sql string * @param params array */ /* settings.php template: $db_host = ""; $db_port = 3306; $db_user = ""; $db_pass = ""; $db_name = ""; */ require('settings.php'); $json_command = $_POST['command']; $command = json_decode($json_command, true); if (isset($command['dbname']) && !empty($command['dbname'])) { $db_name = $command['dbname']; } $sql = $command['sql']; $params = $command['params']; $dsn = "mysql:host={$db_host};port={$db_port};dbname={$db_name}"; $options = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''); $pdo = new PDO($dsn, $db_user, $db_pass, $options); $stmt = $pdo->prepare($sql); $ret = false; if ($stmt) { $ret = $stmt->execute($params); $rows = array(); for ($i = 0; $i < 3000; $i ++) { $row = $stmt->fetch(PDO::FETCH_BOTH); if ($row === false) { break; } $rows[] = $row; } } $result = array('ret'=> $ret, 'rows' => $rows, 'count' => count($rows), 'last_insert_id' => $pdo->lastInsertId(), 'affected_rows' => $stmt->rowCount(), 'pdo_errno' => $pdo->errorCode(), 'pdo_error' => $pdo->errorInfo(), 'stmt_errno' => $stmt->errorCode(), 'stmt_error' => $stmt->errorInfo(), 'sql' => $sql, 'params' => $params, ); $json_result = json_encode($result); echo $json_result; ?> 客户端封装类,pmpc.php class Pmpc { private $_service_url = 'http://102.118.123.121/pmp.php'; private $_service_ip = 'name.vaapp.com'; private $_db_name = ''; private $_timeout = 10; public function __construct() { } public function query($sql, $params, $db_name = '') { $command = array('sql' => $sql, 'params' => $params); if (!empty($this->_db_name)) { $command['db_name'] = $this->_db_name; } if (!empty($db_name)) { $command['db_name'] = $db_name; } $jcommand = json_encode($command); $headers = array('Host: ' . $this->_service_ip); $data = curl_post($this->_service_url, array('command'=>$jcommand), $headers, $this->_timeout); return $data; } }; function curl_post($url, $data = array(), $header = array(), $timeout = 5, $port = 80) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout); //curl_setopt($ch, CURLOPT_PORT, $port); !empty ($header) && curl_setopt($ch, CURLOPT_HTTPHEADER, $header); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); $result = array(); $result['result'] = curl_exec($ch); if (0 != curl_errno($ch)) { $result['errno'] = curl_errno($ch); $result['error'] = "Error:\n" . curl_error($ch); $result['reqinfo'] = curl_info($ch); } curl_close($ch); return $result; } ?> 调用的时候也非常简单,如pmpt.php, require_once('pmpc.php'); $pc = new Pmpc(); $limit = rand(1,9); $sql = "SELECT * FROM node WHERE 1 = :v1 ORDER BY nid LIMIT {$limit}"; $params = array(':v1' => 1); $res = $pc->query($sql, $params); var_dump($res); ?> 这里的参数规则定义了必须使用数据库的bind模式,防止拼接SQL时容易出现的特殊符号转义问题。 客户端与服务器端之间的数据传递使用的是json格式,方便数据格式的转换。 这个实现支持客户端传入数据库名,但不支持客户端传入数据库IP及用户名密码等。 目前的实现,还不太完善,如服务器端桥接程序没有很好的处理错误及异常情况。 客户端的封装没有在query方法返回类似数据库查询的数组结果, 而是返回了原始的HTTP请求的响应文本,需要改进为,客户端封装接口传入的参数与返回 的结果都是PHP的数组格式。 同类产品http://www.razorsql.com/ |
原文: http://qtchina.tk/?q=node/740 |
Powered by zexport
|