Forum Moderators: coopster

Message Too Old, No Replies

$variables return null inside a custom function

         

nolim8ts

11:33 am on Mar 24, 2010 (gmt 0)

10+ Year Member



Hi All,

I'm using the below code inside a custom function and when debugging the code, the $variables always return null. I've validated the config.php without errors.


if(file_exists('config.php'))
{
require_once('config.php');
}

$db_host = $config['db_host'];
$db_database = $config['db_database'];
$db_username = $config['db_username'];
$db_password = $config['db_password'];

Readie

11:35 am on Mar 24, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Well, there's not really much to go by there - but it seems you havn't set the $config array - unless that's declared inside config.php?

If so, I'd change your code to this:

if(file_exists('config.php')) {
require_once('config.php');
} else {
die('File not found.');
}

Matthew1980

12:42 pm on Mar 24, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi there nolim8ts,

Inside this file have you declared $config as an array, then after the file is called (like Readie's suggestion) just do a print_r($config);to ensure that the array is populated as expected, I do exactly the same thing for settings & config on majority of my projects ;-p

Just declare the array in the config file:-

$config = array();

One question though, why do you need to reassign the var's if they are already delared in the config file? Seem's like extra work to me :-)

Cheers,
MRb

nolim8ts

1:58 pm on Mar 24, 2010 (gmt 0)

10+ Year Member



Below is the contents of config.php. When debugging the config file, the array is populated as expected.


<?php
$config = array();

/*** site details ***/
$config['site_name'] = "This Is A Test Website";

/*** database details ***/
$config['db_username'] = "username";
$config['db_password'] = "password";
$config['db_database'] = "website";
$config['db_host'] = "127.0.0.1";

print_r($config)

?>


Below is the code for the function.


function menu_links()
{
try
{
if(file_exists('config.php'))
{
require_once('config.php');
}
else
{
die('File not found.');
}

print_r($config);

$links = "";
$link_type = "menu";

$dbh = new PDO("mysql:host=".$config['db_host'].";dbname=".$config['db_database']."", "".$config['db_username']."", "".$config['db_password']."");
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $dbh->prepare('SELECT link_title, link_location FROM tbl_site_links WHERE link_type = ?');
$stmt->bindParam(1, $link_type);
$stmt->execute();
$stmt->setFetchMode(PDO::FETCH_ASSOC);

foreach($stmt->fetchAll() as $array)
{
$links .= '<li><a href=\"'.$array['link_location'].'\">'.$array['link_title'].'</a></li>';
}

return $links;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
catch(Exception $e)
{
echo $e->getMessage();
}
}

When executing the function, the following error is returned: SQLSTATE[28000] [1045] Access denied for user 'ODBC'@'localhost' (using password: NO)

I've checked the config file and the details are correct.

Matthew1980

3:02 pm on Mar 24, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi there nolim8ts,

You don't need to include the file in the function. Include it in the main index file (or whatever you main file is) and then in the function just put: global $config; This will then look for any reference to that var name & checks against paths that are referred to from any includes that are referenced whilst the script is active ;-p

From there, you can call any part of that array as the global call has or should find the array that it defines as long as the file path from the original include is Ok ;-p

[EDIT]
Not too sure on this though:-

$dbh = new PDO("mysql:host=".$config['db_host'].";dbname=".$config['db_database']."", "".$config['db_username']."", "".$config['db_password']."");

Are all the concatonations needed?

And change this from 127.0.0.1
to localhost, probably not important, but it's a string ;-p

$config['db_database'] = "localhost";

Cheers,
MRb

rocknbil

7:20 pm on Mar 24, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I don't use print_r a lot . . my **GUESS** is that print_r is a global context. Which leads to the solution.

I'm using the below code inside a custom function and when debugging the code, the $variables always return null.


This is because your variables are defined outside the function. Several ways to approach it, a class seems to be the most used but here are some alternatives.

Least desirable as it relies on setting globals:

function menu_links() {
global $config;
//....
$dbh = new PDO("mysql:host=".$config['db_host'].";dbname=".$config['db_database']."",....
//....
}

Preferable in small scripts, pass any variables you need as parameters:

$mylinks = menu_links($config);

function menu_links($config) {
//....
$dbh = new PDO("mysql:host=".$config['db_host'].";dbname=".$config['db_database']."",....
//....
}

The function won't get confused over using the same variable as defined above, remember, it's scope is contained within itself.

Set your variables as constants. These will also have global scope. This is probably the least desirable in a small script context, but for large scripts it's a good thing. your database credentials are, after all, constant throught the program, so it's appropriate.

define("DB_USER","username");
define("DB_PASS",""password");
define("DB_NAME",""website");
define("DB_HOST","127.0.0.1");

function menu_links() {
//....
$dbh = new PDO("mysql:host=".DB_HOST.";dbname=".DB_NAME."",....
//....
}

Matthew1980

8:02 pm on Mar 24, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hey rocknbil,

WRT: print_r() (if I have understood you correctly) will print the value(s) of any var that you give it (not meaning to sound condescending either ;-p) So in this context, as long as the path is there to the file, the array should hold a value if the var isset. It's really quite a handy debugging function. ;-p

But as I said in my earlier post (and the easiest way IMHO) defining the array as a global is for this context at least, the easier way to go, If I have misunderstood the concept of global, please correct me :)

Also defining the constants for the DB login info, would this me a less memory intensive way of doing mass definitions, as I use array's like this myself for the exact same reason, but I had never really considered this until I read your post. An now I'm intrigued.

Sorry for Hi-Jacking the post too ;-p

Cheers,
MRb

rocknbil

11:27 pm on Mar 24, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Nah it's all good . . I just wasn't sure. What I'm saying is, within the context of a function, a variable defined outside it is not available to the function unless you do one of the above. Where it may get confusing is if print_r actually prints a variable from within a function (as above) that is defined outside the function, well, that could lead to some confusing conclusions. :-)
------------------

Edit: You went and got me curious.

print_r() only prints variables available to it. Issuing a print_r() inside a function will only print something if the variable is available.

Therefore, in the above example, the only reason $config prints is because he/she indeed included the file within the function.

Which may invalidate my contribution as well, if it's available inside the function then why are the variables null . . .

For a working example, run this code.

<?php
header("content-type:text/html");
$myvar = "testme";
echo "<p>Here is my var: $myvar</p>";
//
first_test();
echo "<p>The print_r does not print \$myvar from the first
function because it's outside the scope of the function.</p>";
second_test();
//
echo "<p>Note how MY VAR printed before this line
via print_r, because it's defined as a global in second_test().</p>";
//
$returnme = third_test($myvar);
echo "<p>String returned from second_test(): $returnme</p>";
//
function first_test() {
print_r($myvar);
}
//
function second_test() {
global $myvar;
print_r($myvar);
}
//
function third_test($var) {
$txt = "variable passed was $var";
return $txt;
}
?>

[Wed Mar 24 16:15:30 2010] [error] [client 123.456.789.00] PHP Notice: Undefined variable: myvar in /var/www/example.com/functions.php on line 18

Which would be my print_r()

---------------------------------------------
GETTING BACK ON TOPIC . . .

The function bits are still relevant, as you'd likely want to keep your variables somewhere convenient, at hte top of the script and most likely outside this function. That's the whole point of functions.

When you moved the include inside the function, that problem went away and revealed a second.

I've never used PDO, but from the documentation [php.net] looks like you have it right.

The only thing that can be extrapolated is one of those variables are wrong (?)

(using password: NO)

If you see the password in the print_r, it may be shifting off some invalid value. Does your mysql server need a full host, as in [mysql.example.com,...] or an IP?

nolim8ts

3:22 pm on Mar 25, 2010 (gmt 0)

10+ Year Member



Hi All,

Thanks for the responses. Placing
global $config;
inside the function did the trick...

rocknbil

7:38 pm on Mar 25, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



So you're not getting "using password, no?"

Odd, with the file included within the function I'd think you'd have gotten the same result . . . cannot . . . . stand . . . unanswered puzzles!

If it's good, it's all good.