This is a gap that PHP (and other programming languages) don't tell in their books directly upfront: You can have two times the same variable name (in your case $error), but even the same, the two do not identify the same variable (address the same memory).
This might seem little straight forward at first, but it becomes more sense when it is about structuring a larger program as considerable all well understandable variable names are limited, so making every variable by it's name accessible in the global name-space would pretty fast mess up the whole program code.
So I see multiple routes here on how to deal with this if you're interested (if not, here is some existing Q&A regarding the static keyword in a PHP function).
The first one is quite lazy and most likely unsafe in terms of data processing, so the overall programming code needs to be very precise to make safe use of it: "don't re-implement the array, just use it globally". You can do that with a global variable.
Initialization should be done in the beginning of the application:
$GLOBALS['errors'] = [];
You can then add to that variable new entries whenever you feel it is needed:
$GLOBALS['errors'][] = $error;
And if you need to obtain the errors as a list again, just read it out:
var_dump($GLOBALS['errors']);
This actually is the global variable name errors. Global variables are powerful but also expensive in their maintenance as any code could - by intended or by error - reset all errors for example or even more harsh, turn the array into a string and next time some code wants to add a new entry will fail.
So how could a solution not using a global variable look like? By the cost (and with the benefit) of more controlled access to your errors collection, you can create an object representing that list of errors and pass it around where-ever you want to add an error.
But before showing the object instance, I first show an example of a static class as it might be more close to your mental model w/ the function and it's static variable-
Implemented with static modifiers, you can create an inaccessible global variable (private static global) which is only accessible by the function that adds messages to it (and other static function of the same class).
It is then easy to add another globally accessible function that is able to return that variable's content:
final class Errors
{
private static $errors = [];
public static function add(string $error): void
{
self::$errors[] = $error;
}
public static function get(): array
{
return self::$errors;
}
}
This class provides limited access to the otherwise not accessible static variable Errors::$errors.
It does automatically initialize the moment this class definition is loaded (e.g. via include/require or an auto-loader), new errors can be added via:
Errors::add($error);
And errors can be read out via:
var_dump(Errors::get());
This is now more safe to use as the global variable, however still there is only one global list of errors and every part of the code can access it via the Errors::... class identifier (the name of the class).
So the problem that after some time all usable names are consumed is not solved by that.
To prevent that the class could be turned from static into non-static so moving from global static functions to object instances. This is easy to do, basically just removing the static modifiers and switching from self::$ to $this->. That easy I do the whole example at once:
final class Errors
{
private $errors = [];
public function add(string $error): void
{
$this->errors[] = $error;
}
public function get(): array
{
return $this->errors;
}
}
Now to get this class to work, it needs some more work with the benefit of
better control. First of all it needs initialization:
$errors = new Errors;
Afterwards that errors collection needs to be passed to every place where an error needs to be added:
$errors->add($error);
And if you like, read out all errors collected so far:
var_dump($errors->get());
This last variant needs you to manage (and therefore think about) which parts of your code need to have access to which specific errors collection (as you could create more than one). So this is more work on first glance, however simplifies things a lot in the long run. You can change the errors
collection (store in a file as well next to the array for example) w/o needing to change all the places where a message was added.
You can provide a different error collection object for different uses, e.g. in a testing scenario or of a sub-module of your program only.
So this gives also a lot more flexibility (just start minimal).
The static class in the middle might seem as the holy grail now, but I'd say these are only mediocre and will put a lot of drain to your code quite fast as they are not as powerful as global variables but also consume the name which can not be easily changed as your application grows bigger.
If the use is clear, global variables can be a powerful tool, also static access. But the devil is in the details and on a more differentiated level, it's often quite useful to go with object instances in the meaning of object oriented programming.
global variable - memory object
object variable - programming object (gives you more control via the class definition to control changes over time, code and data form their own unit)
staticdoesn't change the variable scope; it just means it doesn't lose its value when the function exits.globalis the keyword you are looking for. But global variables are bad, mkay?