PDO - SQL not working without any warning [duplicate] - php

This question already has answers here:
Why does this PDO statement silently fail?
(2 answers)
Closed 6 years ago.
I wrote a function to insert what i want in any database :
public function insert($db, $array_label, $array_value){
$DB = new PDO('mysql:host='.$_SESSION['mysql'][0].';dbname='.$_SESSION['mysql'][1].';charset=utf8', $_SESSION['mysql'][2], $_SESSION['mysql'][3]);
$sql = "INSERT INTO '".$db."' (";
for($i = 0; $i < count($array_label); $i++){
if($i > 0)
$sql .= ", ";
$sql .= "'".$array_label[$i]."'";
}
$sql .= ") VALUES (";
for($i = 0; $i < count($array_label); $i++){
if($i > 0)
$sql .= ", ";
$sql .= ":".$array_label[$i];
}
$sql .= ")";
$stmt = $DB->prepare($sql);
echo '\$DB->prepare("'.$sql.'");';//DEBUG
for($i = 0; $i < count($array_label); $i++){
$label = ":".$array_label[$i];
$stmt->bindParam("$label", $array_value[$i]);
echo '</br>\$stmt->bindValue("'.$label.'", '.$array_value[$i].')';//DEBUG
}
$stmt->execute;
echo "</br></br>Requête OK.";
}
}
Then, i use it like this :
$array_label = array('ID', 'ID_lang', 'ID_entry_cat', 'date', 'label', 'content');
$array_value = array($ID, $ID_lang, $ID_entry_cat, "2016-03-03 00:00:00", $label, $content);
$DB->insert('entry', $array_label, $array_value);
After doing a lot of test, it may have a syntax problem, but i wasn't able to figure out where.
Here is what i got from the echo's(//DEBUG) :
$DB->prepare("INSERT INTO 'entry' ('ID', 'ID_lang', 'ID_entry_cat', 'date', 'label', 'content') VALUES (:ID, :ID_lang, :ID_entry_cat, :date, :label, :content)");
\$stmt->bindValue(":ID", 1)
\$stmt->bindValue(":ID_lang", 1)
\$stmt->bindValue(":ID_entry_cat", 1)
\$stmt->bindValue(":date", 2016-03-03 00:00:00)
\$stmt->bindValue(":label", dsqfsdq)
\$stmt->bindValue(":content", sdqfdsqf)
I know there is plenty topics on PDO not returning error but :
After reading a lot of them, it didn't help me at all.
Let say this : I'm a complete noob with PDO.
The echo i showed to you is what my function is doing.
I enclosed some pictures of my db to help :
PS: i leaved out "date" but it's not supposed to make troubles. I tested the same thing with it and it did the same thing : nothing.

Replace bindparam with bindvalue since you are passing values of that array:
EDIT
you also have quotes for table and column names,I replaced them with backticks and also you are missing brackets for execute
function insert($db, $array_label, $array_value){
$DB = new PDO('mysql:host='.$_SESSION['mysql'][0].';dbname='.$_SESSION['mysql'][1].';charset=utf8', $_SESSION['mysql'][2], $_SESSION['mysql'][3]);
$sql = "INSERT INTO `".$db."` (";
for($i = 0; $i < count($array_label); $i++){
if($i > 0)
$sql .= ", ";
$sql .= "`".$array_label[$i]."`";
}
$sql .= ") VALUES (";
for($i = 0; $i < count($array_label); $i++){
if($i > 0)
$sql .= ", ";
$sql .= ":".$array_label[$i];
}
$sql .= ")";
$stmt = $DB->prepare($sql);
echo '\$DB->prepare("'.$sql.'");';//DEBUG
for($i = 0; $i < count($array_label); $i++){
$label = ":".$array_label[$i];
$stmt->bindValue("$label", "$array_value[$i]");
echo '</br>\$stmt->bindValue("'.$label.'", "'.$array_value[$i].'")';//DEBUG
}
$stmt->execute();
echo "</br></br>Requête OK.";
}

Try running PDO in Exception mode, you can then catch PDO exceptions:
$db_pdo = new PDO($db_dsn, $dbuser, $dbpassword);
$db_pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// its function
$stmt->execute();
Also turn on error reporting in PHP to see whats going on

Related

Search a MySQL table in PHP

