MySQL collecting results regardless of spaces - php

I have a small application which I have collecting user input and returning a set of results based on the input. The input is a postcode so for example, pl4 7by. Which has a space between it. This is the format of which the data is stored in. I wish to have applicable postcodes returned from the search even if a user inputs without the space between or multiple spaces.
This is currently what I have.
<?php
$input = $_GET["input"] . "%";
try{
$handler = new PDO();
}
catch (PDOException $e){
echo "Connection failed: " . $e->getMessage();
}
$stmt = $handler -> prepare("
SELECT * FROM `LSOA_postcodes` WHERE postcode LIKE :input LIMIT 20
");
$stmt -> execute([
":input" => $input
]);
echo "<table>";
echo "<tr><th>Postcode</th><th>LSOA Code</th><th>LSOA Name</th></tr>";
while($row = $stmt -> fetchObject()){
echo "<tr>";
echo "<td>", $row -> postcode, "</td>";
echo "<td>", $row -> code, "</td>";
echo "<td>", $row -> name, "</td>";
echo "</tr>";
}
echo "</table>";
This is functional and returns the results regardless of case. I could store the data with no spaces, but I wish to have the correct format display to the user.

UPDATE
Just had a sudden thought and came up with this:
SELECT * FROM `LSOA_postcodes` WHERE REPLACE(postcode, ' ', '') LIKE REPLACE(:input,' ', '') LIMIT 20
This works as planned from first sight. Is there any problems that I cannot see with this?

Depending on the size of LSOA_postcodes, you may encounter performance problems using REPLACE as in the above 2 answers because it is unlikely to use index scans.
I would check the $input to see if it contains a space and add one if its length is > 3 - all in php then let the SQL do the search as in the original question.

You could trim the spaces on both sides of the = sign:
SELECT *
FROM `LSOA_postcodes`
WHERE REPLACE(postcode, ' ', '') LIKE REPLACE(:input, ' ', '')
LIMIT 20
Notes:
You'll use any benefit on an index on postcode, if you had one.
I stayed with the like operator like OP suggested, although since there are no wild cards here, a simple = should do the trick - Did not notice the use of % online 2, as per comments below.

Related

Query with multiple OR terms in WHERE returns the whole table

Can anyone tell me why this SQL command does not work?
I have a form with multiple inputs i.e. (id)=> account number, then firstname, lastname and email. I want to allow the user to search anyway they want.
if I leave the code the way it is "with AND" .. when searching only for just the (id) then it will just display the ID row but it won't display the rest of the searches if I try to enter first, last or email, but if I change it to "OR", then all the other input boxes will work displaying the single result, but if I enter just the id "account number" I will display every single customer in my table.. why?
what am I missing so my code can search for all the inputs?
Thank you
$firstname = $_POST['firstname'];
$lastname = $_POST['lastname'];
$email = $_POST['email'];
$firstname = "%$firstname%";
$lastname = "%$lastname%";
$email = "%$email%";
$id = $_POST['id'];
$stmt = $conn->prepare("
SELECT * FROM `Demo_Guests`
WHERE
firstname LIKE :firstname
AND lastname LIKE :lastname
AND email LIKE :email AND id = :id
");
$stmt->bindValue(':id', $id, PDO::PARAM_INT);
$stmt->bindValue(':firstname', $firstname,PDO::PARAM_STR);
$stmt->bindValue(':lastname', $lastname,PDO::PARAM_STR);
$stmt->bindValue(':email', $email,PDO::PARAM_STR);
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_OBJ);
foreach($result as $row){
echo "<tr><td>
" . $row->id . "<br></td>";
echo "<td>" . $row->firstname . "</td>";
echo "<td>" . $row->lastname . "</td>";
echo "<td>" . $row->email . "</td>";
echo "<td>" . $row->reg_date . "</td></tr>";
}
To expand on my comment above, which was:
When you use the OR statement, you need to be sure you don't have firstname LIKE '%%', because that will match everything. You will need to build your query to only use non-empty values provided from the form.
What that means is you will have to build your query from the NON-EMPTY inputs from your search form, and leave out terms that would match everything in your table.
It might be good to start by going through the post data and lifting out the non-empty values, to put in an array:
$searchFields = [];
foreach (['id', 'firstname', 'lastname', 'email'] as $searchField) {
if (!empty($_POST[$searchField])) {
$searchFields[$searchField] = $_POST[$searchField];
}
}
That gives you a list of all the fields that the user actually filled in. You will need that list twice - once to build the query, and once to do the bindings.
if (count($searchFields) > 0) {
$queryStr = "SELECT * FROM `Demo_Guests` WHERE 0";
foreach (array_keys($searchFields) as $fieldName) {
$queryStr .= " OR " . $fieldName . " LIKE :" . $fieldName;
}
// ... the rest of the code goes here
} else {
return "you gotta give me something to work with!";
}
Two notes: 1) I didn't make id a special case, and you will need to do that in your code. 2) WHERE 0 is a lazy-man shortcut to you don't have to do any extra logic later to decide whether you need to add OR to the first term. It turns into WHERE 0 OR firstname LIKE '%Alice%', which is functionally the same as WHERE firstname LIKE '%Alice%'.
Once you build your query string, you can prepare it the way you did above, then perform the bindings with the same array you used to construct the query.
$stmt = $conn->prepare($queryStr);
foreach($searchFields as $fieldName => $fieldValue) {
$stmt->bindValue(':'.$fieldName, "%$fieldValue%", PDO::PARAM_STR);
}
$stmt->execute();
As above, I did not create the code to treat the id field differently, but you should be able to handle that. If you had lots of fields of different types, you might want to change the structure of $searchFields to include type information. If id is the only exception, it's probably easiest to just use an if statement in each loop.
Added:
This search will return all records from the database that match ANY of the input criteria. So if the user searches for firstName LIKE '%Ali%' OR lastName LIKE '%Smi%' you might get back Alice Smith, Alicia Smith, Fred Smith, and Alice Jones.
If, however, you only want that search to return Alice Smith and Alicia Smith, rather than use OR, you use AND. The search will produce fewer results, so it is a little less forgiving for mis-typed names and so forth.
The only other modification to the code is that the lazy-man shortcut also has to change:
if (count($searchFields) > 0) {
$queryStr = "SELECT * FROM `Demo_Guests` WHERE 1";
foreach (array_keys($searchFields) as $fieldName) {
$queryStr .= " AND " . $fieldName . " LIKE :" . $fieldName;
}
// ... the rest of the code goes here
} else {
return "you gotta give me something to work with!";
}
WHERE 1 AND first_name LIKE '%Ali%' is functionally the same as WHERE first_name LIKE '%Ali%'.
Note that in this case, if the user specifies an ID, you will want to ignore the other search fields entirely. Otherwise, if they specify an id and a name that do not match, they won't get back any results at all.

