Using PDO Query reset my server - php

I've some trouble with my website. It works perfectly on localhost, but since yesterday I tried to put it on my windows 2003 server. (with apache 2.2.11, mysql 5.1.31, php 5.2.8).
My problem is when I try to use authentification page of my website, server reset.
It reset only if I call the PDO->query function (to get user on my database)
My query code :
function getUser($login)
{
try{
$bdd = connectDB();
$requete = $bdd->query('SELECT * FROM `utilisateur` WHERE `Login` = \''.$login.'\'');
$user = new Utilisateur();
if($donnees = $requete->fetch())
{
$user->setLogin($donnees['Login']);
$user->setAuth($donnees['Role']);
$user->setTrigramme($donnees['Trigramme']);
}
$requete->closeCursor();
disconnectDB($bdd);
return $user;
}catch(Exception $e){
error_log('Exception :
'.$e, 3, ADR_ERROR_LOG);
}
}
Line : ConnectDb works fine, but when it arrive on the net line, navigator (I've tried with IE, Chrome and Firefox) wait a long time and said 'Connexion with the server has been reset', and I've none error message on my error log:(
Thank's in advance
EDIT : I've tried like this, and still have the same problem :
function getUser($login)
{
try{
$bdd = connectDB();
$requete = $bdd->prepare('SELECT * FROM `utilisateur` WHERE `Login` = :login');
// $requete = $bdd->query('SELECT * FROM utilisateur WHERE Login = \''.$login.'\'');
$requete->bindValue('login', $login, PDO::PARAM_STR);
$requete->execute();
$user = new Utilisateur();
if($donnees = $requete->fetch())
{
$user->setLogin($donnees['Login']);
$user->setAuth($donnees['Role']);
$user->setTrigramme($donnees['Trigramme']);
}
$requete->closeCursor();
disconnectDB($bdd);
return $user;
}catch(Exception $e){
error_log('Exception :
'.$e, 3, ADR_ERROR_LOG);
}
}
EDIT 2 This works with this : BUT WHY ???
$db = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);
mysql_select_db(DB_NAME,$db);
$sql = 'SELECT * FROM `utilisateur` WHERE `Login` = \''.$login.'\'';
$req = mysql_query($sql) or die('Erreur SQL !<br>'.$sql.'<br>'.mysql_error());
$user = new Utilisateur();
while($donnees = mysql_fetch_assoc($req))
{
$user->setLogin($donnees['Login']);
$user->setAuth($donnees['Role']);
$user->setTrigramme($donnees['Trigramme']);
}
mysql_close();
return $user;

Finally I use mysqli_ to do what I wanted and it works perfectly.
If someone have a solution about this problem, He could put it in order to help the next person.
Thank's to the persons who have search solution.

I think you have just got a typo in your code. With PDO a typo can determine your fate and have you scratching your head for a minute. Look at your prepare query. When you bind the login parameter you never specified the : before login.
Look at this part:
$requete->bindValue('login', $login, PDO::PARAM_STR);
So "login" should be ":login". Just for future reference you don't have to use PDO::PARAM_STR because any parameters bound to the query are automatically handled as strings. If you were binding a numeric value then you'd want to set the data type to PDO::PARAM_INT.
PDO can be tricky - especially when it comes to typos and errors.
Long story short I think the parameter naming issue is all of your problems.

Related

How to connect to MySQL using PDO using PHP function [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I'm using this method to connect to my MySQL db to SELECT, INSERT, UPDATE and DELETE data. This is the cnn() function:
function cnn() {
static $pdo;
if(!isset($pdo)) {
$settings = [
PDO::ATTR_TIMEOUT => 30,
PDO::ATTR_PERSISTENT => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC
];
try {
# settings
$config['db']['host'] = 'example.com';
$config['db']['name'] = 'db';
$config['db']['user'] = 'username';
$config['db']['pass'] = '****************';
$pdo = new PDO('mysql:host='.$config['db']['host'].';dbname='.$config['db']['name'], $config['db']['user'], $config['db']['pass'], $settings);
return $pdo;
} catch(PDOException $e) {
http_response_code(503);
echo $e->getCode().': '.$e->getMessage();
}
} else {
return $pdo;
}
}
And then i can just do this to re-use the same pdo object each time i need it on the same request.
1st query
$sql = 'INSERT INTO user (name, lastname) VALUES (:name, :lastname)';
$stmt = cnn()->prepare($sql);
$stmt->bindValue(':name', "John", PDO::PARAM_STR);
$stmt->bindValue(':name', "Wayne", PDO::PARAM_STR);
$stmt->execute();
2nd query
$sql = 'SELECT * FROM user WHERE id_user = :id_user';
$stmt = cnn()->prepare($sql);
$stmt->bindValue(':id_user', 4641, PDO::PARAM_INT);
$stmt->execute();
$user = $stmt->fetch();
I was wondering if there could be any performance issues by using this approach. Thanks.
1)
As referenced by HTMHell, your $config array is local here and I believe this should be deleted after use so password variables are not leakable on a later get_defined_vars() call, or similar cross reference.
2)
It seems far more logical to me to put your function in a class. Run the cnn() function from the __construct. There are a lot of positive aspects to wrapping this function in a full class.
3)
Do NOT set any variable to being static unless you have a specific requirement in the context of putting your cnn() function into a Class.
4)
Correctly use your try{ ... } catch { ... } blocks, do not wrap other code in the try block except code that throws exceptions.
// settings
$config['db']['host'] = 'example.com';
$config['db']['name'] = 'db';
$config['db']['user'] = 'username';
$config['db']['pass'] = '****************';
try {
$pdo = new PDO('mysql:host='.$config['db']['host'].';dbname='.$config['db']['name'], $config['db']['user'], $config['db']['pass'], $settings);
} catch(PDOException $e) {
/***
* Do you really need this, here?
* //http_response_code(503);
**/
echo $e->getCode().': '.$e->getMessage();
}
return $pdo;
5)
DO NOT EVER OUTPUT ERRORS DIRECTLY TO THE SCREEN
Errors should be logged so only server folks and developers rather than the general public can see them. This also means you have a log of errors rather than a single, temporary instance of any that occur.
echo $e->getCode().': '.$e->getMessage(); Should be:
error_log($e->getCode().': '.$e->getMessage());
Or similar. Stay consistent; always return a PDO object and not echo outputs.
6)
Remove your final else wrapper it is merely clutter.
if(!isset($pdo)) {
...
}
return $pdo;
Also remove the return $pdo; inside your try { ... } block. Don't Repeat Yourself.
7)
Properly document your code:
/***
* For generating or asserting a PDO Database Object.
* #return Returns the PDO object
***/
function cnn() {
To answer the question you actually asked:
I was wondering if there could be any performance issues by using this approach.
This question is far too broad and can be solved by yourself using timer testings or other methods (detailed in the link) to establish on your system if it is particularly efficient or inefficient, or what SQL you choose to give it...

PDO Sqlite error 5: database locked

I've been trying to use a sqlite database (php with PDO), but have been running into a problem. Generally the commands work, and everything is fine (including storing files), but for some reason when I run these two commands (which have been simplified), I get the error
SQLSTATE[HY000]: General error: 5 database is locked
I've tried for a while, but have been unable to fix whatever is wrong. The code is below.
Things I've done:
Tried to put sleep(2) between commands
Found out that commenting either of the commands out will cause the error not to happen (which doesn't really help, as both commands must run)
Note that (unlike other problems I saw while looking at similar questions) the database operates correctly in other cases.
$db = new MyDB();
$STH = $db->catchMistakes('SELECT PASSWORD FROM USERS WHERE USERNAME = ?', "test");
$STH->fetchColumn();
$db->catchMistakes("UPDATE ISSUES SET NAME = ? WHERE NUM = ?", ["test", "1"]);
And here's the code for MyDB
public function catchMistakes($cmd, $params = []) {
if (!is_array($params)) {
$params = [$params];
}
try {
$DBH = new PDO("sqlite:" . DB);
$DBH->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$DBH->beginTransaction();
$query = $DBH->prepare($cmd);
$toReturn = $query->execute($params);
$DBH->commit();
return $query;
}
catch(PDOException $e) {
$DBH->rollback();
$error = $e->getMessage();
exit;
}
}
Sorry if there's a simple fix, I'm pretty new at this. Any help would be greatly appreciated.
You can use closeCursor() method on a PDOStatement object to free the connection to the database so the statement can be executed. You can refer to the PHP manual.

Vertica and PDO prepared statements

For the last two days, I've been struggling with a very strange bug while I'm connecting with Vertica using PDO. You see, the following script works:
$c = new PDO("odbc:Driver=Vertica;Server=x.x.x.x;Port=5433;Database=db;", "MyUser", "MyPassword");
$c->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $c->prepare("SELECT * FROM myClients WHERE ClientNum = 88");
$stmt->execute();
After that, I loop through the results and display them no problem. This basically means my connection is correct otherwise I wouldn't get anything out of the database. On the other hand, the following makes the Apache server reset the connection completely (when run in Windows, I get a message that Apache crashed):
$c = new PDO("odbc:Driver=Vertica;Server=x.x.x.x;Port=5433;Database=db;", "MyUser", "MyPassword");
$c->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$c->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
//$c->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
try
{
$stmt = $c->prepare("SELECT * FROM myClients WHERE ClientNum = :cl");
$stmt->bindValue(":cl", 88);
$stmt->execute();
while($res = $stmt->fetch(PDO::FETCH_ASSOC))
{
echo $res['noClient'] . "<br>";
}
}
catch(Exception $e)
{
echo $e->getMessage();
}
The problem is present both in Linux and Windows and I'm using Vertica version 7.0.2-1 along with the corresponding ODBC driver. The problem was also present in Vertica 6.1. Can anyone give me a hand with this?
Thanks in advance.
EDIT: I tried to set PDO::ATTR_EMULATE_PREPARES to both true and false without any change.
EDIT: This being a test script, I didn't bother with any error handling. Also, given that the server actually crashes, I doubt it would change anything.
EDIT: Updated the code above to include some basic error handling. Apologies to Kermit for sounding condescending in my earlier comment. Anyway, even with this addition to my code, I still didn't get any message, the server would just silently crash and I'd get a "Connection reset" page. Upon seeing this, I tried querying different tables in my database and on one, instead of a crash, I got the following:
SQLSTATE[HY000]: General error: 50310 [Vertica][Support] (50310) Unrecognized ICU conversion error. (SQLExecute[50310] at ext\pdo_odbc\odbc_stmt.c:254)
EDIT: Went to my ODBC DSN, clicked Configure, went on the Server Setting tab and found that the locale was set to: en_US#collation=binary (which is the default for Vertica, I believe). Should I check somewhere else?
EDIT: I was curious to see what the bindValue() was doing to my query and so opened the vertica.log file. Here's what I saw:
2014-10-02 11:38:42.100 Init Session:0x5ef3030 [Session] <INFO> [Query] TX:0(vertica-1756:0xbc42) set session autocommit to on
2014-10-02 11:38:42.104 Init Session:0x5ef3030 [Session] <INFO> [PQuery] TX:0(vertica-1756:0xbc42) SELECT * FROM myClients WHERE ClientNum = ?
2014-10-02 11:38:42.105 Init Session:0x5ef3030-a00000000aac68 [Txn] <INFO> Begin Txn: a00000000aac68 'SELECT * FROM myClients WHERE ClientNum = ?'
2014-10-02 11:38:42.915 Init Session:0x5ef3030-a00000000aac68 <LOG> #v_flexgroup_node0001: 08006/2895: Could not receive data from client: No such file or directory
2014-10-02 11:38:42.915 Init Session:0x5ef3030-a00000000aac68 <LOG> #v_flexgroup_node0001: 08006/5167: Unexpected EOF on client connection
2014-10-02 11:38:42.915 Init Session:0x5ef3030-a00000000aac68 <LOG> #v_flexgroup_node0001: 00000/4719: Session vertica-1756:0xbc42 ended; closing connection (connCnt 2)
2014-10-02 11:38:42.916 Init Session:0x5ef3030-a00000000aac68 [Txn] <INFO> Rollback Txn: a00000000aac68 'SELECT * FROM myClients WHERE ClientNum = ?'
Apparently, it seems PDO is replacing the placeholders by question marks in the final query. Not all that unexpected, but for some reason, the actual value of the parameter seems to get lost along the way.
EDIT: Following a suggestion, I tried:
$stmt = $c->prepare("SELECT * FROM myClients WHERE ClientNum = :cl");
$stmt->execute(array(":cl" => 88));
But the problem remains the same.
Okay, so after going halfway crazy trying to figure out what was wrong with PDO, I discovered that using PHP odbc module directly worked.
Since all my modules are actually written using PDO and rewriting them was not an option, I ended up writing the following wrapper classes:
class PDOVertica
{
protected $conn;
public function __construct($dsn, $user, $password)
{
$this->conn = odbc_connect($dsn, $user, $password);
}
public function prepare($qry)
{
return new PDOVerticaStatement($this->conn, $qry);
}
public function lastInsertId()
{
$stmt = odbc_prepare($this->conn, "SELECT LAST_INSERT_ID()");
odbc_execute($stmt);
$res = odbc_fetch_array($stmt);
return $res['LAST_INSERT_ID'];
}
}
class PDOVerticaStatement
{
protected $qry;
protected $param;
protected $stmt;
public function __construct($conn, $qry)
{
$this->qry = preg_replace('/(?<=\s|^):[^\s:]++/um', '?', $qry);
$this->param = null;
$this->extractParam($qry);
$this->stmt = odbc_prepare($conn, $this->qry);
}
public function bindValue($param, $val)
{
$this->param[$param] = $val;
}
public function execute()
{
if($this->param == null)
odbc_execute($this->stmt);
else
odbc_execute($this->stmt, $this->param);
$this->clearParam();
}
public function fetch($option)
{
return odbc_fetch_array($this->stmt);
}
protected function extractParam($qry)
{
$qryArray = explode(" ", $qry);
$ind = 0;
while(isset($qryArray[$ind]))
{
if(preg_match("/^:/", $qryArray[$ind]))
$this->param[$qryArray[$ind]] = null;
++$ind;
}
}
protected function clearParam()
{
$ind = 0;
while(isset($this->param[$ind]))
{
$this->param[$ind] = null;
++$ind;
}
}
}
I was pleasantly surprised to find that this works without me having to rewrite hundreds of modules. I do need to rework some of the SQL since there are differences between MySQL and Vertica, but those are just minor touch ups.
Anyway, should anyone choose to use these classes, keep in mind I only implemented what I needed in terms of functionalities and they only work with queries using placeholders for parameters (:someParameter). Use them and modify them at your own discretion.
Thanks for anyone who helped me.

"invalid data source name" with PDO MySQL

It was always working for me but this time it's not.
conect.ini
conn = "mysql:host=localhost; dbname=%dbname%"
user = "root"
pass = "%passwd%"
conn1 = "mysql:host=%myRealHostAddr%; dbname=%dbname%"
user1 = "%user%"
pass1 = "%passwd%"
pdo
class prepeared {
const LOG = "lock/loginsStat.log";
private $_db;
private $dbc;
function __construct(){
$this->dbc = parse_ini_file($_SERVER["DOCUMENT_ROOT"]."/hours/lock/conect.ini");
try{
$this->_db = new PDO($this->dbc["conn"], $this->dbc["user"], $this->dbc["pass"]);
}catch(PDOException $e){
echo $e->getMessage();
}
}
etc....
Vars %var% are real values just changed them for this post.
Vars with 1 are working at the hosting just fine (without 1, it was added only for a local testing). When I take it to a local machine for some testing I'm adding this 1 to disable them and making a new vars for a local settings.
The error that I see now it's
invalid data source name
Any ideas why? I know that this configuration was working just fine when I used it couple weeks ago so I suspect there is no errors here. Probably I'm wrong...
Get rid of catch(PDOException $e){ echo $e->getMessage();} stuff in order to get full and useful error message instead of that stub you have at the moment.
var_dump($this->dbc); also helps a lot.

Cant pass mysqli connection to class

I am trying to pass an mysqli database connection to a php class. The code I have so far (cut down for simplicity) is as follows:
db.php
$db_host = 'localhost';
$db_name = 'dbname';
$db_user = 'username';
$db_password = 'password';
$db = array('db_host'=>$db_host,
'db_name'=>$db_name,
'db_user'=>$db_user,
'db_password'=>$db_password);
$dbCon = new mysqli( $db['db_host'],
$db['db_user'],
$db['db_password'],
$db['db_name']);
if (mysqli_connect_errno())
{
die(mysqli_connect_error()); //There was an error. Print it out and die
}
index.php
<?php
require_once($_SERVER["DOCUMENT_ROOT"] . "/db.php");
$sql = "SELECT id FROM usr_clients";
$stmt = $dbCon->prepare( $sql );
if ($stmt)
{
$stmt->execute();
$stmt->bind_result($id);
while($stmt->fetch())
{
$cl = new Client($id, $dbCon);
$cl->doIt();
}
$stmt->close();
}
?>
client.php
<?php
Class Client
{
private $con;
public static $clientCount = 0;
public function __construct( $id, $con )
{
$this->con = $con;
$sql = "SELECT id FROM usr_clients WHERE id = $id";
$stmt = $this->con->prepare( $sql );
if ($stmt)
{
echo "it worked!";
}
else
{
echo "it failed";
}
}
}
?>
Now the index.php page successfully recognises the database connection declared in db.php, and returns a list of all clients. It then loops through each client, and creates a "client" object, passing it the database connection.
It is here that the problem seems to start. In the client class, the database connection is not recognised. I get multiple errors on the page saying "it failed". In the logs, there is a line about calling prepare() on a non object.
Can anyone explain why the connection works in index.php, but not in the client class?
Thanks
Your main problem is assumptions.
You are assuming that there is no connection passed, judging by indirect consequence.
But a programmer should be always logically correct in their reasoning.
Talking of connection? Verify the very connection. var_dump($con) in the constructor. var_dump($this->con) in the method. If it fails - only now you can blame connection and start for the solution.
If not - there is no reason in looking for another connection passing method. Yet it's time to find the real problem.
If your query fails, you have to ask mysql, what's going on, using $this->con->error, as this function will provide you with a lot more useful information than simple "it fails". The right usage I've explained here: https://stackoverflow.com/a/15447204/285587

Categories