handling a error in mysql using php caused by ajax - php

I am submitting a form using ajax,
function ajax_post() {
// ...(code);
var hr = new XMLHttpRequest();
var url = "http://domain.com/submit_action.php";
var vars = "element_1=" + ln + "&element_2=" + fn;
hr.open("POST", url, true);
hr.send(vars);
// ...(code);
}
having the php exc the query:
$sql = 'SELECT *
FROM ' . table. '
WHERE ' . $db -> sql_build_array('SELECT', $data);
$result = $db -> sql_query($sql);
$sql = 'INSERT INTO ' . table. ' ' . $db -> sql_build_array('INSERT', $data);
$db -> sql_query($sql);
In my above code, it will run. But when the 'fn' and 'ln' are the same or already exist in the db, then there will be a error. But because im using ajax to submit it, I stay on the current page of the form without getting a error, without knowing if the query exc or not.
Question is, is there a way to have php tell ajax what kind of error occured during the exc of query? Thanks in advance.

anything echoed during your php script will be returned into the hr.responseXML and hr.responseText attributes.
Catch these 2 values within your hr.onreadystatechange callback, whenever the status is OK, to know what happened in your php.
hr.onreadystatechange = function() {
if (hr.readyState == 4 && (hr.status == 200)) {
//do something with hr.responseText
}
}
I personnaly systematically encapsulate my php answers inside a generic xml response, with a customized status: error/ok/business error, and a customized message, so I know what to do with it at the javascript layer.
In addition to this, I would suggest you catch the 1062 mysql error to know that the error is due to an already existing value, and raise a more user-friendly message.

Related

Data not being saved in DB via PHP form