Divide one PHP echo into 3 columns

I have managed to put this code together.
$sql = "
SELECT
inbox.ReceivingDateTime,
namnlista.namn AS SenderNumber, inbox.Text
FROM
inbox
INNER JOIN
namnlista
ON
inbox.SenderNumber = namnlista.SenderNumber";
$result = mysqli_query($conn, $sql);
if (mysqli_num_rows($result) > 0) {
// output data of each row
while($row = mysqli_fetch_assoc($result)) {
echo
$row["ReceivingDateTime"],
$row["SenderNumber"],
$row["Text"],"<br>";
}
} else {
echo "0 results";
}
mysqli_close($conn);
and it shows my info fine on my page but of course like this
ReceivingDateTimeSenderNumberText
And I want to make it look like this (using my index.css file)
ReceivingDateTime SenderNumber Text
I've tried adding stuff into the echo line but every time I do my page stops working so I am doing something wrong...
I've managed to add this, and make a table I guess?
echo
"<table> <tr> <td>"
.$row["ReceivingDateTime"]."</td>".
"<td>". $row["SenderNumber"]."</td>".
"<td>".$row["Text"]."</td></tr></table>";
But still it doesnt look good, I can use padding in CSS but what should I use to make the 3 columns all start at selected points?
Now the next column starts after the same amount of empty space regardless of the length of the previous column and that is not good.
Only concatenate a space (o whatever) after echo. See this example. Concatenation of strings in PHP are with dot.
$sql = "
SELECT
inbox.ReceivingDateTime,
namnlista.namn AS SenderNumber, inbox.Text
FROM
inbox
INNER JOIN
namnlista
ON
inbox.SenderNumber = namnlista.SenderNumber";
$result = mysqli_query($conn, $sql);
if (mysqli_num_rows($result) > 0) {
// output data of each row
while($row = mysqli_fetch_assoc($result)) {
echo
$row["ReceivingDateTime"]." ", //here
$row["SenderNumber"]." ",// and here
$row["Text"],"<br>";
}
} else {
echo "0 results";
}
mysqli_close($conn);
The absolute simplest way to get your data into columns would be to use
echo "<pre>" . $row["ReceivingDateTime"] . "\t" . $row["SenderNumber"] . "\t" . $row["Text"] . "</pre><br>";
This doesn't give you much structure in the html. Semantically a table is probably more appropriate but this is quick and dirty.
The <pre> tag in html means preserve whitespace, and the \t is a special character representing a tab.
Right, similar to what Christian said, you can concatenate a space after each term. But the question indicated that you wanted columns. If that's the case, you can also user '\t' for a tabbed effect.

