PHP PDO AJAX Query not working, my eyes are crossing - php

I am re-writing a file that will dynamically build queries to search and match any word in an string passed by an ajax event...
I cannot get the thing to return data. It acts like everything worked perfectly, but it didn't. All I get in firebug is success: true..which is good because that means there wasn't an error but my SQL results aren't being passed.
I know this code is going to be all over the place for you guys, but it doesn't work...
I've spent most of the day re-working this code so its not pretty or perfect yet, I just want it to return search results again...
Bill, if you are reading this, I didn't get a chance to look into the %LIKE alternatives you suggested last week ha...still waiting on your book in the mail.
Sorry to dump a ton of code on you guys but I just can't see what's wrong here.
function CreateOptions($columns, $num_elements, $condition="AND") {
$colcount = count($columns);
$optionString = " ";
for ($ii=0; $ii < $num_elements; $ii++) {
if ($ii > 0)
$optionString .= " AND (";
for ($i=0; $i<$colcount; $i++) {
if ($i>0)
$optionString .= " OR ";
$optionString .= $columns[$i] . " LIKE '%:search$ii%'";
}
//$optionString .= ")";
}
return $optionString;
}
include_once('../sys/core/init.inc.php');
$json = array();
$result = array();
if (isset($_POST['searchTerm'])){
try {
$search = trim($_POST['searchTerm']);
$search = preg_replace('/\s+/', ' ', $search);
$search = explode(" ", $search);
$num_search_elements = count($search);
switch($_POST['category']) {
case ("account"):
$querySyntax = "SELECT
idAccount,
FirstName,
LastName,
Email,
Phone,
CCCity,
db_name.states.Abbreviation
FROM
db_name.account Right Join
db_name.states On
db_name.account.CCState =
db_name.states.ID
WHERE";
$cols = Array ("FirstName", "LastName", "Phone", "Email", "idAccount");
$querySyntax .= CreateOptions($cols, $num_search_elements);
break;
default:
break;
}
$querySyntax .= " LIMIT 50";
// Build and run query (change to execute)
$dbs = $dbo->prepare($querySyntax);
for($i=0; $i<$num_search_elements; $i++) {
if ($dbs->bindValue(":search$i", $search[$i], (is_int($search[$i]) ? PDO::PARAM_INT : PDO::PARAM_STR))) {
// yea i know... nothing here its all below still
} else {
die("BIND_ERROR");
}
}
$dbs->execute();
// Put the array together
$search_results = $dbs->fetchAll(PDO::FETCH_ASSOC);
//print_r($search_results);
foreach($search_results as $col=>$val) {
$result[$i][$col] = $val;
$i++;
//echo "$col >> $val";
}
$stmt = null;
$result["success"] = true;
}
catch (PDOException $e) {
$result["success"] = false;
$result["error"] = $e->getMessage() . " >> SQL: $querySyntax";
}
} else {
$result["success"] = false;
$result["error"] = "INVALID DATA";
}
header('Content-type: application/json');
echo json_encode($result);
Here is the generated SQL taken straight from Firebug when I tell it to echo the query:
SELECT
idAccount,
FirstName,
LastName,
Email,
Phone,
CCCity,
db_name.states.Abbreviation
FROM
db_name.account Right Join
db_name.states On db_name.account.CCState =
db_name.states.ID
WHERE
FirstName LIKE '%:search0%' OR
LastName LIKE '%:search0%' OR
phone LIKE '%:search0%' OR
email LIKE '%:search0%' OR
idAccount LIKE '%:search0%'
LIMIT 50
replace :search0 with "mar" you get this from my db in terminal and phpmyadmin:
1 Mar <my real name> myemail#email 1231231234 City FL
2 Martin Short mshort#movies.com 2147483647 Beverly Hills CA
4 Martin Short mshort#email.com 2146791243 Beverly Hills CA
5 Martin Short mshort#movies.coms 2146791243 Beverly Hills CA

Try using:
header('Content-Type: text/javascript');
Check your http results using something like Firebug/Network view - it might be returning correctly, just isn't getting parsed in Javascript.

