I'm trying to do a PDO select that will turn into a table with several rows. I'm just getting an empty page, no error message. Here is my code
//variables for connection are stated elsewhere
$pdo_connect = new PDO($dsn, $db_host_admin_username, $db_host_admin_pass);
$pdo_connect->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE,PDO::FETCH_OBJ);
$pdo_connect->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);
$sql_property_info_request = "SELECT * FROM property_offered_bid WHERE bid_id_property_offered_bid=:bid_id";
$stmt_property_info_request = $pdo_connect->prepare($sql_property_info_request);
$stmt_property_info_request->execute(['bid_id' => $bid_id]);
$result_property_info_request = $stmt_property_info_request->fetch();
while ($row = $stmt_property_info_request->fetch()) {
echo $row['property_offered_property_offered_bid']."<br />\n";
}
I've searched if it was PDO parameters and nothing seems to solve that.
Related
I'm trying to take a query string param such as ?table=products and have mysql return all the rows for the "products" table in mysql. I tried running the code below in my browser, but I just get a blank white page. I know the mysql server/username/pass information is correct, I've tested the query in mysql and it works fine.
I guess I have two question:
What am I doing wrong?
How come I can't see any error messages when php has an issue?
e.g. code:
<?php
// Get query string parameter value
$keys = array_keys($_GET);
$key = $keys[0];
$value = $_GET[$key];
// Setup connection to mysql database
$serverName = "localhost";
$username = "root";
$password = "password";
$dbname = "webserver";
$conn = new mysqli($serverName, $username, $password, $dbname);
// SQL query
$sql = "SELECT * FROM $value";
$result = $conn->query($sql);
// Print results
echo $result;
?>
Follow the instuctions on below link to enable php.ini errors
How do I get PHP errors to display?
VULNERABLE IMPLEMENTATION WARNING
The above comments clearly mention the side effects of this implementation.
Since knowing the actual bug is a developer's right! Continue reading the answer keeping the safety of software and its users in mind.
You are trying to print $result which is not valid since its an object.
You can do the following instead:
$response = array();
$sql = "SELECT * FROM $value";
$result = $conn->query($sql);
// Print results
if ($result) {
while($row = $result->fetch_array(MYSQL_ASSOC)) {
$response[] = $row;
}
}
echo json_encode($response);
What am I doing wrong?
Sadly, pretty much everything.
// Get query string parameter value
$keys = array_keys($_GET);
$key = $keys[0];
$value = $_GET[$key];
You are dereferencing a named value based on its position. And its totally unnecessary. Consider:
$value=$_GET['table'];
...
$conn = new mysqli($serverName, $username, $password, $dbname);
Where is your error checking to see if $conn was initialized?
$result = $conn->query($sql);
again, no error checking.
echo $result;
$result here is a mysqli_result object. You need to call some methods on it to get the data out.
while ($row = $result->fetch_array(MYSQLI_ASSOC)) {
var_export($row);
}
How come I can't see any error messages when php has an issue?
Have you tested that the default handlers produce output in your browser? You're not overriding the config in php.ini in the code you've shown us. Did you check your logs?
ini_set('diplay_error', 1);
error_reporting(E_ALL);
I just get a blank white page
Would it be so hard to put
print "finished";
at the end of the code? Then you'd at least know if the code executed.
The main issue you have right now is you need to get the results
while ($row = $result->fetch_assoc()) {
//do something with row
}
See ( for mysqli->query method )
http://php.net/manual/en/mysqli.query.php
false on failure and mysqli_query() will return a mysqli_result object on success
See ( for the result objects definition )
http://php.net/manual/en/class.mysqli-result.php
Now as others mentioned I would never just concatenate user data into your query. Imagine a hacker knows the name of a valid table, not hard considering your sending it through the request. All they would have to do is send a value like this:
$value = 'real_table; DROP DATABASE';
And your query becomes.
$sql = "SELECT * FROM real_table; DROP DATABASE";
I won't say that this would actually work as there are ( maybe ) some restrictions on running multiple queries in a single request,user permissions etc... That might save your bacon, but I certainly wouldn't risk it.
So you have 2 choices.
Use a white list of tables
Query the DB for the schema
The first one is easy to do, make a list of tables
$whitelist = [
'table1',
'table2'
];
Then compare your user input
$safeTable = false;
if( false !== ($index = array_search($table, $whitelist))) {
$safeTable = $whitelist[$index];
}else{
//log error and
exit();
}
// SQL query
$sql = "SELECT * FROM $safeTable";
$result = $conn->query($sql);
For the second one,
$schema = $conn->query('SELECT `TABLE_NAME` FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` LIKE "database"');
$whitelist = [];
while ($row = $result->fetch_assoc()) {
$whitelist[] = $row['TABLE_NAME'];
}
$safeTable = false;
if( false !== ($index = array_search($table, $whitelist))) {
$safeTable = $whitelist[$index];
}else{
//log error and
exit();
}
// SQL query
$sql = "SELECT * FROM $safeTable";
$result = $conn->query($sql);
This will return a list of all the tables in that database, from which you can build an array and then compare. The nice thing about the second one is that if you add a table then you don't have to change the code, which may or may not be a good thing. You have to have a user with permission to read from information_schema database. And you have to do an additional query.
-note- I am not directly using the users input, I'm using their input to find my data. It's less prone to breaking when there is a coder error. Consider this:
///all my codes are broken;
--if(!in_array($_GET['table'], $whitelist))) {
-- //log error and
-- exit();
--}
// SQL query
$sql = "SELECT * FROM {$_GET['table']}";
$result = $conn->query($sql);
Against this:
$safeTable = false;
// all my codes are broken
-- if( false !== ($index = array_search($_GET['table'], $whitelist))) {
-- $safeTable = $whitelist[$index];
-- }else{
-- //log error and
-- exit();
-- }
// SQL query
$sql = "SELECT * FROM $safeTable"; //$safeTable is undefined or false;
$result = $conn->query($sql);
Were using our code for inclusion, instead of exclusion. So if it breaks, it's never included. The other way, if it breaks it's never excluded. Which is not a situation we want to be even remotely possible.
I hope that helps you understand some of the pitfalls. The #1 rule for SQL (or anything on the web), is Never Trust the User. Never put their data into your SQL.
I have in the database a list of links from which I want to take some data.
All the script is working, except the part when I'm taking the link from the DB and paste it in Simple DOM function.
"
include ('utile/db.php');
include_once('utile/simple_html_dom.php');
$dbh = new PDO("mysql:host=$servername;dbname=$dbname;charset=utf8;", $username, $password);
$sth = $dbh->query("SELECT link FROM pilots where year = '2007' and Contry ='CZ' and zboruri <> '101' limit 3 ");
foreach ($sth as $url) {
functie ($url['link']);
}
function functie($lin){
$linkul=file_get_html("$lin");
// pages number
$paging = $linkul->find('div[class*=paging]',0);
echo $paging;
$numar=-4;
foreach($paging->find('a') as $element=>$item){$numar++;}
echo $numar;
}
"
I receive the following error:
Fatal error: Call to a member function find() on null in C:\xampp\htdocs\para\teste.php on line 269
If I change the link manually it will work.
I think it is something related how I extract the link from DB and insert it the function.
Thank you
The issue with fetchALL in foreach.
The line changed:
foreach($sth->fetchAll() as $url){
The final code that is working:
include ('utile/db.php');
include_once('utile/simple_html_dom.php');
$dbh = new PDO("mysql:host=$servername;dbname=$dbname;charset=utf8;", $username, $password);
$sth = $dbh->query("SELECT link FROM pilots where zboruri > '101' limit 3");
foreach($sth->fetchAll() as $url){
functie ($url['link']);
}
function functie($lin){
var_dump($lin);
$linkul=file_get_html("$lin");
$paging = $linkul->find('div[class*=paging]',0);// pages number
echo $paging;
$numar=-4;
foreach($paging->find('a') as $element=>$item){$numar++;}
echo $numar;
}
Thank you for advices.
When I use PDO I use prepared statements, so the syntax on getting the result of the query is a little different... but I think that you need to fetch a row from your $sth since it would be a record set. Here's a snippit of what I do
$dbconn = new PDO('mysql:host='.$hostname.';port='.$dbPort.';dbname='.$dbName.';charset=utf8', $dbuser, $dbpass,array(PDO::MYSQL_ATTR_FOUND_ROWS => true));
$dbconn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$result=$dbconn->prepare($query);
$result->execute($arr);
if(!$result){
// do your error handling, result is either false
// for error or contains a recordset
$errorMessage=$dbconn->errorInfo();
}
$result->setFetchMode(PDO::FETCH_ASSOC);
while($row=$result->fetch()){
// do stuff here, $row is an associative array w/ the
//keys being the column titles in your db table
print_r($row);
}
So i'm trying to pass PDO Query by using php, like this(index.php):
include("dbconn.php");
mysqlConnect("'SELECT * FROM users WHERE name =' . $conn->quote($name))", "jeff");
while my dbconn file that contains the function is(dbconn.php):
function mysqlConnect($queryString, $name) {
// DB Credentials
$dbName = 'db';
$dbUser = 'root';
$dbPass = '';
$dbHost = 'localhost';
try {
$conn = new PDO("mysql:host=$dbHost;dbname=$dbName", $dbUser, $dbPass);
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Here goes the first parameter, then it uses the second parameter as a variable
$data = $conn->query($queryString);
// So the output should be this:
// $data = $conn->query('SELECT * FROM myTable WHERE name = ' . $conn->quote($name));
foreach($data as $row) {
print_r($row);
}
} catch(PDOException $e) {
echo 'ERROR: ' . $e->getMessage();
}
}
So in my function call the php actually executes the $conn->quote($name)) code, making my application not work.
How should i do this? is this allowed in php?
Edit:
or in other words: i call a function and give it 2 parameters, one of the parameters(even tho it's in double quotes) is executed by php which shouldn't happen. How can i fix this
The way you wrote, it will never work. You just have to learn to distinguish a string literal from executable code.
Anyways, you don't need such a frankenstein at all. There is already a mechanism to put your variable in the query, called prepared statements. You just have to use them.
There are other issues with your code too. I've described them all in the article I wrote recently, The only proper guide on PDO, I am sure you will find it interesting - all the issues like wrong error handling, utterly wrong way to connect, lack of prepared statements - all described there. Having all of them solved, here goes the proper function you need:
function pdo($sql, $data=[])
{
global $pdo; // you can add a call to your favorite IoC here.
$stmt = $pdo->prepare($sql);
$stmt->execute($data);
return $stmt;
}
used as
include("dbconn.php");
$user = pdo("SELECT * FROM users WHERE name = ?", ["jeff"])->fetch();
var_dump($user);
this is how PDO have to be used.
By returning a statement, you'll be able to use all the power of PDO, getting data you need in one line, say a list
$news = pdo("SELECT * FROM news ORDER BY id DESC")->fetchAll();
var_dump($news); // already an array
or just a single value
$count = pdo("SELECT count(*) FROM posts WHERE author=?", [$id])->fetchColumn();
var_dump($count); // already a number
or simply by iterating results one by one
$news = pdo("SELECT * FROM news ORDER BY id DESC")->fetchAll();
foreach ($news as $row) {
var_dump($row);
}
and so on.
I'm trying my hand at custom functions in PHP in order to streamline a lot of stuff I'm otherwise doing manually. I'm damn new to custom functions so I'm not sure the limitations. Right now I'm trying to get data with MySQLi using custom functions Here's the code, and then I'll explain the issue:
function connect_db($db = 'db_username') {
iconv_set_encoding("internal_encoding", "UTF-8");
mb_language('uni');
mb_internal_encoding('UTF-8');
# $mysqli = new mysqli('host',$db,'password',$db);
if(mysqli_connect_errno())
{
die('connection error');
}
}
This one seems to be working fine. It's the next function I'm having more trouble with.
edit: Updated thanks to Jeremy1026's response
function do_query($db = 'default_db', $query) {
connect_db();
$result = $mysqli->query($query);
if(!$result){
trigger_error("data selection error");
}
while($row = $result->fetch_assoc()){
$result_array[] = $row;
}
return $result_array;
}
My host forces database names and usernames as the same, so if the db name is 'bob' the username to access it will be 'bob' as well, so that's why $db shows up twice in the connection.
The problem I'm having is that these two functions are in functions.php and being called from another page. I want to be able to pull the results from the query in that other page based on the column name. But I also need to be able to do this with formatting, so then maybe the while() loop has to happen on that page and not in a function? I want this to be as universal as possible, regardless of the page or the data, so that I can use these two functions for all connections and all queries of the three databases I'm running for the site.
God I hope I'm being clear.
Big thanks in advance for any suggestions. I've googled this a bit but it's tough to find anything that's not using obsolescent mysql_ prefixes or anything that's actually returning the data in a way that I can use.
Update: I'm now getting the following error when accessing the page in question:
Fatal error: Call to a member function query() on a non-object in /functions.php`
with the line in question being $result = $mysqli->query($query);. I assume that's because it thinks $query is undefined, but shouldn't it be getting the definition from being called in the page? This is that page's code:
$query = "SELECT * FROM `table`";
$myArray = do_query($db, $query);
echo $myArray['column_name'];
In your 2nd function you aren't returning any data, so it is getting lost. You need to tell it what to return, see below:
function do_query($db = 'default_db', $query) {
connect_db();
$result = $mysqli->query($query);
if(!$result){
trigger_error("data selection error");
}
while($row = $result->fetch_assoc()){
$result_array[] = $row;
}
return $result_array;
}
Then, when using the function you'll do something like:
$myArray = do_query($db, 'select column from table');
$myArray would then be populated with the results of your query.
This is a half-answer. The following single function works in place of the two.
function query_db($database, $new_query) {
$sqli = new mysqli('host', $database, 'password', $database);
$sqli->set_charset("utf8");
global $result;
if($result = $sqli->query($new_query)){
return $result;
}
}
By adding global $result I was able to access the results from the query, run from another page as
query_db("username","SELECT * FROM `column`");
while($row = $result->fetch_assoc()){
print_r($row);
}
It's more streamlined than I have without functions, but it's still not idea. If I have the connection to the database in another function, it doesn't work. If I try to put the while loop in the combined function, it doesn't work. Better than nothing, I guess.
Sample code:
$infoArray = array();
require_once("connectAndSelect.php");
// Connects to mysql and selects the appropriate database
$sql = "SOME SQL";
if($results = mysql_query($sql))
{
while($result = mysql_fetch_array($results, MYSQL_ASSOC))
{
$infoArray[] = $result;
}
}
else
{
// Handle error
}
echo("<pre>");
print_r($infoArray);
echo("</pre>");
In this sample code, I simply want to get the result of my query in $infoArray. Simple task, simple measures... not.
I would have enjoyed something like this:
$sql = "SOME SQL";
$infoArray = mysql_results($sql);
But no, as you can see, I have two extra variables and a while loop which I don't care for too much. They don't actually DO anything: I'll never use them again. Furthermore, I never know how to call them. Here I use $results and $result, which kind of represents what they are, but can also be quite confusing since they look so much alike. So here are my questions:
Is there any simpler method that I
don't know about for this kind of
task?
And if not, what names do you
give those one-use variables? Is
there any standard?
The while loop is really only necessary if you are expecting multiple rows to be returned. If you are just getting one row you can simply use mysql_fetch_array().
$query = "SOME SQL";
$result = mysql_query($query);
$row = mysql_fetch_array($result);
For single line returns is the standard I use. Sure it is a little clunky to do this in PHP, but at least you have the process broken down into debug-able steps.
Use PDO:
<?php
/*** mysql hostname ***/
$hostname = 'localhost';
/*** mysql username ***/
$username = 'username';
/*** mysql password ***/
$password = 'password';
try {
$dbh = new PDO("mysql:host=$hostname;dbname=mysql", $username, $password);
$sql = "SELECT * FROM myTable";
$result = $dbh->query($sql)
//Do what you want with an actual dataset
}
catch(PDOException $e) {
echo $e->getMessage();
}
?>
Unless you are legacied into it by an existing codebase. DONT use the mysql extension. Use PDO or Mysqli. PDO being preferred out of the two.
Your example can be come a set of very consise statements with PDO:
// create a connection this could be done in your connection include
$db = new PDO('mysql:host=localhost;dbname=your_db_name', $user, $password);
// for the first or only result
$infoArray = $db->query('SOME SQL')->fetch(PDO::FETCH_ASSOC);
// if you have multiple results and want to get them all at once in an array
$infoArray = $db->query('SOME SQL')->fetchAll(PDO::FETCH_ASSOC);
// if you have multiple results and want to use buffering like you would with mysql_result
$stmt = $db->query('SOME SQL');
foreach($stmt as $result){
// use your result here
}
However you should only use the above when there are now variables in the query. If there are variables they need to be escaped... the easiest way to handle this is with a prepared statement:
$stmt = $db->prepare('SELECT * FROM some_table WHERE id = :id');
$stmt->execute(array(':id' => $id));
// get the first result
$infoArray = $stmt->fetch(PDO::FETCH_ASSOC);
// loop through the data as a buffered result set
while(false !== ($row = $stmt->fetch(PDO::FETCH_ASSOC))){
// do stuff with $row data
}