Passing database connection by reference in PHP - php

The question is if a database connection should be passed in by reference or by value?
For me I'm specifically questioning a PHP to MySQL connection, but I think it applies to all databases.
I have heard that in PHP when you pass a variable to a function or object, that it is copied in memory and therefore uses twice as much memory immediately. I have also heard that it's only copied once changes have been made to the value (such as a key being added/removed from an array).
In a database connection, I would think it's being changed within the function as the query could change things like the last insert id or num rows. (I guess this is another question: are things like num rows and insert id stored within the connection or an actual call is made back to the database?)
So, does it matter memory or speed wise if the connection is passed by reference or value? Does it make a difference PHP 4 vs 5?
// $connection is resource
function DoSomething1(&$connection) { ... }
function DoSomething2($connection) { ... }

A PHP resource is a special type that already is a reference in itself. Passing it by value or explicitly by reference won't make a difference (ie, it's still a reference). You can check this for yourself under PHP4:
function get_connection() {
$test = mysql_connect('localhost', 'user', 'password');
mysql_select_db('db');
return $test;
}
$conn1 = get_connection();
$conn2 = get_connection(); // "copied" resource under PHP4
$query = "INSERT INTO test_table (id, field) VALUES ('', 'test')";
mysql_query($query, $conn1);
print mysql_insert_id($conn1)."<br />"; // prints 1
mysql_query($query, $conn2);
print mysql_insert_id($conn2)."<br />"; // prints 2
print mysql_insert_id($conn1); // prints 2, would print 1 if this was not a reference

Call-time pass-by-reference is being depreciated,so I wouldn't use the method first described. Also, generally speaking, resources are passed by reference in PHP 5 by default. So having any references should not be required, and you should never open up more than one database connection unless you really need it.
Personally, I use a singleton-factory class for my database connections, and whenever I need a database reference I just call Factory::database(), that way I don't have to worry about multiple connections or passing/receiving references.
<?php
Class Factory
{
private static $local_db;
/**
* Open new local database connection
*
* #return MySql
*/
public static function localDatabase() {
if (!is_a(self::$local_db, "MySql")) {
self::$local_db = new MySql(false);
self::$local_db->connect(DB_HOST, DB_USER, DB_PASS, DB_DATABASE);
self::$local_db->debugging = DEBUG;
}
return self::$local_db;
}
}
?>

It isn't the speed you should be concerned with, but the memory.
In PHP 4, things like database connections and resultsets should be explicitly passed by reference. In PHP 5, this is done automatically, so you don't have to make it explicit.
BTW, singleton methods for creating database handles are a good idea: you can do $db = & Database::Connection(); and always get the correct handle. This saves you from using a global and the static method can do extra magic (like opening it automatically) for you. Just be careful of when your application scales enough that it needs multiple databases: then your magic function will have to know how to hand you back the correct one. IME this is not hugely difficult; the basic way to solve that is for the code layer that needs the DB handle to know how to ask for the correct one.

A database connection does not actually hold the underlying values, so you don't have to worry about losing assignments made inside a function. Metaphorically, you can think of a DB connection as, say, a runway number -- "OK, DB Connection 12 is cleared to be used for a query" -- The query and result set use the connection, and may need exclusive access for awhile, but the connection does not know anything about the underlying data.

A few people have said that you don't need to worry about this for PHP 5. This is incorrect, if you have a database OBJECT that you're using for all access. In that case, you do need to pass by reference, otherwise it instantiates a new DB object, which (often) creates a new connection to the database.
I discovered this using XDebug & WinCacheGrind, which kindly shows all the destructors that get called - in my case, a halfdozen or more database objects.
To clarify: The reason I point this out is that this is a common way of using Database connections, instead of the raw connection resource.

i don't really have a specific answer for php, but in general it would seem to me that you would want to pass this by reference if you are not explicitly sure that you encounter performance issues when passing by value.

Generally speaking, references are not faster in PHP. It's a common misconception, because they are semantically similar to C pointers, so people familiar with C often assume they work the same way. Not so. In fact, references are a tiny bit slower than copies, unless you actually assign to the variable (Which in any case is bad style, unless the variable is an object).
PHP has a mechanism called copy-on-write, which means that a variable isn't actually copied before it needs to. You can pass a huge data structure to a function; As long as it just reads from it, it makes no difference. A reference however, needs an additional entry in the internal registers, so it would actually take some extra processing (Though barely noticeable).

