3

I normally use procedural programming with PHP and looking at other questions here asking how to avoid globals the answers were often to use OOP instead. Is it not possible to avoid globals with procedural programming?

For example I can write the following function in two ways. Both have advantages and disadvantages. If I call this function often then it looks bloated with the second method since it has to pass all the variables each time. The alternative is the first method where the function simply passes the value and the variables are all globals in the function.

doWhatIneedtodo(2);

function doWhatIneedtodo($val) {
  global $this; global $that; global $theother;
  if ($val == 1) { 
    $this++;
  } else
  if ($val == 2) { 
    $that++;
  } else
  if ($val == 3) { 
    $theother++;
  }
}

doWhatIneedtodo(2,$this,$that,$theother);

function doWhatIneedtodo($val,&$this,&$that,&$theother) {
  if ($val == 1) { 
    $this++;
  } else
  if ($val == 2) { 
    $that++;
  } else
  if ($val == 3) { 
    $theother++;
  }
}

Or perhaps there's a better way to do this that I haven't though of?

Hasen
  • 11,710
  • 23
  • 77
  • 135
  • Is there any practical reason you're trying to avoid OOP? It's a powerful tool at your disposal and you should get used to using it. – Havenard Mar 11 '19 at 06:14
  • @Havenard No I'm just wondering if procedural programming indeed has this limitation or whether there is a better way to write my function or not. – Hasen Mar 11 '19 at 06:15
  • this question is absurd, because sequential code always runs at the global scope. – Martin Zeitler Mar 11 '19 at 06:20
  • Well, in some cases you can group information into an `array` instead of writing an individual global variable for each thing. For example, if it is something you'd load from a `config.php`, you can create an associative `$config` array with everything. Globals should be avoided really, you don't want your script to be dependent on variables that seemingly come out of the dark because it is declared God knows where as a global, you want to have control. That's the principle of "tell, don't ask" that helps you keep your code secure and self-contained. – Havenard Mar 11 '19 at 06:20
  • As a global, but at least it is one global and not a dozen. – Havenard Mar 11 '19 at 06:23
  • Code reliant on globals have caused major security breaches in PHP websites in the past, specially when `register_globals` was on by default in the `php.ini` – Havenard Mar 11 '19 at 06:26
  • @Havenard while there only is global and function scope... I should almost edit the title of this question to "How do I avoid learning to produce proper OOP code?" configs are often at the global scope, while one still can `unset()` them at run-time - or read from `.ini` files, outside of the webroot. what I dislike the most are `define()` statements for variable configurations. – Martin Zeitler Mar 11 '19 at 06:27
  • the abuse of `$this` in the example is pretty much speaking for itself ... – Martin Zeitler Mar 11 '19 at 06:33
  • @Martin Zeitler people still use procedural code and there are many arguments that OOP is no faster or better. Therefore it's quite redundant to say 'proper OOP code'. There are certainly circumstances where procedural code is simpler and better. If this particular thing is a limitation of procedural code then fine, that's why I asked to confirm...but I hardly think it makes procedural code completely useless. It's like saying Superman is no use whatsoever because of his kryptonite weakness. – Hasen Mar 11 '19 at 06:41
  • @Hasen for primitive solutions, this might be the case - but not when it gets complex... also the code re-usability is barely given, like that. and all the `require`/`include` statements are rather unfortunate, when trying to use a debugger, because one cannot set a watch on them - while one can do that with objects. – Martin Zeitler Mar 11 '19 at 06:48
  • @Martin Zeitler Yes it's not apparent from the question whether it's a short, simple program or a long complicated one, but I don't think it's correct to assume it's the latter so the question is perfectly valid. I write programs just for myself casually so often I just write a quick program that is literally just one page or one file - OOP would be no use with these. I guess I have my answer anyway now though. – Hasen Mar 11 '19 at 07:13

2 Answers2

3

It's very much a progression from troublesome code to less troublesome code:

  • Purely procedural code without using functions: almost impossible to reuse or modularise, quickly leads to name clashes and spaghetti code in any decent-sized program.
  • Procedural code using functions: some namespacing/scoping for some variables, though eventually still the same issues as above if you use globals.
  • Procedural code with functions and without globals, veering towards functional programming: no name clashes, great reusability, but a lot of passing around of individual values.
  • In other languages this is where structs would come in to define structured "bundles" of values to pass around between functions, but since PHP is lacking structs you'd be using arrays, which are tedious because they are entirely unstructured and untyped and it becomes difficult to keep their structure straight in the long run.
  • So then objects enter the picture, which provide data structures.
  • And while you're using objects anyway, you may as well go for encapsulation and let object methods act on their own data, hiding the internal data structure and instead exposing functionality (methods), so the underlying data structures can be changed and that change is localised to the class itself, instead of all the functions that consume a certain struct/array.

So you see, solving problems with global procedural code one by one eventually leads to OOP anyway, at least in PHP. There's a fork in the road halfway through where you could go to pure functional programming as well, but PHP is ill-equipped for being a purely functional language.

deceze
  • 510,633
  • 85
  • 743
  • 889
0

The reason you mostly find answers regarding this question for OOP is twofold I think:

  • Everybody does PHP OOP these days, it's really worth it.
  • In OOP globals are bad as you want to avoid global state. Introducing global state results in code that's harder to test and to maintain. In procedural PHP everything is global anyways so there's much less need to avoid globals.

Apart from that, my preference goes to your second implementation because it would be far more easy to transition this into proper OOP code. If you use the first implementation and you'd want to change the names of the variables, you'd have to adjust the calling code and the function itself.

vixducis
  • 1,010
  • 1
  • 8
  • 22