how better code prefixes in MySQL tables with PHP? - php

I'm going to write PHP script, that uses table prefix for MySQL tables. Should I write all of requests like for example
$db_query='select * from '.$tbl_prefix.'sometable;';
or it's possible to set some variable, that will add this prefix to all queries?
For example, I'm performing request
$db_query='select * from sometable;';
and MAGIC adds prefix to table itself, so for MySQL query will look like
select * from pref_sometable;

Your first sample is the way to go; you'll need to prepend the prefix each time. It may make it easier to make this into a function though (incase you ever need to update anything, it would be far better to only have to update one location instead of multiple):
function _table($table) {
global $tbl_prefix;
return $tbl_prefix . $table;
}
$db_query = 'SELECT * FROM ' . _table('sometable') . ';';

There's no MySQL command to do that, you must implement it in your code just like you do at first. So:
$db_query='select * from '.$tbl_prefix.'sometable;';
Is fine.
If you don't want to add a prefix on each query, you can create an object like this:
class database {
function select($qry,$database) {
$db_query="select " . $qry . " from myprefix_" . $database;
// $res = query($db_query);
return $res;
}
}
$db_query=database->select("*","sometable");
// echo $db_query;
$db_query=database->select("playernick","sometable");
// echo $db_query;
That's not 100% PHP, it's just and idea so you can get it.

Related

PHP7/mysql PDO custom function

I'm trying to migrate an application written in PHP 5.2, but I'm having trouble creating the correct syntax for custom functions. This works perfectly in the old syntax, but I get a fatal error with this.
Essentially, I'd like to create a function to make it easy to get an email address from a database table that's associated with a unique id. I wrote the code below based on what works in PHP 5.2.
function getemail($id) {
$email_query = $con->query("SELECT email FROM admin WHERE id='$id'");
$rs = $email_query->fetch(PDO::FETCH_ASSOC);
return $rs;
}
Then I could use something like below to call this function.
foreach($con->query('SELECT * FROM admin') as $row) {
echo $row['id'] . ' ' . $row['name'] . ' ' . getemail($row['id']) . '<br>';
}
Any direction to help with this issue is greatly appreciated.
Ok, I have a tool for such a transition, which combines the simplicity of old mysql functions with safety of PDO (if used properly) - Simple yet efficient PDO wrapper
Having set it up, all you need is a code like this:
function getemail($id) {
return DB::run("SELECT email FROM admin WHERE id=?", [$id])->fetchColumn();
}
called like this
echo getemail(1); // admin#example.com

Display data returned by function in PHP MySQL

This is the one thing that I am trying absolutely first time. I have made few websites in PHP and MySQL as DB but never used functions to get data from database.
But here is the thing that I am trying all new now as now I want to achieve reusability for a bog project. I wanted to get the order details from DB (i.e. MySQL) through PHP Function. I am bit confused that how to print values returned by a PHP function.
Function wrote by me is as below:
function _orderdetails(){
$sql = "Select * from orders WHERE 1";
$result = DB::instance()->prepare($sql)->execute()->fetchAll();
return $result;
}
Please let me know how i can print these values and value returned by above function is an array.
I tried by calling function directly through print_r(_orderdetails());
Please let me know:
Efficient way of iterating through this function to Print Values.
Is there any other approach that can be better worked upon?
You cannot chain fetchAll() to execute() like this.
Besides, for a query that takes no parameters, there is no point in using execute(). So change your function like this
function _orderdetails(){
$sql = "Select * from orders WHERE 1";
return DB::instance()->query($sql)->fetchAll();
}
and so you'll be able to iterate results the most natural way
foreach (_orderdetails() as $order) {
echo $order['id'] . '<br />';
}
You can also use ->fetch();
Instead of ->fetchAll();
There some other functions that also work as a worker to iterate through the next row in the table.
You can check PDO for more functions at:
http://php.net/manual/en/book.pdo.php
In your PHP code that will call this function use the following
print_r(_orderdetails());
//to get all the result set... I mean all the values coming from this function.
You can also use the function and use -> after the function call, then put the variable name as follows:
To iterate through the values of this function:
$value_arr = _orderdetails();
foreach ($valur_arr as $value) {
echo $value . '<br />';
}
This way you will echo 1 column from the database table you are using.

Calling PHP functions from within the same file

