Why am I getting "Query was empty" here? - php

Relevant code:
add_action( 'wp_ajax_proj_update', 'proj_update' );
function proj_update ( )
{
$id = $_POST['id'];
$compname = $_POST['compname'];
$projname = $_POST['projname'];
$imageurl = $_POST['imageurl'];
$sumsmall = $_POST['sumsmall'];
$sumfull = $_POST['sumfull'];
$results = $_POST['results'];
$caseid = (!isset($_POST['caseid']) || strcmp($_POST['caseid'],'none')) ? $_POST['caseid'] : "NULL"; // weirdness required to get the value of our <select name="caseid"> element converted to something we can insert to database
$hide = array_key_exists('hide',$_POST) !== false ? 1 : 0; // weirdness required to get the value of <input type="checkbox" name="hide"> converted to something we can insert to database
$thisAction = $_POST['thisAction'];
global $wpdb;
$message = "";
switch ($thisAction)
{
case 'add':
{
/* Note: Have to break up prepare statement because https://core.trac.wordpress.org/ticket/12819 */
$addQuery = $wpdb->prepare("INSERT INTO projs (compname,projname,imageurl,sumsmall,sumfull,results,caseid,hide) VALUES (%s,%s,%s,%s,%s,%s,%d," . $caseid . ",%d)",
array($compname, $projname,$imageurl,$sumsmall,$sumfull,$results,$hide));
$message .= $wpdb->query($addQuery)
? 'Successfully added project to the database.'
: 'Error occurred when trying to add project to database: ' . $wpdb->last_error;
break;
}
For some reason, $wpdb->last_error is turning out to be Query was empty, and I can't figure out why. I've looked at other S.O. posts on this topic and they say that an undefined object is being used as the query, but here I'm using $addQuery as the query and I don't see any reason why it is not defined.
Any ideas?

Try using $wpdb->insert instead of $wpdb->query to do an insert into the database.
More information regarding the use of $wpdb can be found here:
https://codex.wordpress.org/Class_Reference/wpdb

The call to ->prepare is failing because you have an error on your query. You have got 8 columns and 8 placeholders plus $caseid that is manually added, and the array you pass to the function contains 7 elements.
You probably have one exceeding %s.

Related

SQL INSERT function with PHP only

edit I changed the code to the suggestion answer, all snippets now updated
currently I am playing around with PHP. Therefore I am trying to build a programm which can execute SQL commands. so, what I am trying is to write some functions which will execute the query. But I came to a point where I coundn't help myself out. My trouble is, for the INSERT INTO command, I want to give an array, containing the Data that shall be inserted but I simply can't figure out how to do this.
Here is what I got and what I think is relevant for this operation
First, the function I want to create
public function actionInsert($data_values = array())
{
$db = $this->openDB();
if ($db) {
$fields = '';
$fields_value = '';
foreach ($data_values as $columnName => $columnValue) {
if ($fields != '') {
$fields .= ',';
$fields_value .= ',';
}
$fields .= $columnName;
$fields_value .= $columnValue;
}
$sqlInsert = 'INSERT INTO ' . $this->tabelle . ' (' . $fields . ') VALUES (' . $fields_value . ')';
$result = $db->query($sqlInsert);
echo $sqlInsert;
if ($result) {
echo "success";
} else {
echo "failed";
}
}
}
and this is how I fil the values
<?php
require_once 'funktionen.php';
$adresse = new \DB\Adressen();
$adresse->actionInsert(array('nachname'=>'hallo', 'vorname'=>'du'));
My result
INSERT INTO adressen (nachname,vorname) VALUES (hallo,du)failed
What I wish to see
success
and of course the freshly insertet values in the database
There are a few things to consider when you are working with relational databases without using PDO:
What is the database that you are using.
It's your decision to choose from MySQL, postgreSQL, SQLite and etc., but different DBs generally have different syntax for inserting and selecting data, as well as other operations. Also, you may need different classes and functions to interact with them.
That being said, did you checkout the official manual of PHP? For example, An overview of a PHP application that needs to interact with a MySQL database.
What is the GOAL you are trying to accomplish?
It's helpful to construct your SQL first before you are messing around with actual codes. Check if your SQL syntax is correct. If you can run your SQL in your database, then you can try to implement your code next.
What's the right way to form an SQL query in your code?
It's okay to mess around in your local development environment, but you should definitely learn how to use prepared statements to prevent possible SQL injection attacks.
Also learn more about arrays in PHP: Arrays in PHP. You can use key-value pairs in a foreach loop:
foreach ($keyed_array as $key => $value) {
//use your key and value here
}
You don't need to construct your query in the loop itself. You are only using the loop to construct the query fields string and VALUES string. Be very careful when you are constructing the VALUES list because your fields can have different types, and you should add double quotes around string field values. And YES, you will go through all these troubles when you are doing things "manually". If you are using query parameters or PDO or any other advanced driver, it could be much easier.
After that, you can just concatenate the values to form your SQL query.
Once you get more familiar with the language itself and the database you are playing with, you'll definitely feel more comfortable. Good luck!
Is this inside of a class? I assume the tabelle property is set correctly.
That said, you should correct the foreach loop, that's not used correctly:
public function actionInsert($data_values) //$data_values should be an array
{
$db = $this->openDB();
if ($db) {
foreach ($data_values as $data){
// $data_values could be a bidimensional array, like
// [
// [field1=> value1, field2 => value2, field3 => value3],
// [field1=> value4, field2 => value5, field3 => value6],
// [field1=> value7, field2 => value8, field3 => value9],
// ]
$fields = Array();
$values = Array();
foreach($data as $key => $value){
array_push($fields,$key);
array_push($values,"'$value'");
}
$sqlInsert = 'INSERT INTO ' . $this->tabelle . ' (' . join(',',$fields) . ') VALUES (' . join(',',$values) . ')';
$result = $db->query($sqlInsert);
echo $sqlInsert;
if ($result) {
echo "success";
} else {
echo "failed";
}
}
}
This is a rather basic approach, in which you cycle through you data and do a query for every row, but it isn't very performant if you have big datasets.
Another approach would be to do everything at once, by mounting the query in the loop and sending it later (note that the starting array is different):
public function actionInsert($data_values) //$data_values should be an array
{
$db = $this->openDB();
if ($db) {
$vals = Array();
foreach ($data_values['values'] as $data){
// $data_values could be an associative array, like
// [
// fields => ['field1','field2','field3'],
// values => [
// [value1,value2,value3],
// [value4,value5,value6],
// [value7,value8,value9]
// ]
// ]
array_push('('.join(',',"'$data'").')',$vals);
}
$sqlInsert = 'INSERT INTO ' . $this->tabelle . ' (' . join(',',$data_values['fields']) . ') VALUES '.join(' , ',$vals);
$result = $db->query($sqlInsert);
echo $sqlInsert;
if ($result) {
echo "success";
} else {
echo "failed";
}
}
By the way dragonthought is right, you should do some kind of sanitizing for good practice even if you don't make it public.
Thanks to #Eagle L's answer, I figured a way that finally works. It is diffrent from what I tryed first, but if anyone having similar troubles, I hope this helps him out.
//get the Values you need to insert as required parameters
public function actionInsert($nachname, $vorname, $plz, $wohnort, $strasse)
{
//database connection
$db = $this->openDB();
if ($db) {
//use a prepared statement
$insert = $db->prepare("INSERT INTO adressen (nachname, vorname, plz, wohnort, strasse) VALUES(?,?,?,?,?)");
//fill the Values
$insert->bind_param('ssiss', $nachname, $vorname, $plz, $wohnort, $strasse);
//but only if every Value is defined to avoid NULL fields in the Database
if ($vorname && $nachname && $plz && $wohnort && $strasse) {
edited
$inserted = $insert->execute(); //added $inserted
//this is still clumsy and user unfriendly but serves my needs
if ($inserted) {//changed $insert->execute() to $inserted
echo 'success';
} else {
echo 'failed' . $inserted->error;
}
}
}
}
and the Function call
<?php
require_once 'funktionen.php';
$adresse = new \DB\Adressen();
$adresse->actionInsert('valueWillBe$nachname', 'valueWillBe$vorname', 'valueWillBe$plz', 'valueWillBe$wohnort', '$valueWillBe$strasse');

Execute Success but num_rows return 0 [PHP-MySQL] [duplicate]

This question already has answers here:
How to test if a MySQL query was successful in modifying database table data?
(5 answers)
Closed 1 year ago.
The problem I just got is,
the $update_stmt->execute() is ok, and data in database already update
but, $update_resultrow = $update_stmt->num_rows; return 0 ?
I tried to copy MySQL command to run in query and it also worked well, like this:
UPDATE ACCOUNT_EMPLOYEE SET NAME = 'cccccc' WHERE ID = 1
Problem's Code here:
$update_sql = "UPDATE ACCOUNT_EMPLOYEE SET NAME = ? WHERE ID = ?";
if ($update_stmt = $conn -> prepare($update_sql)) {
if ($update_stmt->bind_param("si",
$newname,
$acc_id
)
) {
if ($update_stmt->execute()) {
// must declare here to be able to get num_rows
$update_stmt->store_result();
$update_resultrow = $update_stmt->num_rows;
if ($update_resultrow == 0) {
echo $error_forgot_noresult . '????' . $acc_id ;
$update_stmt->close();
$conn->close();
exit();
}
}
}
}
Yes, Fred -ii-, I never noticed that it has ->affected_rows. please post as answer, and I will marked it here
As per OP's request.
Seeing that the goal here is to test if the query was indeed successful, you need to use affected_rows.
As per the manual http://php.net/manual/en/mysqli.affected-rows.php
printf("Affected rows (UPDATE): %d\n", $mysqli->affected_rows);
Object oriented style
int $mysqli->affected_rows;
Sidenote:
Using
$update_resultrow = $update_stmt->num_rows;
and checking for errors, would have thrown an error, rather than "return 0".
http://php.net/manual/en/mysqli.error.php
Try to find the number of rows affected by your query instead of finding number of rows as below:
$update_sql = "UPDATE ACCOUNT_EMPLOYEE SET NAME = ? WHERE ID = ?";
if ($update_stmt = $conn -> prepare($update_sql)) {
if ($update_stmt->bind_param("si",
$newname,
$acc_id
)
) {
if ($update_stmt->execute()) {
// must declare here to be able to get num_rows
$update_stmt->store_result();
$update_resultrow = $update_stmt->affected_rows;
if ($update_resultrow == 0) {
echo $error_forgot_noresult . '????' . $acc_id ;
$update_stmt->close();
$conn->close();
exit();
}
}
}
}

PHP Query Script - Check empty variable before querying

I have php script which receives many variables from JavaScript search form. The thing is some of these variable could be empty so I have to check each one before querying it. e.g: user could enter the name and id of student and leave the gender field empty, so how I supposed to write the query? I've read that I might need use append but I have no idea how to do that. Any other better idea ?
piece of script:
$name = ($_GET['name']);
$id = ($_GET['id']);
$gender = ($_GET['gender']);
(!$con) {
throw new Exception("Error in connection to DB");
}
$query ="SELECT grade FROM students WHERE name ILIKE '%$name%' ";
$result = pg_query($query);
EDIT
Okay if I use empty and isset functions, then I have to check every variable and write new query? How can I update the original query after checking ?
With PHP you can use empty and isset as such:
if (!isset($_GET['name']) || empty($_GET['name'])) {
// Error detection, this field isn't available
}
Please note that isset is actually redundant in this example, as empty will return false if it is not set.
Documentation can be found here and here
empty ( )
Determine whether a variable is empty :
http://php.net/manual/en/function.empty.php
isset ( )
Determine if a variable is set and is not NULL :
http://php.net/manual/en/function.isset.php
You can just check the variable content like this:
if (!empty($_GET['name'])) {
// make your query
}
Think outside the box.
<?php
$first = TRUE;
$var_names = array('name', 'age', 'gender');
$query = "SELECT * FROM table WHERE"
foreach( $_GET as $key => $value ) {
if( in_array($key, $var_names) && !empty($_GET[$key]) ) {
if( $first ) {
$query .= sprintf(" %s = '%s'", $key, $value);
$first = FALSE;
} else {
$query .= sprintf(" AND %s = '%s'", $key, $value);
}
}
}
if( $first ) { die('no parameters given, query will error out.'); }
echo $query;
This is also terribly insecure for SQL injection, but I'm not going to implement parameterized queries here.

SImple Query Error

I'm running a function that checks whether or not an user has already submitted a question. I've narrowed the problem down to my function which runs a query code. For some reason it is not working. The function does work when the part that involved AND user_requester... is not there. I'm sure it's some sort of syntax error but I don't get a response from the error reporting. Here is the code below:
function question_exists ($question, $user_id) {
$question = sanitize($question);
$query = mysql_query("SELECT COUNT(`primary_id`) FROM `requests` WHERE
`question_asked`= '$question' AND `user_requester` = $user_id");
return (mysql_result($query, 0) == 1) ? true : false;
}
Clarification: I want to prevent an user from submitting the same question twice. That is the purpose of adding the AND section to the where clause in the query. When I do add the AND section, everything goes to pieces and the user can submit the same question anyways.
I would try doing all steps separately so you can test the result of each operation individually. Your return line is handling a lot of things and so it's hard to tell where you problem is. Something like this...
function question_exists( $question, $user_id )
{
$question = sanitize( $question );
$user_id = (int) $user_id; // additional sanitization in case you didn't do it already.
$sql = "SELECT COUNT(`primary_id`) FROM `requests` WHERE
`question_asked`= '$question' AND `user_requester` = $user_id";
$result = mysql_query( $sql );
if ( !$result ) {
// Note: this would be better sent to an error handling function, this is just for simplicity's sake.
echo 'Mysql query error: ' . mysql_error();
exit;
}
$row = mysql_fetch_row ( $result );
if ( $row ) {
return true;
} else {
// temporary debug code
echo "unknown error</ br>\n";
echo "sql: " . $sql . "</ br>\n";
echo "<pre>";
var_dump( $row );
echo "</pre>";
exit();
// real code for after problem is solved
return false;
}
}
If this still doesn't help and you haven't already, dump your $question and $user_id vars to make sure that you are receiving them and your sanitize function isn't doing something incorrectly. Note, I have not run this code so there may be syntax errors.
What kind of error reporting are you referring to? A query failing will not trigger any PHP errors/warnings. You'd need somethign like
$query = mysql_query(...) or die(mysql_error());
to see what really happened.
$query = mysql_query("SELECT COUNT(`primary_id`) FROM `requests` WHERE
`question_asked`= '$question' AND `user_requester` = {$user_id}");
Add curly braces to your variable in the query.

I don't understand how "?" is being used here

So, I have this PHP code:
$tabid = getTabid($module);
if($tabid==9)
$tabid="9,16";
$sql = "select * from field ";
$sql.= " where field.tabid in(?) and";
Now, how exactly does the ? work here? I vaguely understand that in PHP, ?: is a ternary operator, but the colon isn't being used here, and ? is part of a Postgresql query anyway.
The final query looks a bit like this:
select * from field where field.tabid in('9,16')
So, the question mark is replaced by the contents of $tabid, how does that happen?
The issue is that ('9,16') is not accepted by Postgres as an integer, it needs to be written like (9,16), so how do I do that? How do I remove the apostrophes?
Thanks a lot for the help, have a good day!
edit: More code was requested:
$sql.= " field.displaytype in (1,2,3) and field.presence in (0,2)";
followed by if statements, I think this is the relevant one:
if($tabid == 9 || $tabid==16)
{
$sql.= " and field.fieldname not in('notime','duration_minutes','duration_hours')";
}
$sql.= " group by field.fieldlabel order by block,sequence";
$params = array($tabid);
//Running the query.
$result = $adb->pquery($sql, $params);
Oh, I think I see now, I think it is a place holder, a part of the pquery function:
function pquery($sql, $params, $dieOnError=false, $msg='') {
Stuff
$sql = $this->convert2Sql($sql, $params);
}
Now, this is where it seems to get fun, here's part of the convert2Sql function:
function convert2Sql($ps, $vals) {
for($index = 0; $index < count($vals); $index++) {
if(is_string($vals[$index])) {
if($vals[$index] == '') {
$vals[$index] = "NULL";
}
else {
$vals[$index] = "'".$this->sql_escape_string($vals[$index]). "'";
}
}
}
$sql = preg_replace_callback("/('[^']*')|(\"[^\"]*\")|([?])/", array(new PreparedQMark2SqlValue($vals),"call"), $ps);
return $sql;
}
The problem I think lies in the
$vals[$index] = "'".$this->sql_escape_string($vals[$index]). "'"; line.
The sql_escape_string($str) function just returns pg_escape_string($str).
Sorry for the super long edit, but I still haven't been able to get past I am afraid, thanks for all the help!
Edit 2: I fixed the problem, all it took was changin $tabid = "9,16" to $tabid = array(9,16). I have no idea why, oh and I also had to remove the group by statement because Postgresql requires every field to be placed in that statement.
it is a positional parameter for a prepared statement
See: http://php.net/manual/en/function.pg-prepare.php
You don't actually 'remove' the quotes, you have to pass SQL array of ints instead of a string value into the parameter when doing pg_execute
An example:
// Assume that $values[] is an array containing the values you are interested in.
$values = array(1, 4, 5, 8);
// To select a variable number of arguments using pg_query() you can use:
$valuelist = implode(', ', $values);
// You may therefore assume that the following will work.
$query = 'SELECT * FROM table1 WHERE col1 IN ($1)';
$result = pg_query_params($query, array($valuelist))
or die(pg_last_error());
// Produces error message: 'ERROR: invalid input syntax for integer'
// It only works when a SINGLE value specified.
Instead you must use the following approach:
$valuelist = '{' . implode(', ', $values . '}'
$query = 'SELECT * FROM table1 WHERE col1 = ANY ($1)';
$result = pg_query_params($query, array($valuelist));

Categories