How to use a mysqli result row more than once in PHP?

I am trying to put together a tool to help me with my upcoming fantasy hockey draft while also learning PHP. I am trying to create multiple lists on a page, one that displays the top 10 available players overall and then others that display the top 10 available players by position.
Here is my SQL query/code
include 'db/connect.php';
$sql='SELECT * FROM players WHERE pick IS NULL';
$players=$conn->query($sql);
if($players === false) {
trigger_error('Wrong SQL: ' . $sql . ' Error: ' . $conn->error, E_USER_ERROR);
} else {
$rows_returned = $players->num_rows;
}
Then later in the page I have a while loop that generates a table with the top ten players
while ($row = $players->fetch_array()) {
if ($i == 10) {
break;
}
echo "<tr>";
echo "<td>" . $row['Rank'] . "</td>";
echo "<td>" . $row['Player'] . "</td>";
echo "<td>" . $row['Team'] . "</td>";
...
And all that works fine. However, when I go to use the same method to generate a list containing only a certain position (C, RW/LW, etc...) it starts off where the top 10 player list ends. (See what I mean here: http://i.imgur.com/JApeftU.png)
I assume this has to do with the $players->fetch_array() however I do not know what the best way would be to get around it.
Any ideas?
Thanks!
Populate rows with all the players.
while ($row = $players->fetch_array()) { //→ $rows = $players->fetch_all();
$rows[] = $row;
}
You can use count() to get total amount of players in the array
$totalPlayers = count($rows);
Now you can loop through the array with for loop
for($i = 0; $i < $totalPlayers; $i++){
//echo out the stuff you want
echo $rows[$i]['player'];
}
Or only ten
for($i = 0; $i < 10; $i++){
//echo out the stuff you want
echo $rows[$i]['player'];
}
Well, for the future visitors, lured by the misleading title, the other answer is okay.
While for you personally, the other answer, as well as your question, is wrong.
And it's your idea on using databases is wrong in the first place.
A database is not like a text file, which you but bound to read every time from first line to last. Databases are quite intelligent and intended to return you the very data you requested.
Think it this way: what if your league will grow up to employ thousands of players. It will burden PHP script with lots of useless info, when it needs only a hundred of players.
So, it seems you need different queries to get differen data sets. First, you need a query
SELECT * FROM players WHERE pick IS NULL ORDER BY field DESC LIMIT 10
To get overall top ten, where field is whatever field you're using to determine the "top" player. And then several queries, each getting players for the certain position.
SELECT * FROM players WHERE pick IS NULL AND position=? ORDER BY field DESC LIMIT 10

PHP: Can't Get Oracle Table to Display on Page

This is probably a really obvious error. Anyway, some details:
I have an oracle database that I need to extract data from to populate a table on a PHP page. The table is called Flowers and has Name, Price and Stock columns.
The part of the PHP code I'm having trouble with is this:
$titlevalue = Trim($_REQUEST['search']);
$query = "SELECT * FROM FLOWERS WHERE NAME = '$titlevalue'";
$stmt = OCIParse($connect, $query);
if(!$stmt) {
echo "An error occurred in parsing the sql string.\n";
exit;
}
OCIExecute($stmt);
The rest of my PHP works -perfectly- when using a different table on my database, which I did as a test. Just in case, this is the code that prints the query results (it's part of an HTML table, but you can ignore that):
while(OCIFetch($stmt)) {
echo "<tr valign=top bgcolor=#F7D4A3>";
$fg1 = OCIResult($stmt,"NAME");
echo "<td width=75>";
echo $fg1;
echo "</td>";
// Display values in column two.
$fg2 = OCIResult($stmt,"PRICE");
echo "<td width=75>";
echo ($fg2);
echo "</td>";
// Display values in column three
$fg3 = OCIResult($stmt, "STOCK");
echo "<td width=75>";
include($fg3);
echo "</td>";
echo "</tr>";
}
No matter what $titlevalue becomes, I just can't get results with this table. I have also tested it with a generic $query = "SELECT * FROM FLOWERS";, but that didn't produce anything either.
Could someone please lend a hand? :( It's been a very long night.
If I may, two things just to note:
1) you're using '$titlevalue', i think that will translate as ... $titlevalue in the query, and not its value
2) Its late ... have you checked that your table is called FLOWERS (case sensitivity)
I'd comment, but I dont have the rep to do so.
If this was helpful, please +1 or click the tickmark. I normally try and use the full format when doing sql queries
SELECT * FROM `table name` WHERE 'x'
... etc. where possible

Using PHP variable variables in SQL query

Sorry for this question to be a "can you fix it" one, but this little bit of code has been confusing me for a while now.
I'm basically making a table with a bunch of rows and columns and in each one I have a slightly changing SQL query. To make it a bit easier instead of typing all that out I made this bit of script but it is starting to get a bit complicated so can any of you manage to get it correct?
echo '<td background="images/map/';
$tile = mysql_fetch_array(mysql_query("SELECT image FROM map WHERE horizontal = ${'mapPiece' . $mapPieceCount . [0]} AND verticle = ${'mapPiece' . $mapPieceCount . [0]}"));
echo $tile[0];
echo '.png"></td>';
Thanks, Stanni
Assuming I interpreted this right, the [0] needs to go outside of the curly braces:
echo '<td background="images/map/';
$tile = mysql_fetch_array(
mysql_query(
"SELECT image FROM map WHERE horizontal = ".
${'mapPiece' . $mapPieceCount}[0].
" AND verticle = ".
${'mapPiece' . $mapPieceCount}[0]
)
);
echo $tile[0];
echo '.png"></td>';
First of all, you can't append the array index [0] like that, like you're concatenating on a string. Overall, it would be much easier if you just added a few extra lines to make things neater:
$currentPiece = 'mapPiece' . $mapPieceCount;
echo '<td background="images/map/';
$query = 'SELECT image '.
'FROM map '.
'WHERE horizontal = '.${$currentPiece}[0].' '.
'AND verticle = '.${$currentPiece}[0];
$result = mysql_query($query);
$tile = mysql_fetch_array($result);
echo $tile[0];
echo '.png"></td>';

Categories