Converting this function to PDO - php

I'm working on convert this on PDO
function SystemConfig($str)
{
$tmp = mysql_query("SELECT ".$str." FROM server_status LIMIT 1") or die(mysql_error());
$tmp = mysql_fetch_assoc($tmp);
return $tmp[$str];
}
I tried this :
function SystemConfig($str)
{
global $bdd;
$tmp = $bdd->prepare("SELECT ? FROM server_status LIMIT 1");
$tmp->bindValue(1, $str, PDO::PARAM_INT);
$tmp->execute();
$tmp_res = $tmp->fetch(PDO::FETCH_ASSOC);
return $tmp_res[$str];
}
?>
But it's return 'users_online' and not the value (10000 on the database) (PS : SystemConfig('users_online');)
Someone can help me ?
Sincerly,

function SystemConfig($str)
{
static $row;
global $bdd;
if (!$row)
{
$stm = $bdd->query("SELECT * FROM server_status");
$row = $stm->fetch();
}
return $row[$str];
}
but better reorganize your table, because table with sole row is a nonsense
function SystemConfig($str)
{
global $bdd;
$stm = $bdd->prepare("SELECT value FROM server_status WHERE param = ?");
$stm->execute(array($str))
return $stm->fetchColumn();
}

You can only bind value parameters with PDO. You cannot bind column names, table names, or anything else.
You'd still have to manually construct this query by concatenating strings. To make cracker's life harder use a whitelisting approach:
if(!in_array($str, array('users_online', 'users_offline', 'free_memory')) die('...')
// rest of the function.
(But please, stop using the deprecated mysql_* functions. Upgrade to mysqli instead. Or use PDO, but without parameter binding for this one single query)

Related

How to check if column equals a value and do somthing if true? [duplicate]

This question already has answers here:
Single result from database using mysqli
(6 answers)
Closed 2 years ago.
I am trying to write a function that will check for a single value in the db using mysqli without having to place it in an array. What else can I do besides what I am already doing here?
function getval($query){
$mysqli = new mysqli();
$mysqli->connect(HOST, USER, PASS, DB);
$result = $mysqli->query($query);
$value = $mysqli->fetch_array;
$mysqli->close();
return $value;
}
How about
$name = $mysqli->query("SELECT name FROM contacts WHERE id = 5")->fetch_object()->name;
The mysql extension could do this using mysql_result, but mysqli has no equivalent function as of today, afaik. It always returns an array.
If I didn't just create the record, I do it this way:
$getID = mysqli_fetch_assoc(mysqli_query($link, "SELECT userID FROM users WHERE something = 'unique'"));
$userID = $getID['userID'];
Or if I did just create the record and the userID column is AI, I do:
$userID = mysqli_insert_id($link);
Always best to create the connection once at the beginning and close at the end. Here's how I would implement your function.
$mysqli = new mysqli();
$mysqli->connect(HOSTNAME, USERNAME, PASSWORD, DATABASE);
$value_1 = get_value($mysqli,"SELECT ID FROM Table1 LIMIT 1");
$value_2 = get_value($mysqli,"SELECT ID FROM Table2 LIMIT 1");
$mysqli->close();
function get_value($mysqli, $sql) {
$result = $mysqli->query($sql);
$value = $result->fetch_array(MYSQLI_NUM);
return is_array($value) ? $value[0] : "";
}
Here's what I ended up with:
function get_col($sql){
global $db;
if(strpos(strtoupper($sql), 'LIMIT') === false) {
$sql .= " LIMIT 1";
}
$query = mysqli_query($db, $sql);
$row = mysqli_fetch_array($query);
return $row[0];
}
This way, if you forget to include LIMIT 1 in your query (we've all done it), the function will append it.
Example usage:
$first_name = get_col("SELECT `first_name` FROM `people` WHERE `id`='123'");
Even this is an old topic, I don't see here pretty simple way I used to use for such assignment:
list($value) = $mysqli->fetch_array;
you can assign directly more variables, not just one and so you can avoid using arrays completely. See the php function list() for details.
This doesn't completely avoid the array but dispenses with it in one line.
function getval($query) {
$mysqli = new mysqli();
$mysqli->connect(HOST, USER, PASS, DB);
return $mysqli->query($query)->fetch_row()[0];
}
First and foremost,
Such a function should support prepared statements
Otherwise it will be horribly insecure.
Also, such a function should never connect on its own, but accept an existing connection variable as a parameter.
Given all the above, only acceptable way to call such a function would be be like
$name = getVal($mysqli, $query, [$param1, $param2]);
allowing $query to contain only placeholders, while the actual data has to be added separately. Any other variant, including all other answers posted here, should never be used.
function getVal($mysqli, $sql, $values = array())
{
$stm = $mysqli->prepare($sql);
if ($values)
{
$types = str_repeat("s", count($values));
$stm->bind_param($types, ...$values);
}
$stm->execute();
$stm->bind_result($ret);
$stm->fetch();
return $ret;
}
Which is used like this
$name = getVal("SELECT name FROM users WHERE id = ?", [$id]);
and it's the only proper and safe way to call such a function, while all other variants lack security and, often, readability.
Try something like this:
$last = $mysqli->query("SELECT max(id) as last FROM table")->fetch_object()->last;
Cheers

Parametrized PDO query for LIMIT clause

I have seen similar questions answered already but I can't seem to apply the same solutions to my code.
$a=1;
$results = DB::query('SELECT posts.`postbody`, posts.`filepost`, posts.`likes`, posts.`posted_at`, users.`id`, posts.`id_of_post` FROM posts, users WHERE posts.`post_id` = users.`id` ORDER BY id_of_post DESC LIMIT :a', array(':a'=>$a));
class DB {
private static function connect() {
$pdo = new PDO('mysql:host=127.0.0.1;dbname=SocialNetwork;charset=utf8', 'root', '');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
return $pdo;
}
public static function query($query, $params = array()) {
$statement = self::connect()->prepare($query);
$statement->execute($params);
if (explode(' ', $query)[0] == 'SELECT') {
$data = $statement->fetchAll();
return $data;
}
}
}
For the record the following code works fine.
$results = DB::query('SELECT posts.`postbody`, posts.`filepost`, posts.`likes`, posts.`posted_at`, users.`id`, posts.`id_of_post` FROM posts, users WHERE posts.`post_id` = users.`id` ORDER BY id_of_post DESC LIMIT 1');
Not ideal, but you could do away with the PDO parameters.
$a = 1;
$sql = "SELECT stuff FROM table LIMIT {$a};";
Then run your query from the $sql string.
As stated in the previous answers if you do not define:
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
You have to define the parameter to be binded as integer:
foreach($params as $key => $value){
if(is_numeric($value))
$statement->bindParam($key,$value,PDO::PARAM_INT);
else
$statement->bindParam($key,$value,PDO::PARAM_STR);
}
$statement->execute();
This is still not a perfect solution, but if you trust the key value pairs(ie they are from code, not user input) it's good enough.
In MySQL's LIMIT clause, it's an error to do this:
LIMIT '1'
Because LIMIT must take an integer, not a string.
If PDO is configured to emulate prepare() (by interpolating values into your SQL string), it's likely to make the interpolated value a quoted string, which will cause an error.
To avoid this, you must use a native integer as your bound variable and you just specify PDO::PARAM_INT.
$statement = self::connect()->prepare($query);
$statement->bindParam('a', $a, PDO::PARAM_INT);
$statement->execute();
That will let the driver know to avoid putting quotes around the interpolated value.
You can also avoid the error if you set the PDO attribute to disable emulated prepares. I always do this, because I don't trust "emulated prepare."
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
See also my tests I wrote up here: Parametrized PDO query and `LIMIT` clause - not working

Getting a multi dimensional array from a mysql database

Right now im using Mysqli to retrieve data from a Mysql Database, The code im using is difficult to understand and from my understanding has depreciated functions or itself in entire is depreciated.
If i could get some insight and maybe some updated techniques on my Qoal of retrieving data from a mysql DB.
mysqli prepared statements
What i have so far is this:
$param = 1;
$mysqli = new mysqli("127.0.0.1", "user", "password", "databaseName");
$mysqli->query('SELECT reply_id FROM replies WHERE reply_topic = ? ORDER BY reply_date ASC');
$mysqli->bind_param('i',$param)
$mysqli->execute();
$row = bind_result_array($mysqli);
while($mysqli->fetch()){
$set[$row['']] = getCopy($row);
}
$mysqli->free_result();
return $set;
function bind_result_array($stmt)
{
$meta = $stmt->result_metadata();
$result = array();
while ($field = $meta->fetch_field())
{
$result[$field->name] = NULL;
$params[] = &$result[$field->name];
}
call_user_func_array(array($stmt, 'bind_result'), $params);
return $result;
}
function getCopy($row)
{
return array_map(create_function('$a', 'return $a;'), $row);
}
You need to clean up the call on the database first. $mysqli->query has send the query before you bound parameters and so on.
Replace with the following;
$stmt = $mysqli->prepare('SELECT reply_id FROM replies WHERE reply_topic = ? ORDER BY reply_date ASC');
$stmt->bind_param('i',$param)
$stmt->execute();
The $mysqli->prepare returns a new object that you should bind values to and then execute. It avoids SQL injection!
None of this is depreciated. mysqli_ is exactly what you should use.
As all you want is an array of the results, you can use the following code to do so - no user functions required.
$result = $stmt->get_result();
while ($row = $result->fetch_assoc()) {
$set[] = $row['reply_id'];
}
For each row in the while, each field is saved into an array with the column name as the key. So $row['reply_id'] contains the value of the reply_id column in the database. Above I have saved this value to an array called $set, and when it loops over the next result row it saves the next value to that array too.
You can manipulate the result before or after saving it to the new array, as you see fit.
Hope this helps.

Accessing a MySQL Link Identifier from within a Function

I'm having some difficulty returning an array out of a while lopp which I have in a function. Here is the code I am using. I am meant to be able to return an array of results from the function which contains the id numbers of pictures associated with a particular user id - in this case I want to print_r the array for the user id of 17. When this code isn't in the function it works, but when I place it in the function, no luck. I presume its related to a mistake I am making in the returning of the array. Your help is greatly appreciated.
function picture($id)
{
$sql = "SELECT * FROM avatar WHERE user_id={$id}";
$result = $database->query($sql);
$results = array();
while ($row = mysql_fetch_assoc($result))
{
$results[] = $row;
}
return $results;
}
$results = picture(17);
print_r($results);
Your function can't access your MySQL link identifier
First of all, you're mixing object-oriented paradigm ($database->query($sql)) with procedural paradigm (mysql_fetch_assoc($result)) which will make your code a nightmare to maintain.
Assuming that $database is a mysql_ link identifier, you'll need to pass it into your function in order to access it there.
function getUserAvatar($database, $id){
$sql = 'SELECT * FROM `avatar` WHERE `user_id`=' . intval($id) . ' LIMIT 1;';
$result = mysql_query($database, $sql);
$row = mysql_fetch_assoc($result);
return $row;
}
$results = picture($database, 17);
Don't just copy-paste that, keep reading!
The above will probably work, but if you're allowing a user to pass that user ID into the function, it's quite possible that they'll be able to find a vulnerability to inject an SQL statement of their choice into your MySQL database.
mysql_ functions are deprecated, so you should ideally stop using them and switch to mysqli or PDO. You'll also want to get an understanding of prepared statements in order to prevent SQL injections. If you can't upgrade, look at the mysql_real_escape_string and intval functions and make sure you sanitize all user inputs before processing them.
The resulting code will look something like this, if you switch to mysqli and prepared statements:
function getUserAvatar($db, $userId) {
$stmt = $db->prepare("SELECT * FROM `avatar` WHERE `user_id`=? LIMIT 1;");
$stmt->bind_param("i", $userId);
$stmt->execute();
$res = $stmt->get_result();
return $res->fetch_assoc();
}
$db = new mysqli("localhost", "user", "password", "database");
$result = getUserAvatar($db, 17);
may be you should try this..
function picture($id)
{
$sql = "SELECT * FROM avatar WHERE user_id={$id}";
$result = $database->query($sql);
$row = mysql_fetch_assoc($result);
return $row;
}
$results = picture(17);
print_r($results);

Error while using PDO prepared statements and LIMIT in query [duplicate]

This question already has answers here:
How to apply bindValue method in LIMIT clause?
(11 answers)
Closed 7 years ago.
I'm using PDO in my application. But I have a problem while I'm working with prepared statements in a query that contains LIMIT. What's the problem?
Codes:
$start = 0;
$rows = 20;
$sql = "SELECT * FROM tbl_news ORDER BY date DESC LIMIT ?, ?";
$q = $db->prepare($sql);
$q->execute(array($start , $rows));
Error:
check the manual that corresponds to your MySQL server version for the right syntax to use near ''0', '20''
You can do like this:
$sql = SELECT * FROM tbl_news ORDER BY date DESC LIMIT :start, :rows";
$q = $db->prepare($sql);
$q->bindParam(':start', $start, PDO::PARAM_INT);
$q->bindParam(':rows',$rows, PDO::PARAM_INT);
Regarding to post LIMIT keyword on MySQL with prepared statement , the code below could solve my problem.
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
Thanks Álvaro G. Vicario and Maerlyn
It is a known bug which was fixed in 5.5.6 from memory.
From the article:
LIMIT doesn't allow variables in any context.
Its arguments must be integer constants.
Further Edit: (There is contention on the matter)
User variables are accepted arguments of LIMIT clause in prepared statements, and SQL syntax for prepared statements can be used in stored procedures.
Third Edit:
This link explains that these should work with prepared statements.
I just stumbled upon the same problem. For me, using my own statement class (extending PDOStatement) with my own execute() method fixed it.
This is the class:
class MyPDOStatement extends PDOStatement {
public function execute($input_parameters = null) {
if (is_array($input_parameters)) {
$i = 1;
foreach ($input_parameters as $p) {
// default to string datatype
$parameterType = PDO::PARAM_STR;
// now let's see if there is something more appropriate
if (is_bool($p)) {
$parameterType = PDO::PARAM_BOOL;
} elseif (is_null($p)) {
$parameterType = PDO::PARAM_NULL;
} elseif (is_int($p)) {
$parameterType = PDO::PARAM_INT;
}
// parameters passed to execute() are input-only parameters, so use
// bindValue()
$this->bindValue($i, $p, $parameterType);
$i++;
}
}
return parent::execute();
}
}
To tell PDO to use this statement class instead of the default one, do this:
$db = new PDO(...);
$db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('MyPDOStatement'));
Now the code in the question will work:
$start = 0;
$rows = 20;
$sql = "SELECT * FROM tbl_news ORDER BY date DESC LIMIT ?, ?";
$q = $db->prepare($sql);
$q->execute(array($start , $rows));
The only thing you have to make shure is that the variables bound to the statement have the correct type, integer. If you have a numeric string, e.g. from the $_GET array, you can do something like this:
if (isset($_GET['start']) && is_numeric($_GET['start'])
&& is_int($_GET['start'] + 0) {
$start = (int) $_GET['start'];
}
I'm not shure if there is an easier way for the last thing, but at least it works fine for me.
date is a reserved word you have to wrap it with back-ticks

Categories