I,ve trying to save some data in my DB, but it just don't save, no error thrown, i used the echo query_orcN; to see if the data that was input by the form is valid, and its all fine, the form can input up to 5 services ($servicoN), so the cod is kinda repetetive, as i am new with php and mySql, expect to see some newbie coding.
I also verified and the logic to choose what if statement will be used is working fine too, so i will post just the case with one service:
...
<?php
include('login/conexao.php');
$nome_cli = $_POST['nome_cli'];
$nome_orc = $_POST['nome_orc'];
$obs_trab = $_POST['obs_orc'];
$servico1 = $_POST['serv1'];
$obs_serv1 = $_POST['obs_serv1'];
$total1 = $_POST['total1'];
$servico2 = $_POST['serv2'];
$obs_serv2 = $_POST['obs_serv2'];
$total2 = $_POST['total2'];
$servico3 = $_POST['serv3'];
$obs_serv3 = $_POST['obs_serv3'];
$total3 = $_POST['total3'];
$servico4 = $_POST['serv4'];
$obs_serv4 = $_POST['obs_serv4'];
$total4 = $_POST['total4'];
$servico5 = $_POST['serv5'];
$obs_serv5 = $_POST['obs_serv5'];
$total5 = $_POST['total5'];
//um serviço
if($servico1 != '' && $servico2 == '' && $servico3 == '' && $servico4 == '' && $servico5 == ''){
$query_orc1 = "START TRANSACTION;
SET #cod_cli = (SELECT cod_cliente
FROM CLIENTE
WHERE nome_cliente = '$nome_cli');
INSERT INTO TRABALHO(nome_trabalho, cod_cliente, obs_trabalho, statuspag_trabalho)
VALUES ('$nome_orc', #cod_cli, '$obs_trab', 0);
SET #orc = LAST_INSERT_ID();
SET #cod_serv1 = (SELECT cod_servicos
FROM SERVICOS
WHERE descri_servicos = '$servico1');
INSERT INTO SERV_TRAB(cod_trabalho, cod_servicos, qtt_serv_trab, obs_serv_trab)
VALUES (#orc, #cod_serv1, $total1, '$obs_serv1');
COMMIT;";
if($resultado_query_orc1 = mysqli_multi_query($conexao, $query_orc1))
{
//echo $query_orc1;
header('Location: sucesso_orc.php');
exit();
}
else
{
echo "<h3>Falha </h3>".$valid;
echo $result_msg_cliente;
}}
...
I'm using myawardspace to host my project, and already set de engine of the tables to InnoDB as for what i,ve understood, it's one that can support the TRANSACTION.
Already thanks anyone in advance for any help and attention, its the first time a post a question here, hope it's well structered.
You have two problems.
PROBLEM 1: failure of the script to produce expected results (i.e., the question you asked).
PROBLEM 2: Lack of diagnostic information.
To solve problem 2, put the following three lines at the start of your script:
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
Running the script with this change might produce error messages that will lead to a solution for your script. If not, run simple php with a known error, such as:
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
echo '1' //no semi colon is an error
echo '2';
If this produces no error messages, it means there is something in the php or web server (such as Apache) configuration stopping them. Find error logs for php and and the web server (probably apache). Exact details for accessing logs are available myawardspace.
SOLVING PROBLEM 1 - Your Script
Whenever running sql through php, there are two major steps involved in getting it to work.
STEP 1: Verify the sql is valid.
The first shot at forming sql within a php script very often contains errors. That means an important milestone in the development of every php script interacting with a database is verifying the sql outside php. An easy way to do this is to put the following statement immediately after setting the value of query_orc1:
echo query_orc1;
exit;
This will put onto your screen the sql the script is attempting to running. Use copy/paste to run the sql using phpmyadmin or whatever interface you have for your database. If there are problems with the sql, you will see them here. If the sql runs as expected, then you know the part of your script creating the sql is working.
STEP 2: Fix php errors that are failing to submit sql correctly to the database.
Maybe someone can spot errors in this script without benefit of error messages. That is fantastic if someone can provide you that information. I would focus on getting your system to show you error message before trying to troubleshoot the php.
I have no experience with mysqli, therefore I use PDO.
At first: Maybe you should overthink the first part with servico1 to servico5. There is maybe a better solution.
My Changes:
Switch from mysqli to PDO
add prepare statements
replace two statements with subselects
I hope I have commented on every change.
The altered Code:
<?php
include('login/conexao.php');
// Build an PDO Instance (Documentation: https://www.php.net/manual/en/book.pdo.php)
// $db = new PDO("mysql:host=localhost;dbname=test;charset=UTF8", "username", "password", [
// PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
// ]);
$nome_cli = $_POST['nome_cli'];
$nome_orc = $_POST['nome_orc'];
$obs_trab = $_POST['obs_orc'];
$servico1 = $_POST['serv1'];
$obs_serv1 = $_POST['obs_serv1'];
$total1 = $_POST['total1'];
$servico2 = $_POST['serv2'];
$obs_serv2 = $_POST['obs_serv2'];
$total2 = $_POST['total2'];
$servico3 = $_POST['serv3'];
$obs_serv3 = $_POST['obs_serv3'];
$total3 = $_POST['total3'];
$servico4 = $_POST['serv4'];
$obs_serv4 = $_POST['obs_serv4'];
$total4 = $_POST['total4'];
$servico5 = $_POST['serv5'];
$obs_serv5 = $_POST['obs_serv5'];
$total5 = $_POST['total5'];
// switch from
// ($servico1 != '') to !empty($servico1)
// optional, if you like the syntax more, you could use: ($servico1 !== '')
// tripple equals or !== prevents type juggeling
// #see https://www.php.net/manual/en/language.types.type-juggling.php
if (!empty($servico1) && empty($servico2) && empty($servico3) && empty($servico4) && empty($servico5)) {
// Prepared statment to prevent sqlinjection
$stmt = $db->prepare("INSERT INTO TRABALHO (
nome_trabalho,
cod_cliente,
obs_trabalho,
statuspag_trabalho
) VALUES (
:nome_orc,
(SELECT cod_cliente FROM CLIENTE WHERE nome_cliente = :nome_cli ), -- with subselects we can remove unnecessary sql statments
:obs_trab,
0
)
");
try {
// Execute the query and bind the named paraments
// All variables a treated as string
$stmt->execute([
'nome_orc' => $nome_orc,
'nome_cli' => $nome_cli,
'obs_trab' => $obs_trab
]);
} catch (Exception $e) {
// #todo handle exception
echo $e->getMessage();
exit;
}
$stmt = $db->prepare("INSERT INTO SERV_TRAB (
cod_trabalho,
cod_servicos,
qtt_serv_trab,
obs_serv_trab
) VALUES (
:orc,
(SELECT cod_servicos FROM SERVICOS WHERE descri_servicos = :servico1),
$total1,
:obs_serv1
)
");
try {
// get last inserted id with pdo: $db->lastInsertId()
$stmt->execute([
'orc' => $db->lastInsertId(),
'servico1' => $servico1,
'obs_serv1' => $obs_serv1
]);
} catch (Exception $e) {
// #todo handle exception
echo $e->getMessage();
exit;
}
// we don't need an if at this point because if an error occures it will throw an exception
// and the try / catch will catch and handle it
header('Location: sucesso_orc.php');
exit;
}