Your problem could be in this line:
foreach($search_results as $col=>$val) {
$result[$i][$col] = $val;
$i++;
//echo "$col >> $val";
}
At this point in the code $i starts as the value of $num_search_elements, and counts upward from there. It is never re-initialized and set to 0 after a previous loop in the code which uses $i to count up to $num_search_elements.
What happens when you print_r($result) after the above loop? What happens when you print_r($search_results) before this loop? Do they match?
The above code could be replaced with:
foreach($search_results as $col=>$val) {
$result[][$col] = $val;
}
Which will index upward starting from 0.

Your problem comes from the SQL query you generate.
I would suggest you get your query out of PDO and try it in phpmyadmin or mysql console.
If it works there, then your php script is not generating the sql properly. If it's that case it'll be a lot of help if you show us the real sql query and the results from your database.
Edit:
Try replacing this:
for ( $i = 0; $i < $num_search_elements; $i++ ) {
if ( $dbs->bindValue(":search$i", $search[ $i ], (is_int($search[ $i ]) ? PDO::PARAM_INT : PDO::PARAM_STR)) ) {
With this
for ( $i = 0; $i < $num_search_elements; $i++ ) {
$var = ":search".$i;
if ( $dbs->bindValue($var, $search[ $i ], (is_int($search[ $i ]) ? PDO::PARAM_INT : PDO::PARAM_STR)) ) {
And see if it works.

The reson it was not working was because I had the bound search iterations (:search0...) in '' which turns it into a literal which will not match anything in the database.

Related

Inserting multiple values from Checkbox into 4 Columns

I'm a little confused here. I want to add 4 values to the db. Exept if the user only add < 4.
DB columns are:
ticket1, ticket2, ticket3, ticket4
There are multiple checkboxes 1-19.
<input class='' id='cbx' value='1' name='check_num[]' type='checkbox'/><label>1</label>
My code is...
if(!empty($_POST['check_num'])) {
foreach($_POST['check_num'] as $key => $value) {
//i just need the ARRAY or something to divide the numbers in peaces to put on the db.
}
} else {
echo "empty";
}
I'd use something like this, but there are plenty of alternatives.
if(!empty($_POST['check_num'])) {
$count = count($_POST['check_num']);
if($count <= 4){
$columns = "";
$values = "";
$i = 1;
while($i <= $count){
$columns .= "ticket".$i.", ";
$params .= "?, ";
$types .= "i";
$i++;
}
$columns = substr($columns, 0, 2);
$params = substr($columns, 0, 2);
$stmt = $mysqli->prepare("INSERT INTO [table_name] (".$columns.") VALUES (".$params.");";);
mysqli_stmt_bind_param($stmt, $types, ...$_POST['check_num']);
mysqli_stmt_execute($stmt);
}
else{
echo "Too many selections";
}
}
else{
echo "empty";
}
I haven't used anything but PDO for prepared in php in several years. Might be my bias but I'd recommend the switch, this seemed more complicated to me. You may need to update the portions using mysqli prepare and bind I haven't tested this code at all, just wrote it in the answer.
I also assumed each column was an integer type, and of course, update to use your table name in the query.
I added the substr() functions to remove trailing ", " from last entry of each, you could also check if $i == $count before those assignments, and use a different assignment set without the trailing ", " inside that if() with the current assignments in the following else. The $i++ would obviously be outside this if()/else.

Multiple while loop in two queries

I have 2 queries.
and 2 while loops.
my problem is that When I call out the values. only one query and one loop is correct. the other loop is displaying duplicate values.
here is what I have :
$query1=mysql_query("SELECT * FROM table1");
$query2=mysql_query("SELECT * FROM table2");
while($row1=mysql_fetch_array($query1)){
while($row2=mysql_fetch_array($query2)){
echo $row1['nameofattribute'] ;
echo $row2['nameofattribute'] ;
}
}
the output of query 1 is correct. but the output of query 2 is duplicate values.
for example :
query 1= $row1=2 $row1=3 $row1=4
query 2= $row2=3 $row2=3 $row2=3
instead it should be
query 1= $row1=2 $row1=3 $row1=4
query 2= $row2=1 $row2=2 $row2=3
on top is my simple translation of the code. here is my real code :
$query1 = mysql_query("SELECT remarks FROM passed_deliverable WHERE user_id=$uid && deliverable_category_id=4");
$query2=mysql_query("SELECT
deliverable_id, deliverable_title, deliverable_desc, adviser_id ,deliverable_category_id
FROM deliverable d
WHERE d.deliverable_category_id=4
&& EXISTS (
SELECT 'X'
FROM passed_deliverable pd
WHERE pd.deliverable_id = d.deliverable_id && user_id='".$_GET['edit']."' && adviser_id='".$_SESSION['user_id']."' ) ");
while($x=mysql_fetch_array($query1)){
while($deliverable=mysql_fetch_assoc($query2)){
echo "
{$deliverable['deliverable_desc']}
{$x['remarks']}
";
try this :
other answer or loop from mr. hellcode
it shows that you can also use array values instead of just using array
$a1 = 0[];
$a2 = 0[];
while($x=mysql_fetch_array($query1)) {
$a1[] = $x['remarks'];
}
while($deliverable=mysql_fetch_assoc($query2)) {
$a2[] = $deliverable['deliverable_desc'];
}
for($i=0; $i < count($a1) and $i < count($a2); $i++) {
echo "\n\n".$a2[$i]."\n".$a1[$i];
}
Assuming that you just want to combine the resulting rows of both tables in their appearing order (ignoring results that exceed the other table):
$a1 = array();
$a2 = array();
while($x=mysql_fetch_array($query1)) {
$a1[] = $x['remarks'];
}
while($deliverable=mysql_fetch_assoc($query2)) {
$a2[] = $deliverable['deliverable_desc'];
}
for($i=0; $i < count($a1) and $i < count($a2); $i++) {
echo "\n\n".$a2[$i]."\n".$a1[$i];
}
Deprecation of mysql_ functions . Please avoid mysql_ function . Anyway your query seems to unusual. because we don't see any WHERE clause in your queries . That means it will return duplicate value. Table1 each row will be check all rows of Table2 .

PHP SQL where statement with loop variable

I am having problems with the retrieval of data from my database using a where clause with a for loop variable. this codes currently can retrieve the data from the database but however the values retrieved from the database stockpiles. at the number 1 in the for loop its still fine. but when it goes to the next one. the data gathered is the combination of 1 and 2. when it finally hit the end of the loop all of the data is displayed.
Which part of the codes must be edited to change the display of data to non-cumulative
<?php
$sectorcount = $row_SectorCount['COUNT(*)'];
//number of rows in database
$spendingname= array();
$spendingpercent= array();
$spendingid= array();
?>
// Add some data to the details pie chart
options_detail_1.series.push({ name: 'Tax Spending Detail', data: [] });
$(document).ready(function() {
chart_main = new Highcharts.Chart(options_main);
chart_detail_1 = new Highcharts.Chart(options_detail_1);
})
function push_pie_detail(sectorid) {
switch(sectorid)
{
<?php
for ($i=1; $i<=$sectorcount; $i++)
{
echo "case 'sector".$i."':" ,
"setTimeout", "(" , '"chart_detail_1.series[0].remove(false)", 1000);' ,
"chart_detail_1.addSeries(options_detail_1, false);" ,
"chart_detail_1.series[1].setData( [";
mysql_select_db($database_conn2, $conn2);
$query_Spending = "SELECT CONCAT(spending.SectorID, spending.ExpenditureID) AS 'SpendingID',
expenditure.ExpenditureName, spending.SpendingPercent, spending.SectorID
FROM spending
INNER JOIN expenditure ON spending.ExpenditureID = expenditure.ExpenditureID
WHERE spending.SectorID = '.$i.'";
$Spending = mysql_query($query_Spending, $conn2) or die(mysql_error());
$totalRows_Spending = mysql_num_rows($Spending);
while($row_Spending = mysql_fetch_assoc($Spending))
{
$spendingname[] = $row_Spending['ExpenditureName'];
$spendingpercent[] = $row_Spending['SpendingPercent'];
$spendingid[]= $row_Spending['SpendingID'];
}
mysql_free_result($Spending);
$a = 0;
foreach ( $spendingid as $sgi => $sgid)
{
if ($a > 0) echo ', '; // add the comma
echo "{
name: '$spendingname[$sgi]',
y: ". $spendingpercent[$sgi] * $tax .",
id: ' $sgid',
}";
$a++;
}
echo "], false);" ,
"chart_detail_1.redraw();",
"break;";
}
?>
default:
break;
}
}
You need to wrap your variable in 'x' single quotes in your where clause, otherwise it will think you mean id = true, which is true for all of them =) I had the same problem recently
EDIT: So instead of saying where spending.SectorID = $i, you should have 'somevalue', just make a new variable $example = "'" . $i . "'", and use that variable in the where clause
I wrote a function that takes text and wraps it in single quotes just for this situation
Move your $spendingname = array(); and other array definitions inside the loop.

Script to match names submitted via a form with MySQL database breaks when name contains apostrophe

I have script that enters names into a MySQL database, using mysql_real_escape_string so that apostrophes are handled correctly. The trouble I am experiencing is with the script below that checks to see if names entered using another form correspond to names already in my database and if names are found updates the row.
When I try to enter a name with an apostrophe into the form processed by this script, I get an error message stating that the name wasn't found, and the name in the error message contains a backslash before the apostrophe, which is obviously the issue.
So the question is, how can I amend the script below so that it will work with names with apostrophes?
Thanks,
Nick
$row_count = count($_POST['name']);
if ($row_count > 0) {
mysql_select_db($database, $connection);
$name = array();
$workshop = array();
$not_found = array();
for($i = 0; $i < $row_count; $i++) {
// variable sanitation...
$name[$i] = mysql_real_escape_string(ucwords($_POST['name'][$i]));
$workshop[$i] = mysql_real_escape_string($_POST['workshop'][$i]);
}
$names = "('".implode("','",$name)."')";
$not_in = Array();
// lets say all names doesn't exist in `conference`
foreach($name as $value) {
// names in array are keys, not values
$not_in[$value] = true;
}
$query = mysql_query("SELECT Name FROM conference WHERE Name IN $names");
while(list($dbname) = #mysql_fetch_row($query)) {
// delete those name from $not_in who exists
unset($not_in[$dbname]);
}
// names in $not_in array are keys, not values
$not_in = array_keys($not_in);
if(empty($not_in)) {
// its ok, all names have been found. do the magic.
for($i = 0; $i < $row_count; $i++) {
$sql = "UPDATE conference SET Workshop = '$workshop[$i]' WHERE Name LIKE '$name[$i]'";
mysql_query($sql);
$body .= "Name: " . $name[$i] . " Workshop: " . $workshop[$i] . "\n\n";
}
Hmmm! I think I might have found the issue. The problem might not be with the query but with the PHP code. I'll try to explain below using your example John O'Shea.
for($i = 0; $i < $row_count; $i++) {
// variable sanitation...
$name[$i] = mysql_real_escape_string(ucwords($_POST['name'][$i]));
$workshop[$i] = mysql_real_escape_string($_POST['workshop'][$i]);
}
$names = "('".implode("','",$name)."')";
$not_in = Array();
// lets say all names doesn't exist in `conference`
foreach($name as $value) {
// names in array are keys, not values
$not_in[$value] = true;
}
After the above code, Array $not_in will contain escaped keys because $name already contains values escaped using mysql_real_escape_string(). Hence, for example:
$not_in[John] = true;
$not_in[John O\'Shea] = true;
$query = mysql_query("SELECT Name FROM conference WHERE Name IN $names");
while(list($dbname) = #mysql_fetch_row($query)) {
// delete those name from $not_in who exists
unset($not_in[$dbname]);
}
Now $dbname in the above code contains unescaped values retrieved from the DB, for example John O'Shea without the backslashes. Since this is not what $not_in contains, the unset() will not work. This means that all apostrophe values remain in the $not_in array.
So the fix is to keep unescaped values in $not_in.
Hope this makes sense!
========== EDIT: In response to how to keep unescaped values in $not_in:
The idea is to do escaping just where it is needed. Here are the changes that you may do to your code:
Rewrite the first for() as below:
for($i = 0; $i < $row_count; $i++) {
// variable sanitation...
//$name[$i] = mysql_real_escape_string(ucwords($_POST['name'][$i]));
$name[$i] = ucwords($_POST['name'][$i]);
$workshop[$i] = mysql_real_escape_string($_POST['workshop'][$i]);
}
$names = "('" . mysql_real_escape_string(implode("','",$name)) . "')";
And rewrite the UPDATE statement as:
$sql = "UPDATE conference SET Workshop = '$workshop[$i]' WHERE Name LIKE '" . mysql_real_escape_string($name[$i]) . "'";
By the way, According to your code, the UPDATE will not run if there is one name that does not exist in the database. Is it absolutely necessary to run the UPDATE only if all the $_POST['name'] are found in the database? If not, you can significantly reduce the amount of code.
I haven't tested the above changes but I think they should work. Let me know if you get any issues.
========== EDIT 2: Code snippet for updating records that exist and generating errors for records that did not
Hey Nick, I think only writing the below code should do the trick:
$row_count = count($_POST['name']);
if ($row_count > 0) {
mysql_select_db($database, $connection);
for ($i = 0; $i < $row_count; $i++) {
mysql_query("UPDATE conference SET Workshop = '" . mysql_real_escape_string($_POST['workshop'][$i]) . "' WHERE Name LIKE '" . mysql_real_escape_string($_POST['name'][$i]) . "'");
$affectedRows = mysql_affected_rows();
if ($affectedRows == 0) {
echo '<br>Name did not exist - ' . $_POST['name'][$i];
}
}
}
Hope this helps!

PHP/MySQL pagination going wrong

Using PHP on my website linking to a library database in MySQL. The one area I can't seem to get right is the pagination of results. I've tried about twenty different code snippets and have the same problem each time - can't get more than the first page of results to display. Despite reading lots of forum posts on this one, can't get past it. My select query is slightly more complex in that several keywords can be combined and it is searching multiple fields. When results are displayed, they also pull data from different tables. I really hope someone can spot where I'm going wrong. Switch statement used dependent on which type of search the user requests, so the code for one case given below.
$term = trim($_REQUEST['term']);
$searchterm = mysql_real_escape_string($term, $link);
$index = $_REQUEST['index'];
switch ($index)
{
case "title":
$array = explode(" ", $searchterm);
$sql = "select identifier, title, publication_date from publication where";
foreach ($array as $key => $keyword) {
$sql .= " (title like '%$keyword%' or alternative_title like '%$keyword%')";
if ($key != (sizeof($array) - 1)) $sql .= " and ";
if ($key == (sizeof($array) - 1)) $sql .= " order by title";
}
if(!$result = mysql_query($sql, $link)) {
showerror();
}
else {
$numrows = mysql_num_rows($result);
if ($numrows == 0) {
echo "<h2>No records found</h2>";
}
//start pagination
$perPage = 10;
$page = (isset($_REQUEST['page'])) ? (int)$_REQUEST['page'] : 1;
$startAt = $perPage * ($page - 1);
$totalPages = ceil($numrows / $perPage);
$links = "";
for ($i = 1; $i <= $totalPages; $i++) {
$links .= ($i != $page ) ? " <a href='search.php?page=$i&search=$term'>
Page $i</a> " : "$page ";
}
echo "<h3>Displaying page $page of $totalPages:</h3><br />";
$counter = 1;
$sql = "select identifier, title, publication_date from publication where";
foreach ($array as $key => $keyword) {
$sql .= " (title like '%$keyword%' or alternative_title like '%$keyword%')";
if ($key != (sizeof($array) - 1)) $sql .= " and ";
if ($key == (sizeof($array) - 1)) $sql .= " order by title
LIMIT $startAt, $perPage";
}
$result = mysql_query($sql, $link);
echo "<table class=\"results\">\n";
while($row = mysql_fetch_array($result))
{
//echo data
}
echo "</table><br />\n";
echo $links; // show links to other pages
echo "<p> </p>";
}
break;
as stated above, -1 vote for placing someone elses code instead of trying it yourself. This code is wayyyy to much for what a pagination script should do. You could have added more specific code snippet and a better question. I'll try to take a look at it however.
As you can't get further than page 1 it seems that somethings going wrong aroung $page = (isset($_REQUEST['page'])) ? (int)$_REQUEST['page'] : 1 ; or a little below. Try echoƫing your SQL code for each page and take a look if the LIMIT is right or that it stays the same, probably the last. At least that gives you a starting point from where to take a look in your code.
Does it give you the right amount of links to go to?

Categories