I am building a script where a user can query (search) a MySQL database.
The user firstly selects the table from a drop down list, and then they can choose upto 4 'filters' for example userID=001.
Here is my code:
$con=mysqli_connect("localhost","Username","Password","DBname");
// Check connection
if(mysqli_connect_errno()) {
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$query = "SELECT * FROM ".$table." WHERE 1=1 ";
if($filter1 != "" or $filter1v != "" )
{
$query .= " and $filter1 LIKE'%$filter1v%'";
}
if($filter2 != "" or $filter2v != "" )
{
$query .= " and $filter2 LIKE'%$filter2v%'";
}
if($filter3 != "" or $filter3v != "" )
{
$query .= " and $filter3 LIKE'%$filter3v%'";
}
if($filter4 != "" or $filter4v != "")
{
$query .= " and $filter4 LIKE'%$filter4v%'";
}
$query .= ";";
$resultRAW = mysqli_query($con, $query);
echo mysqli_error($con);
$result = array();
while($data = mysqli_fetch_array($resultRAW, MYSQLI_ASSOC))
{
$result[] = $data;
}
echo "<table class='table table-striped' id='tableWithExportOptions'>";
$amountRows = count($result);
for($i = 0; $i < $amountRows; $i++)
{
$keys = array_keys($result[$i]);
$amountColumns = count($keys);
if ($i == 0)
{
echo "<thead><tr>";
//I replaced the foreach clause because of performance reasons but they would work as well
for($j = 0; $j < $amountColumns; $j++)
{
echo "<th>".$keys[$j]."</th>";
}
echo "</tr></thead>";
}
echo "<tr>";
for($j = 0; $j < $amountColumns; $j++)
{
echo "<th>".$result[$i][$keys[$j]]."</th>";
}
echo "</tr>";
}
echo "</table>";
?>
If the user doesn't choose any filters the script works fine, however when using a filter it doesn't show any results?
Depending on your database this may vary. But you can not append a string to the result. $result is a MySQL Result object. You need to fetch the result for example with this code:
$array = array();
while($data = mysqli_fetch_array($result, MYSQLI_ASSOC))
{
$array[] = $data;
}
Then you can work with your result array $array and do whatever you want to do
If you want to create a query this way you need to call the mysqli_query later and build the query which could look like this:
$con = mysqli_connect("localhost","Username","Password","DBname");
// Check connection
if(mysqli_connect_errno())
{
echo "Failed to connect to MySQL: ".mysqli_connect_error();
}
$query = "SELECT * FROM ".$table." WHERE 1=1 ";
if($field != "" or $fieldvalue != "" )
{
$query .= " and ".$field." LIKE'%".$fieldvalue."%'";
}
if($filter1 != "" or $filter1value != "" )
{
$query .= " and ".$filter1." LIKE'%".$filter1value."%'";
}
if($filter2 != "" or $filter2value != "" )
{
$query .= " and ".$filter2." LIKE'%".$filter2value."%'";
}
if($filter3 != "" or $filter3value != "" )
{
$query .= " and ".$filter3." LIKE'%".$filter3value."%'";
}
if($filter4 != "" or $filter4value != "")
{
$query .= " and ".$filter4." LIKE'%".$filter4value."%'";
}
$query .= ";";
$resultRAW = mysqli_query($con, $query);
$result = array();
while($data = mysqli_fetch_array($resultRAW, MYSQLI_ASSOC))
{
$result[] = $data;
}
And I would be extremely careful with $table. in the query. This looks like a very good point to start an SQL Inejction attack. To prevent those I recomment the use of prepared statements. More can be found here: Prevent SQL Injection.
Unfortunalty this does not work with tablenames so you need to manually test it for any malicios input. If you "trust" this variable then it might be ok but if it is a use rinput I would AT LEAST call:
$table = mysqli_real_escape_string($table);
EDIT:
echo "<table class='table table-striped' id='tableWithExportOptions'>";
$amountRows = count($result);
for($i = 0; $i < $amountRows; $i++)
{
$keys = array_keys($result[$i]);
$amountColumns = count($keys);
if ($i == 0)
{
echo "<thead><tr>";
//I replaced the foreach clause because of performance reasons but they would work as well
for($j = 0; $j < $amountColumns; $j++)
{
echo "<th>".$keys[$j]."</th>";
}
echo "</tr></thead>";
}
echo "<tr>";
for($j = 0; $j < $amountColumns; $j++)
{
echo "<th>".$result[$i][$keys[$j]]."</th>";
}
echo "</tr>";
}
echo "</table>";
If this does not work please tell me, I have not tested this.
Because you concatenate string to $result = mysqli_query
$result = "SELECT * FROM $table WHERE 1=1";
if ($field != "" or $fieldvalue != "") {
$result .= " and $field LIKE'%$fieldvalue%'";
}
if ($filter1 != "" or $filter1value != "") {
$result .= " and $filter1 LIKE'%$filter1value%'";
}
if ($filter2 != "" or $filter2value != "") {
$result .= " and $filter2 LIKE'%$filter2value%'";
}
if ($filter3 != "" or $filter3value != "") {
$result .= " and $filter3 LIKE'%$filter3value%'";
}
if ($filter4 != "" or $filter4value != "") {
$result .= " and $filter4 LIKE'%$filter4value%'";
}
mysqli_query($con, $result);
Few things I can see that give me pause here.
But firstly, to Answer your question:
The mysqli_query(); method executes the query you pass to it. In your code you're executing the basic query with mysqli_query(); before you check for and add the filters and their values. So no matter what the user selects on your drop downs, that query without filters will always be executed first. You need to build your whole query string first, then execute the query with mysqli_query(); after all the checking and possible additions to your query.
Additionally, things that might break things later on:
Also, you might want to use and/&& in your if statements. or like you have it will allow your SELECT statement to break if you have the $filter1value populated with a value and $filter1 not, it will test true in your if and the WHERE clause will be concatenated to your query with a value but no field.
TIPS: echo your SQL command out to see what your php code has generated to see if it's valid SQL before running it while you develop.
Myself and many other PHP developers prefer to use PDO to interact with Databases personally, but that's just my preference.
I wanted to give you a code example of how I would have done it, but I honestly would change too much of your code, so I left it.
Side-note: I'm not sure what levels of security you have on the inputs but what you're doing by including your input variables directly into you SQL command string like that leaves you open to SQL injection attacks. Very dangerous depending on who will be able to access your script. Perhaps try using a prepared statement with parameters to keep security up a bit. Please look at mysqli_prepare(); it's friend, the mysqli_stmt_bind_param(); method in this case where you're using mysqli. Always use prepared statements on the database libraries you use if you're accepting external inputs to your system. It'll save your job one day.
Just my two cents use it, don't use it. :)
I guess you should add the filters on the query string before you execute the query, instead of adding the filter to the results? E.g.
$query = "SELECT * FROM $table WHERE 1=1";
if (...) {
$query .= ...
}
// some more ifs...
$result = mysqli_query($con, $query);

Making multiple mysqli queries using a for loop

I'm trying to make a series of mysqli queries by looping through the values of an array - (called column) - but nothing is being returned.
for ($i = 0; $i < sizeof($column); $i++)
{
$mutualInterests = mysqli_query ($conn, "SELECT USER_1 FROM INTERESTS WHERE answer = " . $column[$i] );
while ($row = mysqli_fetch_array ($mutualInterests))
{
echo " $row[USER_1]";
}
}
Just replace your given code with following and see result ..........
$query='SELECT USER_1 FROM INTERESTS WHERE answer ="'.$column[0].'"';
for ($i = 1; $i < sizeof($column); $i++)
{
$query.=' OR answer ="'.$column[$i].'"';
}
$mutualInterests = mysqli_query ($conn,$query);
while ($row = mysqli_fetch_array ($mutualInterests))
{
echo " $row[USER_1]";
}
Replace this:
while ($row = mysqli_fetch_array ($mutualInterests))
{
echo " $row[USER_1]";
}
with this:
$count = 0;
while ($row = mysqli_fetch_array ($mutualInterests))
{
echo $row[$count]."<br>";
$count++;
}
Let me know if it works now! :)

