PHP通过Web API连接PostgreSQL失败问题求助
我有一套POS系统的Web API脚本,可通过表单提交执行查询语句(如select sum(antal*pris) from batch_salg where fakturadate = '2023-08-25')并成功获取数据,调用方式为fetch_from_table($serverurl,$db,$saldiuser,$api_key,$select,$from,$where,$order_by,$limit);,相关参数如下:
$serverurl="https://somedomain/pos/api"; $saldiuser = 'apiuser'; $db='posdb_9945864'; $api_key='dsdkfswaewmfmkev4546';
我仅熟悉MySQL,尝试使用pg_connect直接连接PostgreSQL,代码如下:
pg_connect(DB_HOST, DB_USER, DB_PASSWORD) or die(pg_error()); pg_select_db(DB_DATABASE) or die(pg_error()); $sho1_pg = pg_query("SELECT sum (antal*pris) FROM batch_salg WHERE fakturadate ='$date_today'") or die(pg_error()); $shop1_row = pg_fetch_array($sho1_pg); $shop1_today = $shop1_row['sum'];
但该连接方式失败,报错信息如下:
Warning: pg_connect() [function.pg-connect]: Unable to connect to PostgreSQL server: invalid port number: "pos_99" in /var/www/genogbrug.dk/stuff/jk1.php on line 24
Connection attempt failed.
补充说明:之前可用的Web API代码未定义端口号,我尝试用已有参数结合原MySQL习惯的方式连接却失败,寻求解决方法。以下是可用的Web API完整代码:
<html> <body> <?php (isset($_GET['action']))?$action=$_GET['action']:$action=NULL; (isset($_POST['select']))?$select=$_POST['select']:$select=NULL; (isset($_POST['from']))?$from=$_POST['from']:$from=NULL; (isset($_POST['where']))?$where=$_POST['where']:$where=NULL; (isset($_POST['order_by']))?$order_by=$_POST['order_by']:$order_by=NULL; (isset($_POST['limit']))?$limit=$_POST['limit']:$limit=NULL; (isset($_POST['update']))?$update=$_POST['update']:$update=NULL; (isset($_POST['set']))?$set=$_POST['set']:$set=NULL; (isset($_POST['insert']))?$insert=$_POST['insert']:$insert=NULL; (isset($_POST['fields']))?$fields=$_POST['fields']:$fields=NULL; (isset($_POST['values']))?$values=$_POST['values']:$values=NULL; if (isset($_GET['select'])) $select=$_GET['select']; if (isset($_GET['from'])) $from=$_GET['from']; if (isset($_GET['where'])) $where=$_GET['where']; if (isset($_GET['order_by'])) $order_by=$_GET['order_by']; if (isset($_GET['update'])) $update=$_GET['update']; if (isset($_GET['set'])) $set=$_GET['set']; if (isset($_GET['insert'])) $insert=$_GET['insert']; if (isset($_GET['fields'])) $fields=$_GET['fields']; if (isset($_GET['values'])) $values=$_GET['values']; $serverurl="https://somedomain.com/pos/api"; $saldiuser = 'apiuser'; $db='DBname'; $api_key='125155dfgtr5trg5t1tr5t'; if ($action) { if ($action == 'fetch_from_table') fetch_from_table($serverurl,$db,$saldiuser,$api_key,$select,$from,$where,$order_by,$limit); elseif ($action == 'update_table') update_table($serverurl,$db,$saldiuser,$api_key,$update,$set,$where); elseif ($action == 'insert_into_table') insert_into_table($serverurl,$saldiuser,$db,$api_key,$insert,$fields,$values); } else { print "<form name=\"rest_api_client\" action=\"rest_api_client.php?action=fetch_from_table\" method='post'>\n"; print "<table><tbody>"; print "<tr><td>Select</td><td><input style=\"width:1000px;\" type='text' name='select' value=\"$select\"></td></tr>\n"; print "<tr><td>From</td><td><input style=\"width:1000px;\" type='text' name='from' value=\"$from\"></td></tr>"; print "<tr><td>Where</td><td><input style=\"width:1000px;\" type='text' name='where' value=\"$where\"></td></tr>"; print "<tr><td>Order by</td><td><input style=\"width:1000px;\" type='text' name='order_by' value=\"$order_by\"></td></tr>"; print "<tr><td>Limit</td><td><input style=\"width:1000px;\" type='text' name='limit' value=\"$limit\"></td></tr>"; print "<tr><td colspan='2' align='center'><input type='submit' name='go' value='Go'></td></tr>\n"; print "</tbody></table>"; print "</form>"; print "<form name=\"rest_api_client\" action=\"rest_api_client.php?action=update_table\" method='post'>\n"; print "<table><tbody>"; print "<tr><td>Update</td><td><input style=\"width:1000px;\" type='text' name='update' value=\"$update\"></td></tr>\n"; print "<tr><td>Set</td><td><input style=\"width:1000px;\" type='text' name='set' value=\"$set\"></td></tr>"; print "<tr><td>Where</td><td><input style=\"width:1000px;\" type='text' name='where' value=\"$where\"></td></tr>"; print "<tr><td colspan='2' align='center'><input type='submit' name='go' value='Go'></td></tr>\n"; print "</tbody></table>"; print "</form>"; print "<form name=\"rest_api_client\" action=\"rest_api_client.php?action=insert_into_table\" method='post'>\n"; print "<table><tbody>"; print "<tr><td>Insert into</td><td><input style=\"width:1000px;\" type='text' name='insert' value=\"$insert\"></td></tr>\n"; print "<tr><td>Fields</td><td><input style=\"width:1000px;\" type='text' name='fields' value=\"$fields\"></td></tr>"; print "<tr><td>Values</td><td><input style=\"width:1000px;\" type='text' name='values' value=\"$values\"></td></tr>"; print "<tr><td colspan='2' align='center'><input type='submit' name='go' value='Go'></td></tr>\n"; print "</tbody></table>"; print "</form>"; } function fetch_from_table($serverurl,$db,$saldiuser,$api_key,$select,$from,$where,$order_by,$limit) { $result = file_get_contents($serverurl."/rest_api.php?action=fetch_from_table&saldiuser=$saldiuser&db=$db&key=$api_key&select=".urlencode($select)."&from=".urlencode($from)."&where=".urlencode($where)."&order_by=".urlencode($order_by)."&limit=".urlencode($limit)); $result = json_decode($result, true); if (!is_array($result)) { print "error: ".$result; } else { print "<table border='1'><tbody>"; $rows=count($result); $cols=count($result[0]); for ($x=0;$x<$rows;$x++){ print "<tr>"; for ($y=0;$y<$cols;$y++) { print "<td>".$result[$x][$y]."</td>"; } print "</tr>"; } print "</tbody></table>"; } print "<a href=\"rest_api_client.php?select=$select&from=$from&where=$where&order_by=$order_by&limit=$limit\">Return to query page</a>"; } function update_table($serverurl,$db,$saldiuser,$api_key,$update,$set,$where) { $result = file_get_contents($serverurl."/rest_api.php?action=update_table&db=$db&saldiuser=$saldiuser&key=$api_key&update=".urlencode($update)."&set=".urlencode($set)."&where=".urlencode($where)); $result = json_decode($result, true); if (!is_numeric($result)) { print "error: ".$result; } else { print "<table border='1'><tbody>"; print "<td>".$result."</td>"; print "</tr>"; print "</tbody></table>"; } print "<br><a href=\"rest_api_client.php?update=$update&set=$set&where=$where\">Return to query page</a>"; } function insert_into_table($serverurl,$db,$saldiuser,$api_key,$insert,$fields,$values) { $result = file_get_contents($serverurl."/rest_api.php?action=insert_into_table&saldiuser=$saldiuser&db=$db&key=$api_key&insert=".urlencode($insert)."&fields=".urlencode($fields)."&values=".urlencode($values)); $result = json_decode($result, true); if (!is_numeric($result)) { print "error: ".$result; } else { print "<table border='1'><tbody>"; print "<td>".$result."</td>"; print "</tr>"; print "</tbody></table>"; } print "<br><a href=\"rest_api_client.php?insert=$insert&fields=$fields&values=$values\">Return to query page</a>"; } ?> </body> </html>
1. 错误原因
pg_connect的参数逻辑和MySQL的连接函数完全不同:
- MySQL允许分开传入主机、用户、密码等参数,但PostgreSQL的
pg_connect要求传入完整的连接字符串,或使用命名参数格式。 - 你当前的调用方式会让PostgreSQL错误解析
DB_HOST的内容,把其中非数字的部分当成端口号,导致"invalid port number"报错。 - 另外,POS系统提供了专用Web API,大概率数据库没有开放直接的外部连接权限,这也是直接连接失败的核心原因之一。
2. 可行方案
方案一:正确使用pg_connect连接格式(仅当数据库允许直接连接时)
如果确认数据库开放了外部连接权限,按照PostgreSQL要求的格式构造连接字符串:
// 替换为实际的主机地址、端口(默认5432)等参数 $conn_str = "host=真实主机地址 port=5432 dbname=".DB_DATABASE." user=".DB_USER." password=".DB_PASSWORD; $conn = pg_connect($conn_str) or die(pg_last_error()); // 执行查询(给sum结果起别名,方便后续取值) $query = "SELECT sum(antal*pris) AS total_sum FROM batch_salg WHERE fakturadate = '$date_today'"; $sho1_pg = pg_query($conn, $query) or die(pg_last_error($conn)); $shop1_row = pg_fetch_assoc($sho1_pg); $shop1_today = $shop1_row['total_sum']; // 关闭连接 pg_close($conn);
注意:
- 必须确保你的服务器IP在数据库的白名单/安全组内
- 避免SQL注入,推荐使用参数化查询:
$query = "SELECT sum(antal*pris) AS total_sum FROM batch_salg WHERE fakturadate = $1"; $params = array($date_today); $sho1_pg = pg_query_params($conn, $query, $params) or die(pg_last_error($conn));
方案二:复用现有Web API(推荐)
既然已有API能正常工作,直接调用即可,无需折腾数据库连接:
$serverurl="https://somedomain/pos/api"; $saldiuser = 'apiuser'; $db='posdb_9945864'; $api_key='dsdkfswaewmfmkev4546'; $select = "sum(antal*pris)"; $from = "batch_salg"; $where = "fakturadate = '$date_today'"; // 调用API自带的函数 fetch_from_table($serverurl, $db, $saldiuser, $api_key, $select, $from, $where, null, null); // 或者自定义处理返回结果 $result = file_get_contents($serverurl."/rest_api.php?action=fetch_from_table&saldiuser=$saldiuser&db=$db&key=$api_key&select=".urlencode($select)."&from=".urlencode($from)."&where=".urlencode($where)); $result = json_decode($result, true); if(is_array($result) && !empty($result)){ $shop1_today = $result[0][0]; // API返回二维数组,第一行第一列即为sum结果 }
这个方案无需处理数据库权限、端口等问题,直接利用现有接口,稳定性更高。
内容的提问来源于stack exchange,提问作者Krohn

