4

I'm in learning mode here, very new to PHP, so I'm working with a code sample. Please forgive my use of 'global' here, but I want to understand php variable scoping.

Here is myGlobals.php:

<?php 
     global $db_server;
   // other code not shown
?>

Here is connectToDb.php:

<?php
      require_once 'myGlobals.php';

      // no declared functions in this file, all inline code
      $db_server = mysql_connect(.....);
      mysql_select_db( "theDatabase", $db_server);
?>

Here is addDbRecords.php:

<?php
       require_once 'myGlobals.php';

       // other inline code.....
       doAddDeleteRecord($db_server);

function doAddDeleteRecord($db_server)
{
  //global $db_server;

  if( !mysql_query($query, $db_server))
   {
         // handle the error...
   }
 }
?>

Here is index.php:

<?php
      require_once 'myGlobals.php';
      require_once 'connectToDb.php';
      require_once 'addDbRecords.php';

     // this is simplified, just trying to show that everything in inline code
 ?>

Here is the problem. When I call doAddDeleteRecord($db_server) inside the file addDbRecords.php above, $db_server is not valid -- it is null -- when I call mysql_query(.., $db_server, ...) -- this is the error message:

"Warning: mysql_query() expects parameter 2 to be resource, null given in C:\xampp\htdocs\addDbRecords.php on line 29"

So I tried using the 'global' declaration inside doAddDeleteRecord() (commented out above) -- no change.
The mysql_query(...) still fails with a NULL value for $db_server.

I know the mysql_connect(....) works because other code pulls all my records out of my database successfully (using a SELECT) and the existing records get displayed correctly in the browser.

So in my opinion, the fact that $db_server is declared with 'global' should mean that the scope of $db_server is such that once mysql_connect(...) is called -- at file scope in all my files, $db_server will be a valid connection to my database.

I'm only trying to learn about php scoping, not OOAD or anything else (for now). Why is $db_server() null here?

wantTheBest
  • 1,682
  • 4
  • 43
  • 69
  • never use require_once. use require – dynamic Jun 10 '11 at 18:12
  • 3
    @yes123: Why's that? Most of the answers [here](http://stackoverflow.com/questions/186338/why-is-require-once-so-bad-to-use) seem to claim that that's a myth. – Lightness Races in Orbit Jun 10 '11 at 18:14
  • 1
    If you still use the old mysql_ interface functions, you don't have to pass the connection handle around. If there is only one opened, it is used implicitly. (Unless you pass a null value.) – mario Jun 10 '11 at 18:15
  • @yes123 Uh, that's horrid advice, especially if there are function declarations in the required file. – ceejayoz Jun 10 '11 at 18:15
  • @yes123: Why would you not recommend require_once over require? – Jeff Hubbard Jun 10 '11 at 18:16
  • 1
    @require_once: It might indeed be a cause of the troubles here, because the `myglobals.php` script is really just loaded **once**, where OP might have intended it to be included multiple times. (The general disadvisal makes no sense however.) – mario Jun 10 '11 at 18:16
  • using `global $db_server;` inside `doAddDeleteRecord()` should work correctly. Are you absolutely sure you don't also have `$db_server` referenced in that file anywhere, like `global$ dbserver;`? This would redeclare it as NULL. – Michael Berkowski Jun 10 '11 at 18:17
  • @mario: no it won't. The global only needs to be defined once. This won't cause these sorts of problems. – Chris Eberle Jun 10 '11 at 18:18
  • @Chris: I get that. It needs no redeclarations. But if the myglobals script was to be used for localizing the variable in multiple spots (which is not senseful), then the _once call is what made it not work out. – mario Jun 10 '11 at 18:20
  • It looks like it ought to work... Are you sure there isn't something else causing `mysql_connect()` to fail? You don't *need* to run `global $db_server;` multiple times, so I too have to disagree with `yes123` here: You should always use the `_require()` variations **unless** the file contains only procedural code and is intended to be run multiple times. – Darien Jun 10 '11 at 18:22
  • 1
    @mario: except that the OP isn't using `include[_once]` inside of a function. The OP is including it at the top of each file, which no matter how you cut it would still require the use of the `global` modifier to use those variables within functions. – Chris Eberle Jun 10 '11 at 18:27
  • In hindsight, I don't think you need `global` at all in your code. You're always referencing the variable from the global scope. – Lightness Races in Orbit Jun 10 '11 at 18:30
  • @Chris: All examples are shortened. And that the commands occur at the top is not indicative for execution in the global scope (scripts might itself be included from within functions). Either way using a plain `global` var declaration is the better alternative to the `myGlobals` include. – mario Jun 10 '11 at 18:31

2 Answers2

5

So, you have:

<?php 
     global $db_server;
   // other code not shown
?>

and you include this where needed:

require_once 'myGlobals.php';
// other inline code.....
doAddDeleteRecord($db_server);

The problem is that if you already included 'myGlobals.php' elsewhere, it won't be included here. So you can't guarantee that the global will be brought into scope.

Instead, write:

require 'myGlobals.php';
// other inline code.....
doAddDeleteRecord($db_server);

Or take the much better approach of just:

// other inline code.....
doAddDeleteRecord($GLOBALS['db_server']);
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • +1 you use `global` inside a function to tell PHP you want to use a globally scoped variable instead of creating a privately scoped variable that is only visible in the function. – Fosco Jun 10 '11 at 18:17
  • I disagree, I have a four-file set-up working right now and they **all** use `require_once()`. The very first time you execute the statement `global $db_server` is sufficient. – Darien Jun 10 '11 at 18:27
  • @Darien: Only if you always include the file at the global scope. – Lightness Races in Orbit Jun 10 '11 at 18:28
  • Actually the problem with my answer is that the `global` isn't required _at all_ in any of his files. – Lightness Races in Orbit Jun 10 '11 at 18:29
  • That's a problem too, but what I mean is that the side-effects of `global $foo;`, when (pointlessly) done in global scope, are also global... as long as it has been included once, early enough, you never need to include it again. It's the same as if you had defined a function or class in global scope. – Darien Jun 10 '11 at 18:36
1

I think there's a concern with scope hiding; that is, you're using the same name ($db_server) for the global and for the function local variable. The function local scope hides the global variable name. If you have a global, you don't need to pass it to your function; if you do, don't use the same name for it.

Paul Sonier
  • 38,903
  • 3
  • 77
  • 117
  • I changed the variable name to "function doAddDeleteRecord($db_server_global_scope)" and used db_server_global_scope in the call to mysql_query(.., $db_server_global_scope, ...) -- no change. Just FYI, I did not use 'global' anywhere before, only added it to try to fix this. If I remove 'global' everywhere it's still the same problem. Note: the call to doAddDeleteRecord($db_server_global_scope) that is failing is when my 'add record' form posts back to the file -- could the fact that I'm re-entering the code due to a POST somehow make the db_server null? – wantTheBest Jun 10 '11 at 19:02