0

Ok, PHP is not in my major stack and haven't really gotten deep into it, I just want to get things done so I'll go straight to the code:

<?php require_once('server_helper.php');  ?>
<?php

echo $table_balance; // "balance"

function get_balance($user_id) {
    try {
        $conn = establish_connection();
        echo $table_balance; // ""
        // some more code...
    } catch (Exception $e) {
        print_r($e);
    }
}

Explanation: server_helper.php is one level up and it has $table_balance = 'balance'; in it. The first echo $table_balance; - outside the function works as expected and prints "balance", while the second one - inside the function prints "".

The establish_connection() function is also from the server_helper.php and it's working fine...

I'm including the file with the above code in another file, which handles the route hit, gets the ID and calls get_balance($some_id); The code in get_balance() used to be in that another file, where I've used to include the server_helper.php and it worked like a charm. The reason for moving the code is that I wanted to abstract away the DB communication in a separate layer.

I've tried with include, include_once, require and require_once with no success.

P.S: I know underscore is discouraged but I don't feel comfortable using camelCase in a case-insensitive languages.

Dan
  • 619
  • 1
  • 8
  • 18
  • 1
    Possible duplicate of [Reference: What is variable scope, which variables are accessible from where and what are "undefined variable" errors?](https://stackoverflow.com/questions/16959576/reference-what-is-variable-scope-which-variables-are-accessible-from-where-and) – Sean Jan 19 '18 at 06:50

3 Answers3

2

Because it's not how variables in php works. It's outside context of function. Check variable scope in php

There are 2 approaches to get this done.

Pass it as a parameter

make your function to accept it as a parameter

function get_balance($user_id, $table_balance) {
    try {
        $conn = establish_connection();
        echo $table_balance; // ""
        // some more code...
    } catch (Exception $e) {
        print_r($e);
    }
}

And when you call function, pass this variable as second parameter e.g

get_balance($some_id, $table_balance);

Note: $table_balance should be accessible where you are calling get_balance. otherwise go for second approach.

OR

Make it global.

As Ed Heal said in this answer

Community
  • 1
  • 1
shyammakwana.me
  • 5,562
  • 2
  • 29
  • 50
  • Thanks for the answer, I'm accepting yours because it suggests more approaches, even though the first one is not applicable in my situation. – Dan Jan 19 '18 at 12:18
1

Please read up about global

You need to do this:

function get_balance($user_id) {
    global $table_balance;
    try {
        $conn = establish_connection();
        echo $table_balance; // ""
        // some more code...
    } catch (Exception $e) {
        print_r($e);
    }
}
Ed Heal
  • 59,252
  • 17
  • 87
  • 127
  • The global seems to be my only reasonable choice in the situation, thanks. But the question remains - why it used to work /and still dose/ in other files where the use case is 100% the same. – Dan Jan 19 '18 at 12:11
  • edit: Damn, I figured it out.. in the other cases I write my logic directly in the "route file" if I do say so myself, directly in the ``if ($_SERVER["REQUEST_METHOD"] == "POST") {//...}`` for example, which is not really a function, but seems like one because of the if's indentation... – Dan Jan 19 '18 at 12:17
1

While Ed Heal already addressed the quick way to fix, using global to deal with variable scope issues is like using duct tape to fix things. It's ugly and it will eventually start becoming very hard to manage because you'll suddenly be dealing with everything in the global scope.

If you can, start moving towards object-oriented programming where you can organize your variables into classes and have all the class methods have access to those variables / properties:

class MyLedger
{
  private $conn;
  private $table_balance;

  public function __construct()
  {
    $this->conn = $this->EstablishConnection();
    $this->table_balance = "\$123.45";
  }

  private function EstablishConnection()
  {
    // Code to establish and return a connection here...
  }

  public function GetBalance($user_id)
  {
    return $this->table_balance;
  }
}

Then you'd use it like so:

$Ledger = new MyLedger();
echo $Ledger->GetBalance();

Obviously there will be differences to make it actually work for your situation, but that gives you an idea of the syntax. It's a much cleaner way to organize code than loading up on tons of functions and getting confused on names and scopes and all that.

jhilgeman
  • 1,543
  • 10
  • 27
  • Thanks for the nice example. While OOP helps you organise code I think in my case /rather simple backend system with not very much of a logic/ it'd be rather overhead writing all this boilerplate just for the sake of OOP. It's good to know it's possible tho. – Dan Jan 19 '18 at 12:10