Related

PHP OOP variables from database

I am currently working on a CMS and am learning how to use OOP.
My question is: How do I take variables set in a mysql database and use them on my website?
Lets say I have 2 columns, one called var_name and var_content.
How would I use it so that $var->sitetitle; echos out whatever it matches up to in my database?
I don't know what this is called, if anyone could lead me in the right direction, I appreciate it!
Right now, I have this:
require_once("classes/database.class.php");
$database = new database();
$database->set_value('sitevariables', $database_prefix . "sitevariables");
$database->set_value('host', $database_host);
$database->set_value('pass', $database_pass);
$database->set_value('user', $database_user);
$database->set_value('table', $database_table);
I wanted it so I could use $database->host to get my mysqli server. It's basically the same thing as I want to do, except it takes from the database to get and set the values
you can define a function to get variables, once your database connection is set up (I sadly not think it is possible to query the database for credentials to connect to that vary database. kind of spiraling thing there.)
this takes into account that var() is a member function of your database() class. Since I don't have your database class, I don't think the way I'll query the database is like yours, but you will be able to fix that.
function var($var_name) {
$stmt = $this->query('SELECT var_content FROM variables WHERE var_name=?');
$stmt->execute(array($var_name));
return $stmt->fetch(PDO::FETCH_COLUMN);
}
$sitetitle = $database->var('sitetitle');

Escape SQL queries in PHP PostgreSQL

I have a website with lots of PHP files (really a lot...), which use the pg_query and pg_exec functions which do not
escape the apostrophe in Postgre SQL queries.
However, for security reasons and the ability to store names with
apostrophe in my database I want to add an escaping mechanism for my database input. A possible solution is to go
through every PHP file and change the pg_query and pg_exec to use pg_query_params but it is both time consuming
and error prone. A good idea would be to somehow override the pg_query and pg_exec to wrapper functions that would
do the escaping without having to change any PHP file but in this case I guess I will have to change PHP function
definitions and recompile it which is not very ideal.
So, the question is open and any ideas that would
allow to do what I want with minimum time consumption are very welcome.
You post no code but I guess you have this:
$name = "O'Brian";
$result = pg_query($conn, "SELECT id FROM customer WHERE name='{$name}'");
... and you'd need to have this:
$name = "O'Brian";
$result = pg_query_params($conn, 'SELECT id FROM customer WHERE name=$1', array($name));
... but you think the task will consume an unreasonable amount of time.
While it's certainly complex, what alternatives do you have? You cannot override pg_query() but it'd be extremely simple to search and replace it for my_pg_query(). And now what? Your custom function will just see strings:
SELECT id FROM customer WHERE name='O'Brian'
SELECT id FROM customer WHERE name='foo' OR '1'='1'
Even if you manage to implement a bug-free SQL parser:
It won't work reliably with invalid SQL.
It won't be able to determine whether the query is the product of intentional SQL injection.
Just take it easy and fix queries one by one. It'll take time but possibly not as much as you think. Your app will be increasingly better as you progress.
This is a perfect example of when a database layer and associated API will save you loads of time. A good solution would be to make a DB class as a singleton, which you can instantiate from anywhere in your app. A simple set of wrapper functions will allow you to make all queries to the DB go through one point, so you can then alter the way they work very easily. You can also change from one DB to another, or from one DB vendor to another without touching the rest of the app.
The problem you are having with escaping is properly solved by using the PDO interface, instead of functions like pg_query(), which makes escaping unnecessary. Seeing as you'll have to alter everywhere in your app that uses the DB, you may as well refactor to use this pattern at the same time as it'll be the same amount of work.
class db_wrapper {
// Singleton stuff
private $instance;
private function __construct() {
// Connect to DB and store connection somewhere
}
public static function get_db() {
if (isset($instance)) {
return $instance;
}
return $instance = new db_wrapper();
}
// Public API
public function query($sql, array $vars) {
// Use PDO to connect to database and execute query
}
}
// Other parts of your app look like this:
function do_something() {
$db = db_wrapper::get_db();
$sql = "SELECT * FROM table1 WHERE column = :name";
$params = array('name' => 'valuename');
$result = $db->query($sql, $params);
// Use $result for something.
}