Query isn't inserting into database [duplicate]

This question already has answers here:
Can I mix MySQL APIs in PHP?
(4 answers)
Closed 6 years ago.
I am attempting to implement a click count system. I am using the following code in this link Click here to see code, but changing it to modern standards. Initially I received errors for the msqli_real_escape_ string, but I believed I resolved it(no errors). Now, I am not receiving any errors at all, but the query is not sending into my database. I am using ini_set('display_errors', 1);
error_reporting(E_ALL); for error checking. Also I have my $con and session in and ini file that I call, so the session and connection are not issues.
Does anyone see what I am doing wrong or is there a good way I can check to see what isn't working?
//create current page constant
$curPage = mysqli_real_escape_string($con,htmlspecialchars($_SERVER['PHP_SELF']));
//set number of clicks variable to 0
$clicks = 0;
//do not recount if page currently loaded
if($_SESSION['page'] != $curPage) {
//set current page as session variable
$_SESSION['page'] = $curPage;
$click_sql = "
SELECT *
FROM click_count
WHERE page_url = ?
";
if (!$click_stmt = $con->prepare($click_sql)) {
$click_stmt->bind_param("s", $curPage);
$click_stmt->execute();
$num_rows = $click_stmt->fetchColumn();
if (!$click_stmt->errno) {
// Handle error here
}
$stmt->bind_result($click_id, $page_url, $page_count);
} elseif ($num_rows == 0) {
//try to create new record and set count for new page to 1
//output error message if problem encountered
$click_insert_stmt = "
INSERT INTO click_count
(page_url, page_count)
VALUES(?, ?)";
if(!$click_stmt = $con->prepare($click_insert_stmt)) {
$click_insert_stmt->execute(array('$curPage',1));
echo "Could not create new click counter.";
}
else {
$clicks= 1;
}
} else {
//get number of clicks for page and add 1 fetch(PDO::FETCH_BOTH)
while($click_row = $click_insert_stmt->fetch(PDO::FETCH_BOTH)) {
$clicks = $row['page_count'] + 1;
//update click count in database;
//report error if not updated
$click_update_stmt = "
UPDATE click_count
SET page_count = ?
WHERE page_url = ?
";
if(!$click_stmt = $con->prepare("$click_update_stmt")) {
$click_update_stmt->execute(array('$clicks', '$curPage'));
echo "Could not save new click count for this page.";
}
}
}
}
Edit: New Updated Code
// ********Page count************
//create current page constant
$curPage = mysqli_real_escape_string($con,($_SERVER['PHP_SELF']));
//set number of clicks variable to 0
$clicks = 0;
//do not recount if page currently loaded
if($_SESSION['page'] != $curPage) {
//set current page as session variable
$_SESSION['page'] = $curPage;
$click_sql = "
SELECT *
FROM click_count
WHERE page_url = ?
";
if (!$click_stmt = $con->prepare($click_sql)) {
$click_stmt->bind_param("s", $_SERVER['PHP_SELF']);
$click_stmt->execute();
$num_rows = $click_stmt->fetchColumn();
if (!$click_stmt->errno) {
// Handle error here
}
$stmt->bind_result($click_id, $page_url, $page_count);
} elseif ($num_rows == 0) {
//try to create new record and set count for new page to 1
//output error message if problem encountered
$click_insert_stmt = "
INSERT INTO click_count
(page_url, page_count)
VALUES(?, ?)";
if(!$click_stmt = $con->prepare($click_insert_stmt)) {
$click_insert_stmt->execute(array($curPage,1));
echo "Could not create new click counter.";
}
else {
$clicks= 1;
}
} else {
//get number of clicks for page and add 1 fetch(PDO::FETCH_BOTH)
while($click_row = $click_insert_stmt->fetch(PDO::FETCH_BOTH)) {
$clicks = $row['page_count'] + 1;
//update click count in database;
//report error if not updated
$click_update_stmt = "
UPDATE click_count
SET page_count=page_count+1
WHERE page_url = ?
";
if(!$click_stmt = $con->prepare("$click_update_stmt")) {
$click_update_stmt->execute(array($curPage));
echo "Could not save new click count for this page.";
}
}
}
}
It looks like you're doing a lot of stuff like this:
$click_update_stmt->execute(array('$clicks', '$curPage'));
I'm not sure where you picked up this habit of quoting variables as strings, but you need to drop it. '$x' and $x are two hugely different things. In the first case it's literally '$x' and in the second case it's whatever the $x variable happens to represent.
Fix it like this:
$click_update_stmt->execute(array($clicks, $curPage));
Also since you're using prepared statements, which by the way is great, you do not need to and should not manually escape your values. Applying them to placeholders with bind_param is the safe way of doing it. Doing any other escaping mangles the data.
Just bind directly to the source:
$click_stmt->bind_param("s", $_SERVER['PHP_SELF']);
Don't arbitrarily run things like htmlspecialchars on input out of paranoia or because you're doing cargo-cult programming and you saw it done in a YouTube tutorial somewhere. That function is intended to be used to display values only, not store them. Data in your database should be as raw as possible.
There's a lot of problems with this code, and one of them that has me confused is why there's so much code. Remember SELECT * and then binding results to arbitrary variables is trouble, your schema might change and then your code is out of sync. Whenever possible fetch rows as an associative array if doing this, then all you have to worry about is renamed ore removed columns.
The biggest problem is this is subject to race conditions because it doesn't use an atomic increment. When writing counters, always do your updates as operations that are a single statement:
UPDATE click_count SET page_count=page_count+1 WHERE page_url=?
Your approach of reading the count, incrementing it, and then writing it back into the database means that you're inviting problems if another operation runs concurrently, something very likely on click-counter code.