query works in mysql terminal but not in php

I build my query in PHP dynamically, and when I try to execute it, it fails. When I copy the query it generated and paste it into the mysql terminal and run it, it works fine. The error I get is "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '>' at line 1" for the following query:
UPDATE events SET event = 'orgo lecture', start = '2014-07-24 16:00:00' WHERE userID = 1 AND eventID = 5
The following is the code used to generate the query dynamically:
$query = "UPDATE events SET ";
$query_list = array();
if ($set_event) {
$query_list[] = "event = '{$event}'";
}
if ($set_start) {
$query_list[] = "start = '{$start}'";
}
if ($set_end) {
$query_list[] = "end = '{$end}'";
}
$query_list_size = count($query_list);
for ($i = 0; $i < $query_list_size - 1; $i++) {
$query .= $query_list[$i];
$query .= ", ";
}
$query .= $query_list[$query_list_size - 1];
$query .= " WHERE userID = {$userID} AND eventID = {$eventID}";
echo $query .= "<br />";
$query_result = mysqli_query($connection, $query) or die(mysqli_error($connection));
This issue is this:
echo $query .= "<br />";
Should be
echo $query . "<br />";
Ironically, by checking your query you were breaking it.
As a side note,
$query_list_size = count($query_list);
for ($i = 0; $i < $query_list_size - 1; $i++) {
$query .= $query_list[$i];
$query .= ", ";
}
$query .= $query_list[$query_list_size - 1];
Could be shortened to:
$query .= implode(", ", $query_list);
The echo $query .= "<br />"; instruction is changing the query and making it invalid SQL. Why not use echo $query . "<br />";?

PHP - for statement in a string

