Extension Globals¶
In Zephir, extension globals provide a way to define and manage global variables within an extension. These globals are designed for simple scalar types such as int, bool, double, char, etc. It's a mechanism to set up configuration options that can influence the behavior of your library.
To enable extension globals, you need to add a specific structure to your config.json:
{
"globals": {
"allow_some_feature": {
"type": "bool",
"default": true,
"module": true
},
"number_times": {
"type": "int",
"default": 10
},
"some_component.my_setting_1": {
"type": "bool",
"default": true
},
"some_component.my_setting_2": {
"type": "int",
"default": 100
}
}
}
Each global has the following structure:
For compound (namespaced) globals:
"<namespace>.<global-name>": {
"type": "<some-valid-type>",
"default": <some-compatible-default-value>
}
The optional module key, if present, places the global's initialization process into the module-wide GINIT lifecycle event. This means it is set up only once per PHP process, rather than being reinitialized for every request, which is the default.
{
"globals": {
"allow_some_feature": {
"type": "bool",
"default": true,
"module": true
},
"number_times": {
"type": "int",
"default": 10
}
}
}
In the example above, allow_some_feature is set up only once at startup; number_times is set up at the start of each request.
Inside any method, you can read/write extension globals using the built-in functions globals_get/globals_set:
To modify these globals from PHP, you can create a method for this purpose:
namespace Test;
class MyOptions
{
public static function setOptions(array options)
{
boolean someOption, anotherOption;
if fetch someOption, options["some_option"] {
globals_set("some_option", someOption);
}
if fetch anotherOption, options["another_option"] {
globals_set("another_option", anotherOption);
}
}
}
Note that extension globals cannot be dynamically accessed, as the C code generated by the globals_get/globals_set optimizers must be resolved at compilation time:
let myOption = "someOption";
// will throw a compiler exception
let someOption = globals_get(myOption);
INI directives¶
Every scalar extension global is also registered as a php.ini directive. It shows up in phpinfo(), it can be read with ini_get(), and the value given in php.ini (or on the command line with -d) becomes the global's starting value:
The directive is named after the extension and the global, so number_times in an extension whose namespace is test becomes test.number_times, and the compound global some_component.my_setting_1 becomes test.some_component.my_setting_1.
Use the optional ini-entry key to choose a different name, or to restrict where the directive may be changed from:
{
"globals": {
"number_times": {
"type": "int",
"default": 10,
"ini-entry": {
"name": "test.times",
"scope": "PHP_INI_SYSTEM"
}
}
}
}
scope is any of PHP's directive scopes. It defaults to PHP_INI_ALL, and a directive left at that scope can also be changed while the script runs; the global follows immediately:
// number_times has the default scope, so this is allowed
ini_set('test.number_times', '5');
// globals_get("number_times") is now 5
Narrowing the scope to PHP_INI_SYSTEM, as in the example above, makes ini_set() fail and leaves the global alone.
Which types get a directive:
| Type | php.ini value | Notes |
|---|---|---|
bool | On/Off, 1/0, true/false | Shown as On or Off in phpinfo() |
int, long | an integer | |
uint, ulong | a non-negative integer | A negative value is refused: at startup the global falls back to its default, and at runtime ini_set() returns false and changes nothing |
double | a float | |
char, uchar | a string; the first byte is used | globals_get returns the character code, not a one-character string |
string | any string | |
hash | - | Has no directive: an INI value is always a string |
Precedence and lifetime¶
Three things can set a global, and they do not all last as long:
- The
defaultinconfig.jsonis the value the directive itself carries, and applies whenphp.iniis silent. - A value in
php.inireplaces that default when the extension starts up. ini_set()andglobals_set()change the global for the rest of the current request only.
At the start of every request a global goes back to the value the directive holds, so nothing a request wrote with globals_set() can be seen by the next one. A global declared with "module": true is exempt: it is set up once per process and keeps whatever it was last set to.