Viewed   65 times

sorry i'm a beginner and i can't determine how good a question this is, maybe it sounds utterly obvious to some of you.

if our use of these two below is the same which is better?

function doSomething ($var1,$var2,..){
    ...
}

OR

function doSomething (){
    global $var1,$var2,..;
    ...
}

by our use I mean that I know that in the second scenario we can also alter the global variables' value. but what if we don't need to do that, which is the better way of writing this function? does passing variables take less memory than announcing global's in a function?

 Answers

1

The memory usage is a paltry concern. It's much more important that the code be easy to follow and not have... unpredicted... results. Adding global variables is a VERY BAD IDEA from this standpoint, IMO.

If you're concerned about memory usage, the thing to do is

function doSomething (&$var1, &$var2,..) {
   ...
}

This will pass the variables by reference and not create new copies of them in memory. If you modify them during the execution of the function, those modifications will be reflected when execution returns to the caller.

However, please note that it's very unusual for even this to be necessary for memory reasons. The usual reason to use by-reference is for the reason I listed above (modifying them for the caller). The way to go is almost always the simple

function doSomething ($var1, $var2) {
    ...
}
Saturday, November 12, 2022
4

The F3 instance variable which is declared at the very start of your index.php ($f3=require...) can be retrieved anywhere in the code using the static call $f3=Base::instance().

Anyway, for convenience purpose, at routing time this F3 instance as well as the route parameters are passed to the route handler. Therefore, instead of defining your route handler as:

function display() {
    $f3=Base::instance();
    echo 'I cannot object to an object' . $f3->get('PARAMS.page');
};

you could define it as:

function display($f3) {
    echo 'I cannot object to an object' . $f3->get('PARAMS.page');
};

or even better:

function display($f3,$params) {
    echo 'I cannot object to an object' . $params['page'];
};

These 3 functions are absolutely identical so you should pick up the one that you understand best. But you should remember that $f3 and $params are only passed at routing time, which means to 3 functions: the route handler, the beforeRoute() hook and the afterRoute() hook. Anywhere else in the code (including inside a class constructor), you should call Base::instance() to retrieve the F3 instance.

PS: your question being "why do i have to pass the $f3 class to the function?", I would suggest you to rename its title to reflect it.

UPDATE: Since release 3.2.1, the F3 instance is also passed to the constructor of the route handler class:

class myClass {
    function display($f3,$params) {
        echo 'I cannot object to an object' . $params['page'];
    }
    function __construct($f3) {
        //do something with $f3
    }
}
Saturday, December 10, 2022
3

You can use the global keyword:

$a = "Hello World";
$b = "Hello World";

function outputStrings(){
  global $a, $b;
  echo $a." - ".$b;
}

$b = "Goodbye World";

outputStrings(); // ouputs "Hello World - Goodbye World"

However, its best not to use this structure. Its generally confusing and will make your code difficult to maintain. Wordpress uses this approach a lot in their code base and it makes for very tricky debugging. Other plugins and code can interject and modify global variables, changing the output of your script.

What would be better would be to either:

Use an OOP structure for your web app.

This way you can use objects instead of just random global variables. This gets around the issue of you accidentally overwriting a global variable in the course of a script. It also helps to organise the variables correctly, so all variables concerning users can be in the User class. It makes more sense to structure it like that.

class User {
  private $firstName;
  private $secondName;
  private $gender;

  public function __construct($fname, $sname, $gend){
    $this->firstName = $fname;
    $this->secondName = $sname;
    $this->gender = $gend;
  }

  public function outputDetails(){
    echo $this->firstName." ".$this->secondName." is ".$this->gender;
  } 
}

$user = new User("Thomas", "Clayson", "Male");
$user->outputDetails();

Pass variables into functions

Just like you've shown in your example. This is the generally accepted standard way of doing this. You should always pass in variables like this, it helps you define scopes and a proper structure. Also it means you know what the value of variables is, as you own them and pass them to functions, rather than just plucking variables from global scope.

Wednesday, November 2, 2022
 
chp
 
chp
4

Use the assign() function.

  assign("new.data", my.data[,-col], envir = .GlobalEnv) 

The first argument should be a string. In this case, the resultant global variable will be named "new.data". If new.data is the name itself, drop the quotes from the function call.

<<- does not always assign to the global environment.

In general, however, it is better to return things from a function than set global variables from inside a function. The latter is a lot harder to debug.

Tuesday, December 6, 2022
 
5

Inspect the bytecode.

from dis import dis
dis(f)

Result:

  2           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               1 (1)
              6 BINARY_ADD
              7 STORE_FAST               0 (x)

  3          10 LOAD_FAST                0 (x)
             13 LOAD_GLOBAL              0 (y)
             16 BINARY_ADD
             17 STORE_FAST               1 (z)

  4          20 LOAD_FAST                1 (z)
             23 RETURN_VALUE

The global variables will have a LOAD_GLOBAL opcode instead of LOAD_FAST. (If the function changes any global variables, there will be STORE_GLOBAL opcodes as well.)

With a little work, you could even write a function that scans the bytecode of a function and returns a list of the global variables it uses. In fact:

from dis import HAVE_ARGUMENT, opmap

def getglobals(func):
    GLOBAL_OPS = opmap["LOAD_GLOBAL"], opmap["STORE_GLOBAL"]
    EXTENDED_ARG = opmap["EXTENDED_ARG"]

    func = getattr(func, "im_func", func)
    code = func.func_code
    names = code.co_names

    op = (ord(c) for c in code.co_code)
    globs = set()
    extarg = 0

    for c in op:
        if c in GLOBAL_OPS:
            globs.add(names[next(op) + next(op) * 256 + extarg])
        elif c == EXTENDED_ARG:
            extarg = (next(op) + next(op) * 256) * 65536
            continue
        elif c >= HAVE_ARGUMENT:
            next(op)
            next(op)

        extarg = 0

    return sorted(globs)

print getglobals(f)               # ['y']
Tuesday, October 11, 2022
 
benvc
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :