0

I have some code that returns error Undefined variable: dblink:

This code is from a legacy system. "dblink" variable appears only inside this function in this one file.

function db_connect($dbhost, $dbuser, $dbpass, $dbname = "") {
    if (!strlen($dbuser) || !strlen($dbpass) || !strlen($dbhost))
        return null;

    @$$dblink = mysql_connect($dbhost, $dbuser, $dbpass);
    if ($$dblink && $dbname)
        @mysql_select_db($dbname);
    //set desired encoding just in case mysql charset is not UTF-8
    if ($$dblink) {
        @mysql_query('SET NAMES "UTF8"');
        @mysql_query('SET COLLATION_CONNECTION=utf8_general_ci');
    }
    return $$dblink;
}

I am not entirely sure what to make of @$$variable and $$variable. I assume that @ means "suppress warnings", and "$$variable" just means "${value of $variable}", which does not make sense.

I am planning to rename this to just $dblink and see what happens. There may possibly be a historical reason for this in earlier PHP versions, or maybe at one time such code did make sense, and the answer to how it made sense is what my question is seeking.

sjagr
  • 15,983
  • 5
  • 40
  • 67
Dennis
  • 7,907
  • 11
  • 65
  • 115
  • you have answered for your question. @ is bad practice and no need of dynamic variable $$ there. so replace is as $dblink and go forward. – Asik Nov 17 '14 at 16:15
  • 2
    `I am planning to rename this to just $dblink and see what happens.` - Might I suggest that this is what you should do *before* posting questions? – MatBailie Nov 17 '14 at 16:16
  • 2
    but then it will make sense and there will be no question – Dennis Nov 17 '14 at 16:17
  • 1
    More likely a typo cover up. `$$dblink` will simply become the empty variable name here `${''}`. And while you're already fixing code, investigate a rewrite using PDO. – mario Nov 17 '14 at 16:18
  • I think the `@` might be an attempt to suppress the result of `mysql_connect`. The double `$$` doesn't make sense, especially since `$dblink` doesn't seem to be in scope. Maybe this is just an error someone has made before. If the result of `db_connect` is not used directly, this might have gone unnotices for ages. – GolezTrol Nov 17 '14 at 16:18
  • If you want to programming, never say this: `and see what happens`. If you do not know exactly what you are doing with your code, then don't do that. – vaso123 Nov 17 '14 at 16:19
  • actually a few of magical learning moments in my code learning were directly from `try this and see what happens`. I don't think doing so is a bad practice across the board. – Dennis Nov 17 '14 at 16:21

1 Answers1

4

It's clearly wrong, but will still work:

$$foo = 'bar';
echo $foo; // Returns nothing
echo $$foo; // Returns bar
echo $$otherUndefinedVar; // Returns bar
echo ${''}; // Returns bar
echo ${NULL}; // Returns bar
if ($$foo) echo 'true'; // Returns true

This is because PHP will just use the default value of an empty string (in the context of string-based functionality) while throwing a notice that $foo is undefined, then you're essentially working with a variable named $ (but you can't access it without using ${''}.)

And since there was a notice being thrown, I bet this previous developer used @ to suppress the notice without questioning why the usage of $$ didn't work. But I'm not psychic!

Unfortunately I can't answer your question since it's too broad (and like I mentioned, not a psychic ;), but hopefully the code example above gives some clarity as to why it still worked - it's a common problem for amateur programmers to "beat the code up" until it works the way they want to. Often making very very bad mistakes in the process.

sjagr
  • 15,983
  • 5
  • 40
  • 67
  • 1
    hey cool I learned something. Namely, this construct => `${''}`. I haven't seen it before. – Dennis Nov 17 '14 at 16:23
  • @Dennis There's a lot of neat examples of variable variables! [Notably this one too](http://php.net/manual/en/language.variables.variable.php#97222) – sjagr Nov 17 '14 at 16:25
  • Except `$dblink` isn't defined anywhere. – AbraCadaver Nov 17 '14 at 16:32
  • @AbraCadaver But `$$dblink` now is, so an `if ($$dblink)` would still validate. As that code stands there's no avoiding those notices unless the notice was suppressed with `@` in each instance, but that function would 100% work still. And once `$$dblink` is returned, it's no longer an issue anywhere outside of the function. – sjagr Nov 17 '14 at 16:34