I have a php file called choose.php where inside i echo some HTML i.e. a select element.
I am using PDO to populate the select element from a mysql database.
the code i have written works perfectly but when i put it into a function and try to call it i get an error telling me that i cannot declare said method again.
the code is thus:
echo '<select>';
$sql = "SELECT name FROM people";
$res = $conn->prepare($sql );
$res ->execute();
while ( $row = $res ->fetch() )
{
echo '<option value = "' . $row['name '] . '">' . $row['name '] . '</option>';
}
echo '</select>';
in other words the function would look like this:
function getnames()
{
$sql = "SELECT name FROM people";
$res = $conn->prepare($sql );
$res ->execute();
while ( $row = $res ->fetch() )
{
echo '<option value = "' . $row['name '] . '">' . $row['name '] . '</option>';
}
}
Why cant i call the method inside the echoed select element?
echo '<select>';
getnames();
echo '</select>';
Also how would i accomplish this by placing the method in another php file to keep it tidy?
Why cant i call the method inside the echoed select element?
Because the method body references $conn, which is supposedly a global variable and not in scope inside the method body. You can verify that this is the problem (and "fix" it) with
function getnames()
{
global $conn;
// the rest as before
}
Now, although this will make the problem go away, what you propose here is not a good way to organize things. There are several issues:
getnames uses a global variable ("invisible argument") -- note that you would not have had reason to ask this question if this had been corrected!
The name of the method is misleading -- it doesn't "get" something, it prints HTML.
The method is unusable for anything else other than its specific purpose -- if you wanted to do something else with the names (e.g. print a table) you would have to write another method.
You are interleaving straight HTML output (the <select> tag) with business logic (querying the database). It's better to do all the business logic up front (keep the results you need in variables) and then do the HTML all in one go.
All of the above are serious deficiencies of the chosen approach and none of them would be present in a well built application. I suggest that instead of making the problem go away you would be better served by refactoring the code to address these, and the problem will fix itself on the way.
Code Review would be an excellent place to ask a question along the lines of "I have this code and this recommendation -- how would I implement it properly?" if you need extra help.
You are trying to access $conn variable which is not available in your function scope.
To access $conn variable inside your function use global, like below:
global $conn;
How are you loading the file in which the getnames function is defined? Try using require_once and making sure it's not being included more than once - already defined means it's be defined and the file is being called again, hence trying to define it again
If you're calling that same code multiple times on your page it will get very heavy to load. I would recommend just running it at the top of the page and putting the data to a variable, then echoing that variable at each location that you need it
So your code in the top of your page
$sql = "SELECT name FROM people";
$res = $conn->prepare($sql );
$res ->execute();
$outputData = '';
while ( $row = $res ->fetch() ){
$outputData .= '<option value = "' . $row['name '] . '">' . $row['name '] . '</option>';
}
Then
echo '<select>'.$outputData.'</select>';

How to filter function parameters

