I have a searchable database of the House and Senate and I just want to make a simple web page that can search this database. The only problem is, while I'm comfortable writing SQL select statements, how do I properly format them for use in PHP?
For example, here's my radio button to select Senators by state:
$sql = "";
if ($_POST['pkChamber'] == "Senate") {
if ($_POST['pkParty'] == "Y") {
$sql = SELECT * FROM senateinfo
WHERE state = (Variable = "stname")
ORDER BY last_name, first_name');
}
else
{
$sql = SELECT * FROM senateinfo
WHERE state = (Variable = "stname")
ORDER BY last_name, first_name
}
}
I am not sure what you're asking for, But I have a good example of reliable and safe way for building WHERE statement dynamically:
$w = array();
$where = '';
if (!empty($_GET['rooms'])) $w[]="rooms='".mysql_real_escape_string($_GET['rooms'])."'";
if (!empty($_GET['space'])) $w[]="space='".mysql_real_escape_string($_GET['space'])."'";
if (!empty($_GET['max_price'])) $w[]="price < '".mysql_real_escape_string($_GET['max_price'])."'";
if (count($w)) $where = "WHERE ".implode(' AND ',$w);
$query = "select * from table $where";
Hope this helps.
Your query seems fine. I think you just need to understand some of the finer points of string parsing in PHP.
When you use double quotations (") to enclose a string, PHP actually will try to parse it looking for variables and/or other php code to process first. Something like this:
$sql = "SELECT * FROM table WHERE state = '{$state}' AND user = {$user->id}";
PHP will substitute out $state for whatever is defined in that variable and the same for the id of whatever user is instantiated in that class. (Also, you don't have to wrap your simple variables in {}. It does help with readability but is only required for class methods/variables.)
If you use single quotes (') to enclose a string, PHP simply treats it like normal. For your above query, I would suggest enclosing it in single quotes like this:
$sql = 'SELECT * FROM senateinfo WHERE state = (Variable = "stname") ORDER BY last_name, first_name)';
If you want to use variables later on in this query, then you will need to escape the double quotations that are in there like this:
$sql = "SELECT * FROM senateinfo WHERE state = (Variable = \"stname\") ORDER BY last_name, first_name)";
This way, PHP doesn't error out thinking you were trying to concatenate strings incorrectly when all you were doing was pasting a query.
You need to focus on one issue at a time.
Try to avoid writing SQL in PHP until you've a clear handle on strings in PHP, and how to inject variables into those strings. So:
Read up on string quoting in PHP (double quotes vs. Single quotes, and yes, HEREDOC)
Read up on variables in strings in PHP (note that if it doesn't have a $ dollar sign, it's a CONSTANT, not a string variable. Start off right with $strings and $variables where they're supposed to be used, not CONSTANTs, which only fall back to turn into strings if nothing else is available.)
Read up on binding SQL in PHP. Anything else will lead you down the path of SQL injection. If there are only naked strings used in your PHP SQL, then you are setting yourself up for failure when you finally deploy your web scripts to the harsh and unforgiving Internet. It's full of sharks ready to take advantage of SQL injection prone scripts.
Here is an example of code I use daily to bind SQL, centered around a custom function that makes it easy:
query("select * where someTable where someTable_id = :bound_id", array(':bound_id'=>13));
I can get you a function for creating bound SQL simply like that later (when I'm actually at a computer instead of mobile) if you're interested.
I use HEREDOCs for writing out non-trivial queries:
$sql = <<<EOL
SELECT blah, blah, blah
FROM table
WHERE (somefield = {$escaped_value}) ...
ORDER BY ...
HAVING ...
EOL;
Heredocs function as if you'd done a regular double-quoted string, but with the bonus of not having escape internal quotes. Variable interpolation works as expected, and you can do indentation on the text as well, so your query looks nicely formatted
I always do mine like this to keep it looking nice.
$sql = "SELECT * FROM senateinfo " .
"WHERE state = (Variable = "stname") " .
"ORDER BY last_name, first_name')";
Related
Why do I see in several examples of mysql queries via php the syntax:
$q = "CREATE TABLE '$tablename' ('$t_id_name')";
or things similar to that? I'm asking about the single quotes around the variable names. Is this required in MySQL strings? If I echo the string, it seems to expand the variables whether the quotes are there or not.
And would this pose a problem if this were done for something that was intended to be an integer?
To answer your question, the quotes are necessary, but not to expand the variable. A typical SQL query would look like this:
$q = "SELECT * FROM `table` WHERE `first_name` = 'user3475234'";
Now, consider the following example:
<?php
$tablename = "users";
$user = "user3475234";
$q = "SELECT * FROM `$tablename` WHERE `first_name` = '$user'";
echo $q;
This will display: SELECT * FROM `users` WHERE `first_name` = 'user3475234'. Note that the quotes weren't necessary to output the string, but they were a necessary part of the query.
That being said, code like this opens your script to SQL injection. I won't explain too much about it, since there are plenty of resources discussing it, but consider the example where someone's username is user3475234' OR 1==1--. This username will effectively return all users in the table.
You must use backticks (`) for field or table name especially if the field or table name are same with mysql command. And you need to use single-quote (') for value.
$queryDetails = mysql_query("SELECT * from members WHERE username = '$current_url' ");
I'm trying to use fwrite to create a page on register. This is the only thing what is going wrong. As I'm using 'fwrite', I cannot use speech marks as it ends the 'fwrite' command.
I've tried escaping the query out;
$queryDetails = mysql_query('SELECT * from members WHERE username = \'$current_url\' ');
But that hasn't worked. I can't use " as it closes the fwrite.
Any help?
The full code is
$queryDetails = mysql_query('SELECT * from members WHERE username = \'$current_url\' ');
$queryNumRowsDetails = #mysql_num_rows($queryDetails);
if ($queryNumRowsDetails != 0){
//collect data from SQL database
while ($row = mysql_fetch_assoc($queryDetails)){
$dbUsername = $row['username'];
$dbClub = $row['club'];
$dbReputation = $row['reputation'];
}
}
else{
die("There was a problem gathering user data.");
}
And if I try to escape the ' as shown in the second code block. It goes to the "There was a problem gathering user data."
$current_url is a variable collecting the current URL and taking away a few bits, leaving only a username remaining. Meaning example.com/users/AdziHades/index.php equates to just AdziHades.
Though your question lacks the information indicating what's not working, it looks like your problem with the query might be that you're using single quotes and trying to have it evaluate the variable inside. For example:
$myvar = 2;
$mystring = "I have $myvar apples.";
In that code, $mystring would evaluate to I have 2 apples.. If, instead, you use single quotes, like so:
$myvar = 2;
$mystring = 'I have $myvar apples.';
You will get I have $myvar apples.'. This is because single quotes will not evaluate variables automatically. Note: I am NOT referring to the quotes used in the query itself (around $current_url), I'm talking about the quotes around the entire query.
You have two options here. The 'easy' option is to just concatenate the value of the variable. The better, more future-proof way is to switch to using prepared statements with PDO (here is a page that explains why you should be using this and how to use it or at least mysqli. Prepared statements will allow for more secure queries without you having to manually escape your values to prevent SQL injection. I highly recommend you look at going down this route. The mysql_* extensions you're using have been deprecated and will most likely cause you problems in the future.
new to php and am enrolled on a course, so can ask tutor tomorrow if this is more complicated than i think it might be!
I have an sql query, and it works fine. But I am trying to add and 'and' in the select statement.
This is what I have at the minute
$query = "SELECT * from table1 where table1.age <= " . $_POST['min_age'] ;
I have a 'region' input on my linked html page and want results to be returned only if the min_age and region values match those inputted by the user.
I have tried adding an 'and where' but it doesn't work and I am not sure if it is because of the multiple "'s or if what I am trying to do needs a different method?
Thanks
If you need multiple conditions, just separate them with AND:
... WHERE table1.age <= ? AND table1.region = ?
No need to use WHERE again. Just like you wouldn't need to use if() more than once if you were writing a complex condition in PHP.
PS: This isn't directly related to your question, but you should get into the habit of not putting $_POST or $_GET variables directly into your SQL queries. It's a good way to get hacked! Ask your tutor about "SQL injection," or read my presentation SQL Injection Myths and Fallacies.
I know you're just starting out, but if you were training to be an electrician, you would place a high priority on learning how to avoid being electrocuted or how to avoid causing a fire.
Here's how I would write your query using mysqli. One advantage of using query parameters is you never need to worry about where you start and end your quotes.
$query = "SELECT * from table1 where table1.age <= ? AND table1.region = ?";
$stmt = $mysqli->prepare($query) or trigger_error($mysqli->error, E_USER_ERROR);
$stmt->bind_param("is", $_POST["min_age"], $_POST["region"]);
$stmt->execute() or trigger_error($stmt->error, E_USER_ERROR);
The other good habit I'm showing here is to always report if prepare() or execute() return an error.
If you must interpolate variables into your SQL, first make sure you protect the variables either by coercing the value to an integer, or else by using a proper escaping function like mysqli_real_escape_string(). Don't put $_POST variables directly into the string. Also you don't have to stop and restart the quotes if you use PHP's syntax for embedding variables directly in double-quoted strings:
$age = (int) $_POST["min_age"];
$region = $mysqli->real_escape_string($_POST["region"]);
$query = "SELECT * from table1 where table1.age <= {$age}
AND table1.region = '{$region}'";
I like embedding variables in strings - "I like $verb $noun in strings!"
But then I was designing a database access script:
$sqlfragment = "SELECT * from " . $databasetableprefix . "_user";
Lovely. But what happened to my embedding variables in strings?!
I want to do something like this:
$sqlfragment = "SELECT * from $databasetableprefix_user";
But that will be interpreted as from the variable $databasetableprefix_user.
So I would use a space:
$sqlfragment = "SELECT * from $databasetableprefix _user";
But spaces aren't allowed in database table names, so that won't work.
(What I want is this resulting string: "SELECT * from cc_user", if cc is the prefix.)
Can I create this string using variable embeds? Perhaps a sort of 'nothing' character, that will stop PHP from thinking it is part of the variable name, but not carry through to the SQL?
$sqlfragment = "SELECT * from {$databasetableprefix}_user";
Wrap the variable in {} like so:
$sqlfragment = "SELECT * from {$databasetableprefix}_user";
You have to use curly brackets to tell PHP where the variable name begins and ends, as described in detail in the PHP manual.
$sqlfragment = "SELECT * from {$databasetableprefix}_user";
Also, be very careful using variables to generate SQL statements, as it can easily become a security risk if you don't carefully track the source of your variables or validate their values.
when I write a query for MySQL, usually use a form like this:
$column= "column_name";
$query = "SELECT * FROM table_name WHERE \"".$column."\"" = \"some_value\" ";
if I want to avoid using the \"". sequence for the variables, can I use this other form or there could be some compatibility issues or some other problem ?
$column= "column_name";
$query = "SELECT * FROM table_name WHERE \"$column\" = \"some_value\";
In both of these cases what you're doing is fine, but a few notes:
1) What you're doing in your first form is using the strings like string literals, which means you can/should use single quotation marks instead of double quotation marks, as they are parsed much faster.
$column = 'column_name';
$query = 'SELECT * FROM table_name WHERE ' . $column . ' = "some_value"';
What you're doing in the second example is also fine, it just depends on the reason you're trying to avoid using the escape character, but if you're just doing it for the sake of readability, what you have is fine.
Worth noting is that handling queries the way you're doing here is getting deprecated and you should take a look at PDO and inject your values that way.
Edit Per Comments Above - Removed " from around the column.
Yes, you can.
Strings delimited with double quotes are interpreted by the PHP parser.
to make sure, the variable is identified correctly, put it into curly brackets
Example
$variable = 1;
$array = array( 1,2 );
$object = new stdclass();
$object->member = 1;
$string = "You can basically put every kind of PHP variable into the string. This can be a simple variable {$variable}, an array {$array[0]} or an object member {$object->member} even object methods.";
If you want PHP to take the $variable literally without interpretation, put the string into single quotes.
Another method I really like to use for queries is the heredoc notation
$sqlQuery = <<< EOQ
SELECT
"field"
FROM
"table"
WHERE
"id" = '{$escapedValue}'
EOQ;
One more note:
In SQL you should delimit values with the single quote, and identifiers like table name and field names with double quotes (ANSI compatible) or the back tick ```