Keep getting logged out after updating the database in PHP

I recently posted a question about deleting multiple rows in the database and basically re-used the code to update multiple rows in the database, but now I am having issue once the database has been updated and the page refreshes it keeps loggin me out an I'm not sure why.
Here is the ajax:
function editUser(){
var url = 'edit-user.php';
var ids = document.getElementById("edit-user-id").value;
var role = document.getElementById("role").value;
var status = document.getElementById("accountStatus").value;
var data = 'userID=' + ids.toString() + '&role=' + role + '&status=' + status;
$.ajax({
url: url,
data: data,
cache: false,
error: function(e){
alert(e);
},
success: function () {
var selects = $('#users-table').bootstrapTable('getSelections');
ids = $.map(selects, function (row) {
return row.id;
});
$('#users-table').bootstrapTable('refresh', {
silent: true
});
location.reload();
}
});
}
And here is the PHP:
require("../config.php");
try{
$role = $_GET['role'];
$status = $_GET['status'];
$ids = array($_GET['userID']);
$inQuery = implode(',', $ids);
$query = 'UPDATE users SET role = :role, account_status = :status WHERE user_id IN ('.$inQuery.')';
$query_params = array(
':role' => $role,
':status' => $status
);
$stmt = $db->prepare($query);
$stmt->execute($query_params);
// Set variable message of affected rows
$count = $stmt->rowCount();
$user_updated = ''.$count.' user(s) updated successfully.';
$_SESSION['user_updated'] = $user_updated;
} catch (Exception $e){
$error = '<strong>The following error occured:</strong>'.$e->getMessage();
$_SESSION['error'] = $error;
}
I tried changing cache: true, but that didn't work. Again, I do not want to be logged out. Any ideas what I am doing wrong?
EDIT: I have narrowed it down to only happen when the page refreshes. I removed this piece of code location.reload(); from the ajax call and it does not redirect me back to the login page, but if i hit F5 or click refresh it logs me out.
This is too long for a comment:
Nothing is jumping out at me that would cause you to lose what is set in the $_SESSION['user']. Try dumping $_SESSION on each page just to keep track of it and disable the redirect for now (just put an error message or something). You can dump the array like so:
print_r($_SESSION);
Do you also know your prepared statement is broken? I don't see the point of the array or the implode for $ids and $inQuery. It should be something like:
$stmt = $db->prepare(
'UPDATE users
SET role = ?, account_status = ?
WHERE user_id = ?'
);
$stmt->execute(array($_GET['role'], $_GET['status'], $_GET['userID']));
There is no point in using IN if you only have one entry. You also aren't protecting your query from anything because you are still inserting the values into the prepare statement.
It appears that I needed to move session_start() to the top of the config.php file to make sure that it is the very first thing called on the page. Everything seems to be working ok right now.

Zend|Db\Sql|Expression not working in Zend SL statement

I cannot get valid data from the Zend Framework sql statements shown below which I use in php and is called from an angularjs script:
$where = new Where ();
$where->greaterThanOrEqualTo('user_id', '963');
$resultSet = $this->tableGateway->select(function(Select $select) use
($where){
$select->where($where);
$select->columns(array('date_added','datemonth' => new \Zend\Db\Sql\Expression("MONTH('date_added')"), 'count' => new \Zend\Db\Sql\Expression("COUNT(*)")));
$select->group('datemonth');
return $resultSet;
My angular js script dumps the data as shown below:
success(function(response) {
for(var i in response.response) {
var tc = response.response[i];
alert("userdata date_added=" + tc['date_added'] + " datemonth=" + tc['datemonth'] + " count=" + tc["count"]);
}
And the results are as shown:
userdata date_added=2014-05-22 20:00:27 datemonth=undefined count=undefined
Can anyone tell me if I am using the Zend\Db\Sql\Expression incorrectly or why isn't the datemonth and count not coming back correctly? I want to be able to get the number of records by month.
Update: I was able to dump the putput from the server and it shows all the fields on the database record but none for the fields created in the Zend Expression functions for datemonth and count. Below is the dump. Anyone know why the Expression fields aren't in the dump?
Php Code:
echo "Resultset = " . $resultSet->date_added;
Dump of above code:
Resultset = {"success":true,"response":[{"inputFilter":null,"user_id":0,"instagram_user_id":"","fbid":"","instagram_username":null, "full_name":"","profile_image":"","bio":"","website":"","media_count":0,"following_count":0,"followed_by_count":0,"like_count":0,"recommend_count":0,"date_added":"2014-05-22 20:00:27","flag_count":0,"date_updated":"","email":"","password":"","access_token":"","premium":0,"login_attempts":0,"status":0,"request_count":0,"request_date":""}]}
You may try this to preview your SQL query:
$sql = new \Zend\Db\Sql\Sql($this->tableGateway->adapter);
echo $sql->getSqlStringForSqlObject($select);

Error passing variable from AJAX to PHP for MySQL query

I am getting an error when trying to pass a variable from AJAX to PHP for a MySQL query. I have tried hardcoding to make sure that the query works and it does, but when I try to dynamically pass the variable it is telling me the following "Error: Unknown column '$searchid' in 'where clause'". I am trying to send the value of a dropdown box to ajax to pull back data from a MySQL database. The returned data will then be put into 2 text boxes to be edited. Note: I am trying not to use the jQuery framework for this so I can get a better understanding of what the AJAX is actually doing.
AJAX code
function ajax_post(){
var request = new XMLHttpRequest();
var id = document.getElementById("editorginfo").value;
request.open("POST", "parse.php", true);
request.setRequestHeader("Content-Type", "x-www-form-urlencoded");
request.onreadystatechange = function () {
if(request.readyState == 4 && request.status == 200) {
var return_data = request.responseText;
alert (return_data);
document.getElementById("orgeditname").value = return_data;
document.getElementById("orgeditphone").value = return_data;
}
}
request.send("id="+id);
}
PHP Parse code
<?php
include_once('../php_includes/db_connect.php');
$searchid = $_POST['id'];
$sql = 'SELECT * FROM orginfo WHERE id = $searchid';
$user_query = mysqli_query($db_connect, $sql) or die("Error: ".mysqli_error($db_connect));
while ($row = mysqli_fetch_array($user_query, MYSQLI_ASSOC)) {
$orgid = $row["id"];
$orgname = $row["orgname"];
$orgphone = $row["orgphone"];
echo $orgname, $orgphone;
}
?>
It's been a while since I have had time to work with code so I believe everything I used is still relevant. Also I know I havent put any sanitizing in yet, I wanted to make sure I can get the function working first, and I am the only one with access currently.
Thanks in advance for any help.
To solve your immediate issue, you'll want to change this:
$sql = 'SELECT * FROM orginfo WHERE id = $searchid';
Into this:
$sql = "SELECT * FROM orginfo WHERE id = $searchid";
Since your string is in single quotes, it is literally passing the string '$searchid' into the query rather than the value of $searchid.

Categories