The Advantage/Disadvantage Between Global Variables and Function Parameters in PHP

The advantage / disadvantage between global variables and function parameters in PHP?

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) {
...
}

php global variable overhead in a framework

I must agree with NevilleK, that you Core` class sounds line an God Object antipattern.

And for anyone dumb enough to suggest use of singletons/registries i would suggest to do a little research on the subject. They create the same global state as your classical global variables.

Global state is not so much matter of performance ( though in php it has some minor impact ), but it created untestable and tightly coupled code.

You really should look into the Dependency Injection. That might show you another way , which does not require to have such a Core class in your code.


Some additional videos for you:

  • Global State and Singletons
  • Don't Look For Things!
  • Advanced OO Patterns
  • Cake is a Lie
  • Clean Code: Arguments

Why is $GLOBALS significately slower than global keywords?

EDIT: New version, I made a mistake in the first one.

I've rewritten your tests, so it does test the things you want:

<?php

$value = 6235;

function byGlobal() {
global $value;
return $value++;
}

function superGlobal() {
return $GLOBALS['value']++;
}

function asParam($parameter) {
return $parameter++;
}

$time = microtime(true);
for ($i = 0;$i < 10000000;$i++) $value = asParam($value);
echo 'asParam: '.(microtime(true)-$time).'<br/>';

$time = microtime(true);
for ($i = 0;$i < 10000000;$i++) $value = byGlobal();
echo 'byGlobal: '.(microtime(true)-$time).'<br/>';

$time = microtime(true);
for ($i = 0;$i < 10000000;$i++) $value = superGlobal();
echo 'superGlobal: '.(microtime(true)-$time).'<br/>';

Example results for PHP 7.0.17 on CentOs7:

asParam: 0.43703699111938
byGlobal: 0.55213189125061
superGlobal: 0.70462608337402

and

asParam: 0.4569981098175
byGlobal: 0.55681920051575
superGlobal: 0.76146912574768

So, the superGlobal is the slowest, but not by that much. I guess the reason is that it is an array.

What I take away from this is that PHP is fast! I would not worry about the small differences in these tiny time slices. Having readable code is far more important. I my experiences the slowest thing in a website are the database queries.

Is there any disadvantage to declare a variable global?

Why Global Variables Should Be Avoided When Unnecessary

  • Non-locality -- Source code is easiest to understand when the scope of its individual elements are limited. Global variables can be read
    or modified by any part of the program, making it difficult to
    remember or reason about every possible use.
  • No Access Control or Constraint Checking -- A global variable can be get or set by any part of the program, and any rules regarding its use
    can be easily broken or forgotten. (In other words, get/set accessors
    are generally preferable over direct data access, and this is even
    more so for global data.) By extension, the lack of access control
    greatly hinders achieving security in situations where you may wish to
    run untrusted code (such as working with 3rd party plugins).
  • Implicit coupling -- A program with many global variables often has tight couplings between some of those variables, and couplings between
    variables and functions. Grouping coupled items into cohesive units
    usually leads to better programs.
  • Concurrency issues -- if globals can be accessed by multiple threads of execution, synchronization is necessary (and too-often neglected).
    When dynamically linking modules with globals, the composed system
    might not be thread-safe even if the two independent modules tested in
    dozens of different contexts were safe.
  • Namespace pollution -- Global names are available everywhere. You may unknowingly end up using a global when you think you are using a
    local (by misspelling or forgetting to declare the local) or vice
    versa. Also, if you ever have to link together modules that have the
    same global variable names, if you are lucky, you will get linking
    errors. If you are unlucky, the linker will simply treat all uses of
    the same name as the same object.
  • Memory allocation issues -- Some environments have memory allocation schemes that make allocation of globals tricky. This is especially
    true in languages where "constructors" have side-effects other than
    allocation (because, in that case, you can express unsafe situations
    where two globals mutually depend on one another). Also, when
    dynamically linking modules, it can be unclear whether different
    libraries have their own instances of globals or whether the globals
    are shared.
  • Testing and Confinement - source that utilizes globals is somewhat more difficult to test because one cannot readily set up a 'clean'
    environment between runs. More generally, source that utilizes global
    services of any sort (e.g. reading and writing files or databases)
    that aren't explicitly provided to that source is difficult to test
    for the same reason. For communicating systems, the ability to test
    system invariants may require running more than one 'copy' of a system
    simultaneously, which is greatly hindered by any use of shared
    services - including global memory - that are not provided for sharing
    as part of the test.

What are the advantages to passing a global DB connection into each function of a model?

The main advantage is: it's easier. As in, it's the simplest thing to do, because as a result, you have no application architecture. You're grasping at things from everywhere and anywhere because you have no idea how to get them otherwise, and this makes for very poor maintainability. Guess what happens 5 years down the line with this sort of codebase? Massive legacy technical debt, and it's very likely your developers aren't using Object Oriented Programming - more likely shoving procedural code in classes.

I'm not going to bother explaining about global state, because there's already a fantastic answer that already exists on programmers. A small excerpt:

Very briefly, it makes program state unpredictable.

To elaborate, imagine you have a couple of objects that both use the same global variable. Assuming you're not using a source of randomness anywhere within either module, then the output of a particular method can be predicted (and therefore tested) if the state of the system is known before you execute the method.

However, if a method in one of the objects triggers a side effect which changes the value of the shared global state, then you no longer know what the starting state is when you execute a method in the other object. You can now no longer predict what output you'll get when you execute the method, and therefore you can't test it.

You'll find some developers do this purely out of laziness or a lack of knowledge / understanding of the basic concepts of SOLID. If you access global state (like the database), then the beautiful, isolated class you are currently writing that theoretically can be handed off to any other developer, and also tested in it's own right, is now coupled to this object somewhere off in the clouds.

As well as the above, you're making a liar of your object API. Each object should, via it's constructor / method signatures, specify exactly the required external objects with which it requires to function. This allows:

  • Your object to have a definitive API for it's usage
  • Future developers can see exactly what is required for this object to function from the constructor / method signatures
  • Everything passed in via Dependency Injection (the posh word for passing in parameters, basically), can be 'mocked out' for testability
  • Developers don't need to read through your code to find out what other objects are required, because of point 2
  • You aren't accessing something that can be changed by something else, somewhere else, and make debugging a nightmare

Your code should not be brittle. You should be completely confident in making changes somewhere in a massive codebase, without worrying about breaking something somewhere else. Your unit tests will cover this. I highly recommend reading The Clean Coder as it elaborates on some of these concepts.

AlmaDO has a picture of a good image about Singletons, which are basically objects that return a single instance of an object, like a database or logger. So if you request a new database from it, you either get a new one or just get back the one that already exists. In the traditional request / response / dead context, this is completely unecessary. If you're having a very long-running process, maybe this might be necessary, especially in other languages, but as a general rule of thumb in PHP; unless you're running a PHP web socket server or similar, DI is a much better way to go for maintainability.

This is exactly the same as calling StaticObject::Database, again - something that can be accessed from anywhere.

This is a really good post on Singletons in PHP, and how they're not at all needed - that post also has a lot of useful links in it further down.

Basically - don't be lazy and grasp SOLID. There's a reason it exists, and it's certainly not just for PHP, either. The main reason people do it is because they don't know better and it's easier, and easier isn't always the best way.


Also, a few additional clarifications. We don't have "models". We have a model, which is a layer. This is a massive misinterpretation of 'MVC', which we don't even actually have in PHP ('classical mvc'). We have the separation of concerns and that's it.

  • Your "models" are likely, services, domain objects, entities. More info on what the model is

  • Your user should not know about the database. It should be an Entity. Active Record Pattern is not the way forward. Take a look at DataMapper. Your repository would use the database object and return an array of User objects. Contextually as well, a user having access to the database makes no sense.

  • Most frameworks do not work by having access to the database in entities - this isn't PHP 4 any more, it's progressed a lot since then ;-) I highly recommend moving away from CakePHP (it's not MVC in any way) and take a look at a framework like Symfony, which still has it's flaws - knowing the flaws of your chosen framework is very important

PHP big array manipulation

There already was a similar question at StackOverflow, please take a look at:

The advantage / disadvantage between global variables and function parameters in PHP?

PHP $_GET performance

The difference in performance if any will be negligible and not worth the effort - so much so that even if you attempted to microtime it the difference would be consumed by random factors.

However Option A is better in terms of creating more sustainable code. e.g. If you ever wish to change the value of $var you can do it from one position in your code.

Simply put this is never going to be the bottleneck in your program.

What are the advantages/disadvantages of monolithic PHP coding versus small specialized php scripts?

Modular code is easier to understand and maintain. A huge monolithic codebase can become like a house of cards. It works just fine in practice, but changing any of the lower elements becomes impossible. If you split up your code into clear abstractions, it can be much easier to make changes and you'll save yourself a nightmare if you ever add developers.

Passing Variable to other PHP without refreshing

in the functions.php

function get_header(){
if (file_exists('header.php'))
require 'header.php';
else echo "There is an error retrieving a file";
}

in the header.php, and in the balise title you call the session parameter

<!Doctype html>
<html lang="en">

<head>
<title>
<?php if(!empty($_SESSION['title-page'])) echo $_SESSION['title-page']; else 'Learn PHP'; ?>
</title>
</head>

<body>
<div class="header">

<h1>Learn PHP</h1>
<p>Your library of PHP learning!</p>
<hr/>
</div>
<!-- footer is handled by footer.php that include </body> and </html>-->

and in the index.php

<?php 
session_start();
$_SESSION['title-page'] = 'this is the welcome Page';
require 'functions.php';
get_header();
?>

<table>
<h3>What we learned</h3>

<ul>
<li><a href="sample">Syntax</a> </li>
<li><a href="sample">Variables</a> </li>
<li><a href="sample">Code Flow</a> </li>
<li><a href="sample">Arrays</a> </li>
<li><a href="sample">Superglobals</a> </li>
</ul>
</table>

<?php get_footer(); ?>

and in another-page.php

<?php 
session_start();
$_SESSION['title-page'] = 'this is an another Page';
require 'functions.php';
get_header();
?>

<table>
<h3>What we learned</h3>

<ul>
<li><a href="sample">Syntax</a> </li>
<li><a href="sample">Variables</a> </li>
<li><a href="sample">Code Flow</a> </li>
<li><a href="sample">Arrays</a> </li>
<li><a href="sample">Superglobals</a> </li>
</ul>
</table>

<?php get_footer(); ?>


Related Topics



Leave a reply



Submit