What is a proper way to filter parameters passed in functions? The goal is to make the function secure, especially when working with a database.
Example:
function user_profile($user_id)
{
//get user's profile data
$query = "SELECT * FROM `users` WHERE `user_id` = $user_id";
}
$user_id is a URI segment.
Other general examples are welcomed.
To escape strings, use the same method you'd use outside the function:
$user_id= mysql_real_escape_string($user_id);
If you're expecting the value to be, for example, an integer and would like to return error from the function if it isn't, you can do something like:
if (!is_int($user_id)) {
return FALSE;
}
else // do you query
Or if you expect it to match some specific pattern, do so with preg_match():
// For example, $user_id should be 4 letters and 4 numbers
if (!preg_match("/^[A-Z]{4}[0-9]{4}$/", $user_id)) {
return FALSE;
}
else // do you query
There's a couple of ways. The OLD way is to use mysql_real_escape_string(). However, many people nowadays complain bitterly about this, and say the proper way is to use prepared statements.
Create a filter class to handle all your filtering. Before you pass the variable into the function as a parameter, pass it through the filter class first. Or run the parameter through the filter class in the first line of your function.
So essentially, you're creating an abstract layer that 'filters'.
So the kind of filtering you're wanting to do in your scenario is to filter against sql injection/code injections.
So create a wrapper with this filter class around the mysql_real_escape_string() function.
The idea is to create an extensible filter class that can be used anywhere else in your application that is conceptually high level enough to handle all future needs.
final class Filter
{
static public function sqlInjections($some_parameter)
{
// my code to prevent injections by filtering $some_parameter
return mysql_real_escape_string($some_paramters);
}
static public function badWords()
{
// code in the future that can be added to filter bad words
}
}
call it like so $filtered_parameter = Filter::sqlInjections($some_paramter);
If your user_id field is a string in your database, then, you'll use mysql_real_escape_string(), or mysqli_real_escape_string(), or PDO::quote() -- depending on the API you're working with :
$query = "SELECT * FROM `users` WHERE `user_id` = '"
. mysql_real_escape_string($user_id) . "'";
or
$query = "SELECT * FROM `users` WHERE `user_id` = '"
. mysqli_real_escape_string($user_id) . "'";
or, with PDO -- provided that $db is a PDO object :
$query = "SELECT * FROM `users` WHERE `user_id` = '"
. $db->quote($user_id) . "'";
But, if it's an integer, you should make sure that the value passed to it is indeed an integer -- which is generally done using intval() :
$query = "SELECT * FROM `users` WHERE `user_id` = "
. intval($user_id);
Edit: I just realized you said it's an URL segment -- so, not an integer. I don't delete this idea, though: it might help someone else who would read this answer.
Another solution would be to not build a query containing that value -- and use prepared statements.
See :
For mysqli : mysqli::prepare()
And with PDO : PDO::prepare()
Use mysql_real_escape_string()
$query = "SELECT * FROM users WHERE user_id = '" . mysql_real_escape_string($user_id) . "'";
You can do two or Three complementary ways to prevent SQL injection:
The escape functions commented above.
Query the other way around:
function user_profile($user_id)
{
//get user's profile data
$query = "SELECT * FROM users WHERE {$user_id} = user_id";
}
User prepare and execute functions/methods if your database engine allow it
http://php.net/manual/en/pdo.prepare.php
http://www.php.net/manual/en/pdostatement.execute.php

Function to escape different variable types in MySQL Query

I got sick of writing queries in my PHP as:
"WHERE '" . Database::escape($var) . "'";
The escape() function just calls mysql_real_escape_string() - but it's there so I can extend support to other databases later.
Having to single quote strings in the query was making my code more cluttered. So my idea was to create an other function in my database class to 'prepare' a variable for a query:
static public function prepare($var)
{
if (is_object($var) || is_array($var) ) {
return " '" . Database::escape(serialize($var)) . "' ";
} else if (is_bool($var)) {
return ' ' . (int)$var . ' ';
} else if (is_int($var)) {
return ' ' . $var . ' ';
} else if (is_string($var) || is_float($var)) {
return " '" . Database::escape($var) . "' ";
} else {
throw new Exception('Unsupported variable type [' . gettype($var) . ']');
}
}
Now the benefit here is that, I don't need to worry about which variables I pass to a query. However it raises two questions:
Am I handling each variable type properly?
For what reason (if any) should I not do this?
Yes, just use parameterised queries and it will Just Work. That is the right solution, and it's not terribly tricky.
In PHP, use PDO to do this, its API is much more sane than mysql_ or mysqli_ and moreover, it can throw exceptions on errors and do other nice things.
You probably shouldn't be doing this. Here's why: mysqli::prepare or PDO::prepare
As for your function itself, what happens if you have something stored in a string (say "5") that you want to store as an int? It'll still quote it anyway.
You are looking for a) pepared statements and b) a database abstraction layer (like PDO).
What you are trying to do on your own has been solved already, you should not roll your own implementation.
If you go down that road you'll notice that this:
"... WHERE '" . Database::escape($var) . "'"
is pointless and dangerous. A clear separation of SQL code and parameters requires you to be more explicit and gets you on the safe side against SQL injection the same time:
"--- WHERE SomeField = ?" /* the parameter (?) will be filled elsewhere */
It's worth noting that true vendor-independence in the database field is somewhere between hard and impossible, depending on your needs and priorities. So trying to write portable SQL could turn out as an exercise in futility unless you are willing to sacrifice a lot. For MySQL it starts even with the LIMIT clause, which you will find impossible to port to, say, SQL Server.
You can try
$sql = "SELECT * FROM SomeTable WHERE userid = '{Database::prepare($userid}'";
to alleviate the typing issues. Though my suggestion is that if you are accepting inputs from a form, why not setup Database::prepare() to run through the $_REQUEST or $_POST to clean them up, or spit out a copy?
This is how I do it:
$safe_post = InputCleaner::clean($_POST);
$sql = "SELECT * FROM table WHERE userid = {$safe_post['userid']}";

Categories