2

I recently began restructuring some of my "copy-paste" database classes I use for projects. I was working over the login class and came across an interesting function.

My Login class has a function that looks like this:

function &db_connect() {
    require_once('mysql.php');
    $db = new DB();
    return $db;
}

What's interesting is it returns a reference to the $db object instead of the actual object. Thats all fine, but then I came across this:

function __construct(&$db) {
    $this->db = $db;
    $this->date = $GLOBALS['date'];
    if ($_SESSION['logged']) {
        $this->_checkSession();
    }
}

That code is used like this:

$db = db_connect();
$user = new User($db);

As you can see, what's actually going on is that I am passing around a reference to the DB instance rather than the actual object. I obviously had my reasons when I wrote this code 3 years ago, so now I'm wondering, why?

Should all my "DB" classes and objects be passed by reference? Does simply passing by value, say, a PDO object, cause it to create new connections? What's correct practice and what should I be using?

jduncanator
  • 2,017
  • 1
  • 18
  • 37
  • possible duplicate of [How to properly set up a PDO connection](http://stackoverflow.com/questions/11369360/how-to-properly-set-up-a-pdo-connection) – tereško Sep 29 '13 at 07:33
  • @tereško My question wasn't specific to PDO (even tho I mentioned it in the name as database connections would be more sensitive to multiple instances than other types). It was more so to see what correct practice I should be using in the future when passing around instance critical objects. – jduncanator Sep 29 '13 at 09:07
  • I would say that the same basic solution applies to all case when you want to share an object between multiple instances. Also, please not that object in PHP 5.0+ are not passed around by references (for more info on that please see [this](https://www.youtube.com/watch?v=_YZIBWQr_yk) and [this](http://www.youtube.com/watch?v=bxxIXPc9IR8) video). – tereško Sep 29 '13 at 09:54
  • @tereško Could you elaborate on that without making me stream youtube videos? – jduncanator Sep 29 '13 at 11:36

2 Answers2

2

The value stored in the variable is an object reference. Passing this reference by value is typically how one would do this -- the & is unnecessary, and provides no benefit here.

Were you to assign to $db from within the constructor, this would change the value of the variable you passed in:

$a = 1;

function foo(&$p) {
    $p = 2;
}

foo($a);
// $a is now 2

I would argue that using & in this case is wrong, as it could lead to unexpected behavior if you changed your code to assign to $db. Suddenly the caller would see their variable change too.

cdhowie
  • 133,716
  • 21
  • 261
  • 264
0

The following program illustrates how objects as arguments are treated in PHP 5:

<?php

class Foo {
  public $value;
  public function __construct($value) { $this->value = $value; }
}

function swap      ($a, $b)   { $tmp = $a; $a = $b; $b = $tmp; }
function swap_refs (&$a, &$b) { $tmp = $a; $a = $b; $b = $tmp; }
function inc       ($a, $b)   { ++$a->value; ++$b->value; }

$a = new Foo(1); $b = new Foo(2);

swap ($a, $b);
printf("swap():      \$a %d, \$b %d\n", $a->value, $b->value);

swap_refs ($a, $b);
printf("swap_refs(): \$a %d, \$b %d\n", $a->value, $b->value);

inc($a, $b);
printf("inc:         \$a %d, \$b %d\n", $a->value, $b->value);

It prints out

swap():      $a 1, $b 2
swap_refs(): $a 2, $b 1
inc:         $a 3, $b 2
Oswald
  • 29,474
  • 3
  • 39
  • 67