I'm working on an android app that requires connection to a database. I have the android part working but I'm having trouble with my php script.
<?php
$con = mysqli_connect(/This info is correct/) or die ("Unable to connect");
$gebruikersnaamOntvanger = $_POST["gebruikersnaamOntvanger"];
$idBetaler = $_POST["idBetaler"];
$bedrag = $_POST["bedrag"];
$saldoBetaler = $_POST["saldo"];
$response = array();
$response["success"] = "false";
$statement = mysqli_prepare($con, "SELECT idGebruiker, Saldo FROM Gebruikers WHERE Gebruikersnaam = ?");
mysqli_stmt_bind_param($statement, "s", $gebruikersnaamOntvanger);
mysqli_stmt_execute($statement);
mysqli_stmt_store_result($statement);
mysqli_stmt_bind_result($statement, $idGebruiker, $Saldo);
while($row = mysqli_stmt_fetch($statement)){
$idOntvanger = $idGebruiker;
$saldoOntvanger = $Saldo;
}
$saldoOntvanger += $bedrag;
$saldoBetaler -= $bedrag;
try {
$statement2 = mysqli_prepare($con, "INSERT INTO Transacties (idBetaler, idOntvanger, Bedrag, Datum, Uitgevoerd) VALUES(?, ?, ?, now(), 1)");
mysqli_stmt_bind_param($statement2, "iid", $idBetaler, $idOntvanger, $bedrag);
mysqli_stmt_execute($statement2);
$response["success"] = "success";
} catch(Exception $e) {
$response["success"] = $e->gettext;
}
echo json_encode($response);
?>
So the android part work and returns the JSON object correctly but nothing changes in the database. I have tried adding a try catch so I get what's the error but the try catch never works. The script alwayws returns success even if it didn't work. Please be aware I'm new to PHP and I have double checked the SQL queries and they should be correct. If you need more information please ask.
mysqli_* function dosn't throws exceptions. So your catch is never executed even on error. Change your code like this :
if(!mysqli_stmt_execute($statement2))
throw new Exception(mysqli_stmt_error($statement2));
When you'll see the error you can fix your code. May be add same error handling to mysqli_prepare and others
I think the issue was the use of iid in the binding for the insert query. It should either be iis or iii presumably. You tried using try/catch blocks but to my mind did not make full use of them - the creation of a prepared statement should be tested to see if it succeeds or fails ~ the outcome of which can be used in the try/catch logic to indicate faults. Excuse the mix of procedural and OOP style code
<?php
if( $_SERVER['REQUEST_METHOD']=='POST' && isset( $_POST["gebruikersnaamOntvanger"], $_POST["idBetaler"], $_POST["bedrag"], $_POST["saldo"] ) ){
try{
$con = mysqli_connect(/This info is correct/) or die ("Unable to connect");
$gebruikersnaamOntvanger = $_POST["gebruikersnaamOntvanger"];
$idBetaler = $_POST["idBetaler"];
$bedrag = $_POST["bedrag"];
$saldoBetaler = $_POST["saldo"];
$response = array('success'=>false);
$stmt=$conn->prepare( 'select `idgebruiker`, `saldo` from `gebruikers` where `gebruikersnaam` = ?' );
if( !$stmt ) throw new Exception('unable to prepare select query');
else {
$stmt->bind_param( 's', $gebruikersnaamOntvanger );
$result=$stmt->execute();
if( !$result )throw new Exception('No results from select query');
else {
$stmt->store_result();
$stmt->bind_result( $idGebruiker, $Saldo );
while( $stmt->fetch() ){
$idOntvanger = $idGebruiker;
$saldoOntvanger = $Saldo;
}
$saldoOntvanger += $bedrag;
$saldoBetaler -= $bedrag;
$stmt=$con->prepare('insert into `transacties` ( `idbetaler`, `idontvanger`, `bedrag`, `datum`, `uitgevoerd` ) values(?, ?, ?, now(), 1)');
if( !$stmt )throw new Exception('Unable to prepare insert query');
else {
/* What is the value of $bedrag? integer, string?? */
/*
The binding iid was incorrect - perhaps iis or iii
*/
$stmt->bind_param('iis', $idBetaler, $idOntvanger, $bedrag );
$result = $stmt->execute();
$response['success']=$result;
}
}
}
echo json_encode( $response );
}catch( Exception $e ){
echo $e->getMessage();
}
}
?>
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I am trying to create a user registration and login system. My code is connecting to the database and form is feeding data but the statements does not execute. There are no error messages either.
public function reg_user($username, $email, $address, $pwd){
$pass = password_hash($pwd, PASSWORD_BCRYPT);
$check = $this->db->prepare('SELECT * FROM bakery_users WHERE u_mail = :u_mail');
$check->bindParam(':u_mail', $email, PDO::PARAM_STR);
$check->execute();
$count = $check->rowCount();
if($count < 0){
$reg = $db->prepare('INSERT INTO bakery_users (u_name, u_mail, u_add u_pass) VALUES (:u_name, :u_mail, :u_add, :u_pass)');
$reg->bindParam(':u_mail', $username,PDO::PARAM_STR);
$reg->bindParam(':u_mail', $email,PDO::PARAM_STR);
$reg->bindParam(':u_add', $address,PDO::PARAM_STR);
$reg->bindParam(':u_pass', $pass,PDO::PARAM_STR);
$reg->execute();
return true;
}else{
$db = null;
return false;
}
}
The main problem, I believe, lies in the sql statement - it is missing a comma between u_add and u_pass
$reg = $db->prepare('INSERT INTO bakery_users (u_name, u_mail, u_add, u_pass) VALUES (:u_name, :u_mail, :u_add, :u_pass)');
If you test the return value of prepare you can fork the logic dependant upon it's success/failure
if( $reg ){
$reg->bindParam(':u_mail', $username,PDO::PARAM_STR);
$reg->bindParam(':u_mail', $email,PDO::PARAM_STR);
$reg->bindParam(':u_add', $address,PDO::PARAM_STR);
$reg->bindParam(':u_pass', $pass,PDO::PARAM_STR);
$reg->execute();
return true;
} else {
exit('error');
}
You also have a misnamed parameter in the first bind statement
$reg->bindParam(':u_mail', $username,PDO::PARAM_STR);
should be
$reg->bindParam(':u_name', $username,PDO::PARAM_STR);
You can use a try/catch block to try to identify problems in a constructive manner like this
public function reg_user($username, $email, $address, $pwd){
try{
$pass = password_hash($pwd, PASSWORD_BCRYPT);
$check = $this->db->prepare('SELECT * FROM `bakery_users` WHERE `u_mail` = :u_mail');
if( !$check )throw new Exception('Failed to prepare SELECT query');
$check->bindParam(':u_mail', $email, PDO::PARAM_STR);
$check->execute();
$count = $check->rowCount();
if( $count < 0 ){
$reg = $db->prepare('INSERT INTO `bakery_users` (`u_name`, `u_mail`, `u_add`, `u_pass` ) VALUES ( :u_name, :u_mail, :u_add, :u_pass )');
if( $reg ){
$reg->bindParam(':u_name', $username,PDO::PARAM_STR);
$reg->bindParam(':u_mail', $email,PDO::PARAM_STR);
$reg->bindParam(':u_add', $address,PDO::PARAM_STR);
$reg->bindParam(':u_pass', $pass,PDO::PARAM_STR);
$reg->execute();
return true;
} else {
throw new Exception('Failed to prepare INSERT query')
}
} else{
$db = null;
return false;
}
}catch( Exception $e ){
exit( sprintf('An error "%s" on line %d of "%s"',$e->getMessage(),$e->getLine(),__METHOD__ ) );
}
}
I should have spotted sooner the use of if( $count < 0 ) ~ that should be if( $count==0 )
public function reg_user( $username=false, $email=false, $address=false, $pwd=false ){
try{
if( !( $username & $email & $address & $pwd ) ) throw new Exception('bad foo');
$sql='SELECT * FROM `bakery_users` WHERE `u_mail` = :u_mail';
$stmt = $this->db->prepare( $sql );
if( !$stmt ) throw new Exception('Failed to prepare SELECT query');
$args=array( ':u_mail' => $email );
$stmt->execute( $args );
$count = $stmt->rowCount();
if( $count == 0 ){
$sql='INSERT INTO `bakery_users` ( `u_name`, `u_mail`, `u_add`, `u_pass` ) VALUES ( :u_name, :u_mail, :u_add, :u_pass )';
$stmt = $db->prepare( $sql );
if( $stmt ){
$args=array(
':u_name' => $username,
':u_mail' => $email,
':u_add' => $address,
':u_pass' => password_hash( $pwd, PASSWORD_BCRYPT )
);
return $stmt->execute( $args );
} else {
throw new Exception('Failed to prepare INSERT query')
}
} else{
$db = null;
return false;
}
}catch( Exception $e ){
exit( sprintf( 'An error "%s" on line %d of "%s"', $e->getMessage(), $e->getLine(), __METHOD__ ) );
}
}
There are no error messages either
because you're using the wrong PDO error mode, you're using the default one, which, iirc, is called PDO::ERRMODE_SILENT
this is THE correct way to create a PDO object:
$db = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8mb4', 'username', 'password',
array(PDO::ATTR_EMULATE_PREPARES => false, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
and when you created yours, you forgot the PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION-part.
I'm a beginner in PHP programming.
I have an SP in SQL Server with input, output and ReturnValue parameters that returns data from an sample table.
CREATE PROCEDURE [dbo].[sp_PHP]
#in1 int, #in2 int, #out3 int OUTPUT
WITH EXEC AS CALLER
AS
SET #out3 = #in1 * #in2
SELECT * FROM PHP
RETURN #in1 + #in2
This is my PHP code
<?php
try
{
$conn = new PDO("sqlsrv:Server=xxxxx,1433;Database=xxxxxx", "xx", "xx");
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
}
catch (Exception $e)
{
die(print_r($e->getMessage()));
}
$query = '{? = CALL sp_PHP(?, ?, ?)}';
$stmt = $conn->prepare($query);
$returnVariable = -1;
$inputVariable1 = 18;
$inputVariable2 = 24;
$outputVariable3 = -1;
$stmt->bindParam(1,$returnVariable, PDO::PARAM_INT | PDO::PARAM_INPUT_OUTPUT, 100);
$stmt->bindParam(2,$inputVariable1, PDO::PARAM_INT);
$stmt->bindParam(3,$inputVariable2, PDO::PARAM_INT);
$stmt->bindParam(4,$outputVariable3, PDO::PARAM_INT | PDO::PARAM_INPUT_OUTPUT, 100);
$stmt->execute();
$results = $stmt->fetchAll(PDO::FETCH_BOTH);
foreach($results as $row) {
echo $row['PHP_ID'].' '.$row['PHP_Char'].'<br>';
}
echo '<hr>';
echo 'Return value: '.$returnVariable.'<br>';
echo 'Output parameter: '.$outputVariable3.'<br>';
?>
If I remove the line in the SP
SELECT * FROM PHP
and don't read the data received in PHP with following code
$results = $stmt->fetchAll(PDO::FETCH_BOTH);
foreach($results as $row) {
echo $row['PHP_ID'].' '.$row['PHP_Char'].'<br>';
}
I receive the correct values of $returnVariable (42) and $outputVariable3 (432).
But if I read (and show) the data read from the SP, $returnVariable and $outputVariable3 are equal to -1 (the assigned value)
I wanto to read output parameter, ReturnValue and data at the same time.
Is it possible? Where am I wrong?
Thanks!!
Solution:
The value of the output (or input/output) parameter is accessible when you consume all results returned by the stored procedure (PDO and not PDO versions). In your case you need to move throw resultsets with PDOStatement::nextRowset to get the values for the output parameters.
Example:
I've reproduced your example and next code works for me.
<?php
$server = 'server\instance,port';
$database = 'database';
$uid = 'user';
$pwd = 'password';
try {
$conn = new PDO("sqlsrv:server=$server;Database=$database", $uid, $pwd);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch( PDOException $e ) {
die( "Error connecting to SQL Server".$e->getMessage());
}
try {
$sql = "{? = CALL sp_PHP(?, ?, ?)}";
#$sql = "EXEC ? = sp_PHP(?, ?, ?)";
$stmt = $conn->prepare($sql);
$returnVariable = -1;
$inputVariable1 = 18;
$inputVariable2 = 24;
$outputVariable3 = -1;
$stmt->bindParam(1, $returnVariable, PDO::PARAM_INT | PDO::PARAM_INPUT_OUTPUT, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
$stmt->bindParam(2, $inputVariable1, PDO::PARAM_INT);
$stmt->bindParam(3, $inputVariable2, PDO::PARAM_INT);
$stmt->bindParam(4, $outputVariable3, PDO::PARAM_INT | PDO::PARAM_INPUT_OUTPUT, PDO::SQLSRV_PARAM_OUT_DEFAULT_SIZE);
$stmt->execute();
do {
echo 'Result set:'."<br>";
while ($row = $stmt->fetch( PDO::FETCH_ASSOC) ){
print_r($row)."<br>";
}
echo "<br>";
echo "<br>";
} while ($stmt->nextRowset());
} catch( PDOException $e ) {
die( "Error executing query" );
}
$stmt = null;
$conn = null;
echo 'Stored procedure return value: '.$returnVariable."</br>";
echo 'Stored procedure output parameter: '.$outputVariable3."</br>";
?>
What is the proper syntax for preparing a transactional statement in mysqli? I've tried a number closest I've come is:
$conn->begin_transaction();
$stmt = $conn->prepare("INSERT INTO ARCHIVE_CLICKS_PATH SELECT * FROM CLICKS_PATH WHERE REFERER = ?");
$stmt->bind_param('i', $referer);
$stmt = $conn->prepare("DELETE FROM CLICKS_PATH WHERE REFERER = ?;");
$stmt->bind_param('i', $referer);
$stmt->close();
$conn->commit();
Doesn't throw errors, also doesn't seem to do anything.
Edit: I searched \ read the answer posted above before posting, it doesn't help me at all with prepared mysqli statement syntax specifically (which seems to be the issue). There is no errors being thrown, and the statement works fine when I directly input it to the database. I can get it to work fine unprepared, but I can't find the proper syntax of where to bind_params \ execute \ commit for a mysqli prepared statement example anywhere.
To add the following works fine:
BEGIN;
INSERT INTO ARCHIVE_CLICKS_PATH SELECT * FROM CLICKS_PATH WHERE REFERER = 15;
DELETE FROM CLICKS_PATH WHERE REFERER = 15;
COMMIT;
When I directly input it into the database.
You are supposed to use try catch block to throw the exception. see the example below:
$sql1 = "INSERT INTO ARCHIVE_CLICKS_PATH SELECT * FROM CLICKS_PATH WHERE REFERER = ?;";
$sql2 = "DELETE FROM CLICKS_PATH WHERE REFERER = ?;";
$stmt1 = $conn->prepare($sql1);
$stmt2 = $conn->prepare($sql2);
try{
$conn->query('BEGIN;');
if($stmt1 == false || $stmt2 == false || $stmt1->bind_param("i", $b) == false || $stmt2->bind_param("i", $a) == false || $stmt1->execute() == false || $stmt2->execute() == false){
throw new Exception($conn->error);
}
else{
echo "successful";
}
$conn->query('COMMIT;');
}
catch(Exception $e){
$conn->query("ROLLBACK;");
echo $e->getMessage();
}
This is what I figured out to solve it based on the answer above in case it ever helps anyone:
try
{
$conn->autocommit(FALSE);
$conn->begin_transaction();
$stmt1=$conn->prepare("INSERT INTO ARCHIVE_CLICKS_PATH SELECT * FROM CLICKS_PATH WHERE REFERER = ?;");
$stmt1->bind_param('i',$referer);
if ($stmt1->execute() == false) {
throw new Exception('Statement 1 Failed');
}
$stmt2=$conn->prepare("DELETE FROM CLICKS_PATH WHERE REFERER = ?;");
$stmt2->bind_param('i', $referer);
if ($stmt2->execute() == false) {
throw new Exception('Statement 2 Failed');
}
$stmt1->close();
$stmt2->close();
$conn->commit();
}
catch(Exception $e)
{
$conn->rollback();
throw $e;
}
i want to insert into a table depending on the id of the session:
here the code in class.php:
public function activate($activation, $id,$change,$userID){
$stm1= $this->conn->prepare("INSERT INTO `log` (`date`,`change`) VALUES(CURRENT_TIMESTAMP(),'$change') WHERE `user_id` =$userID");
($stm1->execute());
$stmt = $this->conn->prepare("UPDATE `segments` SET `activation` = '$activation' WHERE `id` = '$id'")
or die($this->conn->error);
if ($stmt->execute()) {
$stmt->close();
$this->conn->close();
return TRUE;
}
}
at the top of the page i have this:
require './config.php';session_start();$userID = $_SESSION['user_id'];
and in action.php where the action go i have this:
$conn = new db_class();
$conn->activate($activation, $id,$change,$userID);
echo "Updated successfully.";
exit;
the first query insert into log is not working \ please help
This should be a comment but I don't have the rep yet...
Primarily, you don't do that type of insert with a WHERE clause. The insert will fail.
As an aside, that insert is open to sql injection. Bind your your parameters. Also, you should add error handling. If you had that, you would see the insert fails. Quick example (1 way...there are other ways...and I assumed $change is a string and $userId is an int...)
$sql = 'INSERT INTO log
SET `date` = CURRENT_TIMESTAMP(),
change = :change,
user_id = :user_id;';
$stmt = $this->conn->prepare( $sql );
$stmt->bindParam( ':change', $change, PDO::PARAM_STR );
$stmt->bindParam( ':user_id', $userID, PDO::PARAM_INT );
$result = $stmt->execute();
if (!$result) {
// failure -> get and handle the error
$error_array = $stmt->errorInfo();
} else {
// do something
}
The docs can help > pdo::execute, pdo::errorinfo
i have several database checks with PDO before i insert some values on the DB and i don't know if one try/catch will catch all errors in the nested PDO or if i need one try/catch for every PDO. This is the code i got now:
try {
$db = connect_db();
$q = "query foobar";
$stm = $db->prepare($q);
$stm->bindParam(1, $foobar);
$status = $stm->execute();
if ($stm->rowCount() == 0) {
if ($def == 0) {
$q = "query foobar";
$stm = $db->prepare($q);
$stm->bindParam(1, $foobar);
$stm->bindParam(2, $foobar);
$stm->bindParam(3, $foobar);
$stm->bindParam(4, $foobar);
$status = $stm->execute();
if ($status) {
echo "<script>alert('foobar');window.location.assign('admin.php');</script>";
} else {
echo "<script>alert('foobar');window.location.assign('admin.php');</script>";
die();
}
} else {
$q = "query foobar";
$stm = $db->prepare($q);
$stm->bindParam(1, $nombre);
$status = $stm->execute();
if ($stm->rowCount() == 0) {
$q = "query foobar";
$stm = $db->prepare($q);
$stm->bindParam(1, $foobar);
$stm->bindParam(2, $foobar);
$stm->bindParam(3, $foobar);
$stm->bindParam(4, $user);
$status = $stm->execute();
if ($status) {
echo "<script>alert('foobar.');window.location.assign('admin.php');</script>";
} else {
echo "<script>alert('foobar.');window.location.assign('admin.php');</script>";
die();
}
}
}
} else {
echo "<script>alert('foobar.'); history.back();</script>";
die();
}
} catch (Exception $e) {
// Proccess error
$msg = $e->getMessage();
$timestamp = date("Y-m-d H:i:s");
$line = $e->getLine();
$code = $e->getCode();
handle_error($msg, $timestamp, $line, $code);
die("foobar");
}
PDO::ERRMODE_EXCEPTION
In addition to setting the error code, PDO will throw a PDOException and set its properties to reflect the error code and error information. This setting is also useful during debugging, as it will effectively "blow up" the script at the point of the error, very quickly pointing a finger at potential problem areas in your code (remember: transactions are automatically rolled back if the exception causes the script to terminate).
Exception mode is also useful because you can structure your error handling more clearly than with traditional PHP-style warnings, and with less code/nesting than by running in silent mode and explicitly checking the return value of each database call.
So, one is enough