PHP: how would I use this simple class?

I was looking around for more "correct" login/logout portions of code, and found this one:
http://snipplr.com/view/1079/auth/
I got two questions though that stop me from using it.
1: How would I instantiate the class, and use it in my script?(I know PHP but am just befuddled for some reason)
2: there's the following lines:
global $db;
$db->query("sql here...");
How on earth does that make a database object? I think maybe I should create an object like $db = mysql_connect(...) outside the script, and global is calling it from outside the class?
If I know how to call this class, others will seem like a breeze, this is really helpful to me!
That code is dangerous, you should not use it in it's current state.
It blindly trusts $_COOKIE and creates SQL queries using string concatenation, without properly escaping input. Malicious users can easily perform SQL injection on any application using that class.
The presence of the var keyword, the presence of a constructor using the same name as the class and the lack of access control keywords in front of the methods tells me that the code was written for PHP4, not PHP5. It will still run, though
Both of these are fixable problems. First, let's address your questions.
The code written by #Delan Azabani is a good example of how to use the class.
The code is confusing. At first, it looks like the code is using a real database object instead of the old, low-level functions provided by the mysql extension. But then it goes and calls functions from the mysql extension! It's probably someone's custom-written wrapper. The code isn't actually creating a database object, it's simply referencing the value of $db in the global scope, as you suspect.
You've mentioned that you're using the mysql extension. I urge you to reconsider and use PDO or mysqli instead. Not only will this class work with either (though with some changes to mitigate the glaring security hole), but your own code will be better off using the more modern, safer techniques used in PDO and mysqli.
Let's fix the login method, using PDO.
public function login($username, $password) {
global $db;
$sth = $db->prepare("SELECT user_id FROM users WHERE username = ? AND password = ?");
$sth->execute(array($username, $password));
if($sth->rowCount() == 1) {
$this->user_id = $sth->fetchColumn();
...
Let's go over what changed. First, we added query placeholders, those are the question marks. The prepare method returns a statement handle, which you're already probably familiar with. Next, we tell the prepared statement to run itself using the execute method, passing an array of variables. The variables will be automatically escaped for you and then inserted into the query in place of the placeholders.
After the query has run, we use rowCount to pull back the number of matching rows. We want exactly one. Because we're pulling back the first column of the first row, we then use fetchColumn to grab just that bit of data.
The rest of the login method is just fine.
The check method needs similar fixing up.
public function check($username, $password) {
global $db;
$sth = $db->prepare("SELECT user_id, password FROM users WHERE username = ?");
$sth->execute(array($username));
if($sth->rowCount() == 1) {
list($db_user_id, $db_password) = $sth->fetch(PDO::FETCH_NUM);
if(md5($db_password . $this->salt) == $password) {
$this->user_id = $db_user_id;
...
Once again, we prepare a query with placeholders, then execute with the actual variables. Again we want only one row, but this time we want everything in the row. We'll use PDO::FETCH_NUM to tell fetch that we want a numerically indexed array, then we'll take the two resulting entries in the array and stuff them in $db_user_id and $db_password, using them where the old code called mysql_result. PDO doesn't let you pick and choose different columns from the same row using fetchColumn.
If you wanted to use the mysqli extension instead, there's a bit more work to be done. I hope I've convinced you to use PDO instead, though!
The rest of the class is, eh, adequate. Make sure to adjust the $domain class variable at the top to match your actual domain name, it's used in the cookies.
global $db just allows the global database pointer $db to be accessed from inside the class method. You need to create the database by running mysql_connect and mysql_select_db. The entire class is in class Auth, so instantiate an Auth object before doing anything else (well, after connecting to the database, of course).
You can then call the methods inside your Auth object. For example, if a login form submits to login-post.php, you can have this code inside:
$m = new Auth();
if ($m -> login($_POST['u'], $_POST['p'])) {
header('Location: /');
exit;
} else {
header('Location: login?wrong=1');
exit;
}
Looks like the code you posted is just assuming you have a variable defined in your global scope called $db that looks like a wrapper class to the native PHP MySQL resource. So yes, you should create $db outside in the global scope (i.e. not inside a class), but it's expecting a custom class.
I did a little searching, and it looks like he's using THIS class: http://snipplr.com/view/27966/class-db/
It asks you to create an ini file called "crunksauce.ini" (I kid you not) in the same directory as the executing script, and contains configuration variables. The config file should like this:
database = <your database name>
host = <your db host>
user = <your db user>
pass = <your db password>
After creating the config file, you can create the db object like this:
$db = new Db();

Concurrency Problem

I'm having what seems to be a concurrency problem while using MySQL and PHP + Propel 1.3. Below is a small example of the "save" method of a Propel object.
public function save(PropelPDO $con = null) {
$con = Propel::getConnection();
try {
$con->beginTransaction();
sleep(3); // ignore this, used for testing only
parent::save($con);
$foo = $this->getFoo(); // Propel object, triggers a SELECT
// stuff is happening here...
$foo->save($con);
$con->commit();
} catch (Exception $e) {
$con->rollBack();
throw $e;
}
}
The problem is the $foo object. Let's say we get two calls of the example method one after another in a very short time. In some cases, if the second transaction reads $foo...
$foo = $this->getFoo();
... before the first transaction has had the chance to save it...
$foo->save($con);
... $foo read by the second transaction will be outdated and bad things will happen.
How can I force the locking of the table Foo objects are stored in so that subsequent transactions can read from it only after the first one has finished its work?
EDIT: The context is a web application. In short, in some cases I want the very first request to do some data modification (which happens between fetching and saving of $foo). All subsequent requests should not be able to do the modification. Whether the modification will occur or not depends on the fetched $foo state (table row attribute). If two transactions fetch the same $foo, the modification will occur twice which causes a problem.
when you load this existing row to the screen/application, load the LastChgDate too. when you save it, use "AND LastChgDate=thevalue". check the affected row count of the update, if it is zero, return an error "someone else has already saved this record", and rollback and other changes. With this logic in place you can only save a row if it the same as when you loaded it. for new rows, INSERT, this is not necessary because they are new.
In MySQL, I think you can use SELECT FOR UPDATE to accomplish the lock.
Another option is to use the GET_LOCK and RELEASE_LOCK MySQL function calls to create named locks that you would use to control access to the resource.
There are some downsides to these approaches. I haven't used them myself very much and they are MySQL specific but they could work for you.

What is the best way to store configuration variables in PHP?

I need to store a bunch of configuration information in PHP.
I have considered the following....
// Doesn't seem right.
$mysqlPass = 'password';
// Seems slightly better.
$config = array(
'mysql_pass' => 'password'
);
// Seems dangerous having this data accessible by anything. but it can't be
// changed via this method.
define('MYSQL_PASSWORD', 'password');
// Don't know if this is such a good idea.
class Config
{
const static MYSQL_PASSWORD = 'password';
}
This is all I have thought of so far. I intend to import this configuration information into my application with require /config.inc.php.
What works for you with regard to storing configuration data, and what are best practices concerning this?
I've always gone with option #2 and just ensure that no one but the owner has ANY sort of access to it. It's the most popular method among PHP applications like Joomla, vBulletin, Gallery, and numerous others.
First method is too messy to me (readability) and the third is WAY too dangerous to do. I've never thought about the Class method, so someone else can provide their input on that one. But I guess it's fine so long as the right access is used on the class' usage.
Example..
define('EXAMPLE1', "test1"); // scenario 1
$example2 = "test2"; // scenario 2
function DealWithUserInput($input)
{
return eval($input);
}
Now this example of code is really dumb, but just an example. Consider what could be returned by the function depending on which scenario the user could try to use in their input.
Scenario 2 would only cause an issue if you made it a global within the function. Otherwise it's out of scope and unreachable.
I'd say it also depends of userbase a bit. If configurations has to be very user friendly or user has to have ability to change config via web etc.
I use Zend Config Ini for this and other settings are stored in SQL DB.
I generally use the second method... When handling database connections I generally open a connection at the beginning of the request, then close it at the end. I have a function that establishes the connection, then removes the username/password from the global array (with the unset() function), This prevents other parts of the system from accessing the "sensitive" mysql connection data.
I'm also with option 2 for most config values. If you were going to implement the Class then I would tie the specific values to the Class that it affects instead of a general config Class.
In your example, your Class would be for database connections and an instance would save the password, db_name, etc. This would encapsulate the data properly and also provide an easy means to create multiple connections if that was ever needed.

Categories