I have a MySQL statement that I want to execute and inside this statement I would like to include a for loop to define the columns that data will be entered into etc.
The code I currently have is
$stmt = $conn->prepare('INSERT into DATA ('.
for($i = 0; $i < count($columns); $i++) {
echo $columns[$i];
}
.') VALUES ('.
for($i = 0; $i < count($columns); $i++) {
echo ':'.$columns[$i].' , ';
}
.')');
Obviously this doesn't work but if it was to work also in the second for statement it echos a comma at the end of each loop, which will cause an error for the last loop so also is there a way to fix this to?
Thanks in advance!
Use the join/implode function:
$params = array_map(function($var){return ':'.$var;}, $columns);
$sql = 'INSERT into DATA ('.join(',', $columns).') VALUES ('.join(',', $params).')';
$stmt = $conn->prepare($sql);
Another approach using implode:
$sql = "INSERT into DATA (`" . implode('`,`', $columns) . "`) values (:" . implode(',:', $columns) . ")"
$stmt = $conn->prepare($sql);
Example result:
// Input array
$columns = array('A', 'B', 'C');
// Output
INSERT into DATA(`A`,`B`,`C`) values (:A,:B,:C)
You should create the query outside of the prepare() function to make it easier.
Something like that would be better/clearer :
$count = count ($columns); // Avoid using count in your loop init (Performances)
$query = 'INSERT INTO DATA (' .
for($i = 0; $i < $count; $i++) {
$query .= $columns[$i];
}
$query .= ') VALUES (';
for($i = 0; $i < $count; $i++) {
if ($i != $count - 1) $query.= ':'.$columns[$i].' , ';
else $query .= ':'.$columns[$i]; // No coma for the last value
}
$query .= ')';
$stmt = $conn->prepare($query);

SQL array values in php

Hi I'm really new to php/mysql.
I'm working on a php/mysql school project with 39 fields all in all in a single table.
I want to shorten my codes especially on doing sql queries.
$sql = "INSERT into mytable ('field_1',...'field_39') Values('{$_POST['textfield_1']}',...'{$_POST['textfield_39']}')";
I don't know how to figure out this but , i want something like:
$sql = "Insert into mytable ("----all fields generated via loop/array----") Values("----all form elements genrated via loop/array---")";
Thank you in advance.
<?php
function mysql_insert($table, $inserts) {
$values = array_map('mysql_real_escape_string', array_values($inserts));
$keys = array_keys($inserts);
return mysql_query('INSERT INTO `'.$table.'` (`'.implode('`,`', $keys).'`) VALUES (\''.implode('\',\'', $values).'\')');
}
?>
For example:
<?php`enter code here`
mysql_insert('cars', array(
'make' => 'Aston Martin',
'model' => 'DB9',
'year' => '2009',
));
?>
try this it i thhink it il work
You could use implode:
$sql = "
INSERT into mytable
('" . implode("', '", array_keys($_POST) . "')
VALUES
('" . implode("', '", $_POST . "')";
(This assumes the indices of the POST array are also the names of the db table fields)
However, this is extremely insecure since you would directly insert post data into the database.
So the least you should do beforehand is escape the values and make sure they are ok/valid table fields:
// Apply mysql_real_escape_string to every POST value
array_walk($_POST, "mysql_real_escape_string");
and
// Filter out all POST values with invalid indices
$allowed_fields = array('field_1', 'field_2', /* ... */ );
$_POST = array_intersect_key($_POST, $allowed_fields);
<?php
$sql = "Insert into mytable (";
for ($i = 1; $i < 40; $i++) {
if ($i == 39) {
$sql .= "field_$i";
} else {
$sql .= "field_$i,";
}
}
$sql .= "Values(";
for ($i = 1; $i < 40; $i++) {
if ($i == 39) {
$sql .= "'" . $_POST[textfield_$i] . "'";
} else {
$sql .= "'" . $_POST[textfield_$i] . "',";
}
}
?>
< ?php
$sql = "Insert into mytable (";
for ($i = 1; $i < 40; $i++) {
if ($i == 39) {
$sql .= "field_$i";
} else {
$sql .= "field_$i,";
}
}
$sql .= "Values(";
for ($i = 1; $i < 40; $i++) {
if ($i == 39) {
if(is_int($POST[textfield$i])){
$sql .= $POST[textfield$i];
}
else{
$sql .= "'" . $POST[textfield$i] . "'";
}
} else {
if(is_int($_POST[textfield_$i])){
$sql .= $_POST[textfield_$i] .",";
}
else{
$sql .= "'" . $_POST[textfield_$i] . "',";
}
}
}
?>
it will work for numeric values. you can insert numeric values in single quotes but some times it will create some problems

Categories