Currently an environment variable can be specified in the php.ini file.
This is useful if you want tune one or two settings in your runtime
environment. Where this runs into issues is if you want to do something
similar to Juan Terminio[1][2].
I'm proposing a change the php.ini parser that would allow for an extended
syntax for environment variables in the php.ini. In this syntax when
checking for an environment variable if it is empty the fallback value
would be used instead. The original environment variable syntax would
remain valid as well.
Possible syntax options. I currently do not have a very deep understanding
of the current .ini parser so this may make invalid assumptions.
-
memory_limit = ${PHP_MEMORY_LIMIT:-"default value"}
-
memory_limit = ${PHP_MEMORY_LIMIT::"default value"}
-
memory_limit = ${PHP_MEMORY_LIMIT:="default value"}
-
memory_limit = ${PHP_MEMORY_LIMIT=="default value"}
-
Potential issue: Adopting a bash-ism
This type of environment fallback is common in bash. If adopted it could
lead users to think other bash features are also available. To dissuade
this I would suggest that the fallback value syntax not appear in any of
the default php.ini files. Users must read the documentation and decide if
it works for them and add it in their php.ini file.
Changes needed in the code
Digging through the code I find that two sections would need to be changed,
both in Zend/zend_ini_parser.y. I hope to be able to write this code myself
but would gladly accept some guidance.
- cfg_var_ref: Currently TC_DOLLAR_CURLY TC_VARNAME '} would need to be
changed to something like TC_DOLLAR_CURLY TC_VARNAME ':-' TC_FALLBACK '}' - zend_ini_get_var: I imagine this would require adding a third parameter
to the function signature that would be used in the event of a null value
when checking the environment.
[1]
https://jtreminio.com/blog/php-modules-toggled-via-environment-variables/
[2]
https://jtreminio.com/blog/docker-php/php-fpm-configuration-via-environment-variables/
I look forward to your feedback.
Derek
- memory_limit = ${PHP_MEMORY_LIMIT:-"default value"}
- memory_limit = ${PHP_MEMORY_LIMIT::"default value"}
- memory_limit = ${PHP_MEMORY_LIMIT:="default value"}
- memory_limit = ${PHP_MEMORY_LIMIT=="default value"}
Not a fan of special syntax for environment variables regardless of
the syntax. I think $_ENV['foo'] ?? 'bar'
is fine as-is. Not so
much the superglobal, but there's also getenv()
.
--c
Not a fan of special syntax for environment variables regardless of
the syntax. I think$_ENV['foo'] ?? 'bar'
is fine as-is. Not so
much the superglobal, but there's alsogetenv()
.
I feel fairly silly, this being for just .ini files. Seems reasonable
enough there, though now we're talking about .ini files no longer
being static...
--c
PHP's ini values are already a bit of a mess. You have a global php.ini
file, and then most PHP ini directives can be set per directory using the
.htaccess file. About a third can be set at runtime. This makes tracking
down where a setting came from a bit of a headache unless care is taken.
This proposal promises to make the situation even more complicated.
Also, what would this solve that using .htaccess files to override the
default values not solve aside from the rare settings that cannot be set
per directory?
Currently an environment variable can be specified in the php.ini file.
This is useful if you want tune one or two settings in your runtime
environment. Where this runs into issues is if you want to do something
similar to Juan Terminio[1][2].I'm proposing a change the php.ini parser that would allow for an extended
syntax for environment variables in the php.ini. In this syntax when
checking for an environment variable if it is empty the fallback value
would be used instead. The original environment variable syntax would
remain valid as well.Possible syntax options. I currently do not have a very deep understanding
of the current .ini parser so this may make invalid assumptions.
memory_limit = ${PHP_MEMORY_LIMIT:-"default value"}
memory_limit = ${PHP_MEMORY_LIMIT::"default value"}
memory_limit = ${PHP_MEMORY_LIMIT:="default value"}
memory_limit = ${PHP_MEMORY_LIMIT=="default value"}
Potential issue: Adopting a bash-ism
This type of environment fallback is common in bash. If adopted it could
lead users to think other bash features are also available. To dissuade
this I would suggest that the fallback value syntax not appear in any of
the default php.ini files. Users must read the documentation and decide if
it works for them and add it in their php.ini file.Changes needed in the code
Digging through the code I find that two sections would need to be changed,
both in Zend/zend_ini_parser.y. I hope to be able to write this code myself
but would gladly accept some guidance.
- cfg_var_ref: Currently TC_DOLLAR_CURLY TC_VARNAME '} would need to be
changed to something like TC_DOLLAR_CURLY TC_VARNAME ':-' TC_FALLBACK '}'- zend_ini_get_var: I imagine this would require adding a third parameter
to the function signature that would be used in the event of a null value
when checking the environment.[1]
https://jtreminio.com/blog/php-modules-toggled-via-environment-variables/
[2]https://jtreminio.com/blog/docker-php/php-fpm-configuration-via-environment-variables/
I look forward to your feedback.
Derek
Hi Michael,
niedz., 26 lip 2020, 06:22 użytkownik Michael Morris tendoaki@gmail.com
napisał:
PHP's ini values are already a bit of a mess. You have a global php.ini
file, and then most PHP ini directives can be set per directory using the
.htaccess file. About a third can be set at runtime. This makes tracking
down where a setting came from a bit of a headache unless care is taken.
This proposal promises to make the situation even more complicated.Also, what would this solve that using .htaccess files to override the
default values not solve aside from the rare settings that cannot be set
per directory?
Bear in mind that .htaccess has a very narrow use and it's kind oh thing
Apache2 related and not PHP specific!
Personally I like the idea of setting ini directives via environment
variables but not by a complex syntax in ini files but rather by looking up
for a directive by environment variable name and setting it up directly for
instance:
PHP_MEMORY_LIMIT=1G php script.php
Being equivalent of:
php -dmemory_limit=1G script.php
This would allow to avoid changes in php.ini file in containers with php or
php-fpm like Docker ones and to adjust ini directive values by simple
environment variables.
I believe there should be no two ini directives which could be ambiguous
like for eg. "memory_limit" and "memory.limit" and cause issues on ini
directives lookup by env variable name like PHP_MEMORY_LIMIT.
Cheers,
Michał Marcin Brzuchalski
On Mon, Jul 27, 2020 at 12:18 AM Michał Marcin Brzuchalski <
michal.brzuchalski@gmail.com> wrote:
Hi Michael,
niedz., 26 lip 2020, 06:22 użytkownik Michael Morris tendoaki@gmail.com
napisał:PHP's ini values are already a bit of a mess. You have a global php.ini
file, and then most PHP ini directives can be set per directory using the
.htaccess file. About a third can be set at runtime. This makes tracking
down where a setting came from a bit of a headache unless care is taken.
This proposal promises to make the situation even more complicated.Also, what would this solve that using .htaccess files to override the
default values not solve aside from the rare settings that cannot be set
per directory?Bear in mind that .htaccess has a very narrow use and it's kind oh thing
Apache2 related and not PHP specific!
Most major webserver applications have an equivalent to .htaccess. Indeed,
IIS can bind PHP flags and values to environment values already if I recall
correctly, and has been able to do so for a very long time (though I
haven't played with IIS in over a decade so my memory could be wrong on
this).
You mention Docker - usually I've seen it used alongside Ansible, Chef or
Puppet. Each of these provisioning programs can modify the php.ini file
used on the container at deploy time without necessitating a change to PHP
itself. What advantage does the community gain from moving these decisions
from the provision files to the php.ini file?
You mention Docker - usually I've seen it used alongside Ansible, Chef or
Puppet. Each of these provisioning programs can modify the php.ini file
used on the container at deploy time without necessitating a change to PHP
itself. What advantage does the community gain from moving these decisions
from the provision files to the php.ini file?
My use case is specifically Docker and Kubernetes. Like Michal said,
containers aim to be immutable. When we deploy containers they are built
via CI with a specific base image sets up PHP with the extensions we need
and then creates a layer for our application. That means to change any one
configuration value in the php.ini file would trigger a rebuild of the
container.CI would then rebuild the container and deploy it. That can take
minutes at times. The quick way would be to change an environment variable,
mark all old containers as bad and any new ones pick up the new environment
setting as they fill in for the bad ones. Another use case. We have a
private Kubernetes stack for a specific client. With environment variables
we can turn the php.ini using environment variable but each time a new
config value is used this way we have to make sure that same environment
variable is exposed to the container. The ability to have a fallback value
while not 100% necessary does have the ability to reduce errors around
environment variables in Docker/Kubernetes deployments.
We don’t use Ansible, Chef, or Puppet. Everything is CI and kubectl. I
might understand using these tools if you are running your own Kubernetes
stack but we are not currently doing that.
On July 26, 2020 at 10:18:23 PM, Michał Marcin Brzuchalski (
michal.brzuchalski@gmail.com) wrote:
Personally I like the idea of setting ini directives via environment
variables but not by a complex syntax in ini files but rather by looking up
for a directive by environment variable name and setting it up directly for
instance:
PHP_MEMORY_LIMIT=1G php script.php
Being equivalent of:
php -dmemory_limit=1G script.php
This seems like a reasonable alternative. With this would the php.ini be
the fallback value I’m looking for with the environment variable only being
used if present?
On July 27, 2020 at 12:01:13 AM, Michał Marcin Brzuchalski (
michal.brzuchalski@gmail.com) wrote:
I do like the idea of applying INI settings with environment variables but
I believe
we should not change anything by providing complex INI parsing rules.
Your proposal inspired me to think of it more and think of potential RFC
for changing the configuration mechanism we use in PHP so it can be
slightly refactored and extracted from zend_ini into zend_config with
additional
configuration providers for "argv" values, environment variables,
INI settings and extension provider.
I believe and hope it has a potential and allows us to make things more
clear when talking
about INI settings.
We always talk about INI settings while INI is just a file format and we
apply internally
INI settings from different sources like -d
options from the command line
or provided
by extension like mentioned in the thread .htaccess.
In summary, potential RFC proposal would be:
- extract zend_config from zend_ini, INI directives will in a future be
considered a configuration settings/directives whatever; - implement different prioritized configuration providers for CLI argv,
INI files, ext, environment variables - allowing to resolve
configuration settings in a specific order
This will in a future open wide range of possibilities, like new formats to
be implemented via file format, specific configuration provider.
That sounds a little more complex that I was aiming for but does solve the
issue in a different way. I however wouldn’t be able to write that code
currently.
Thank you kindly for the responses. One comment I’ve seen that adding this
proposal would make the php.ini file no longer static. Can you please
clarify how
memory_limit = ${PHP_MEMORY_LIMIT}
is any less static than
memory_limit = ${PHP_MEMORY_LIMIT:-“256M”}
To me the ini setting is both static and deterministic. They may have
different outcomes under the proposed change but that doesn’t make it
dynamic.
Cheers,
Derek
Hi Derek,
pt., 24 lip 2020 o 22:54 Derek Bonner derek@derekbonner.com napisał(a):
Currently an environment variable can be specified in the php.ini file.
This is useful if you want tune one or two settings in your runtime
environment. Where this runs into issues is if you want to do something
similar to Juan Terminio[1][2].
I do agree that this is hard to apply INI setting on Docker environment.
I'm proposing a change the php.ini parser that would allow for an extended
syntax for environment variables in the php.ini. In this syntax when
checking for an environment variable if it is empty the fallback value
would be used instead. The original environment variable syntax would
remain valid as well.
I disagree here. IMO INI setting should remain static.
Possible syntax options. I currently do not have a very deep understanding
of the current .ini parser so this may make invalid assumptions.
- memory_limit = ${PHP_MEMORY_LIMIT:-"default value"}
- memory_limit = ${PHP_MEMORY_LIMIT::"default value"}
- memory_limit = ${PHP_MEMORY_LIMIT:="default value"}
- memory_limit = ${PHP_MEMORY_LIMIT=="default value"}
I do like the idea of applying INI settings with environment variables but
I believe
we should not change anything by providing complex INI parsing rules.
Your proposal inspired me to think of it more and think of potential RFC
for changing the configuration mechanism we use in PHP so it can be
slightly refactored and extracted from zend_ini into zend_config with
additional
configuration providers for "argv" values, environment variables,
INI settings and extension provider.
I believe and hope it has a potential and allows us to make things more
clear when talking
about INI settings.
We always talk about INI settings while INI is just a file format and we
apply internally
INI settings from different sources like -d
options from the command line
or provided
by extension like mentioned in the thread .htaccess.
In summary, potential RFC proposal would be:
- extract zend_config from zend_ini, INI directives will in a future be
considered a configuration settings/directives whatever; - implement different prioritized configuration providers for CLI argv,
INI files, ext, environment variables - allowing to resolve
configuration settings in a specific order
This will in a future open wide range of possibilities, like new formats to
be implemented via file format, specific configuration provider.
Why it cannot be handled by a specialised library?
- On environments with dl disabled you cannot load additional extension
without adding it to INI files or by-dextension=[ext]
CLI option. - If you struggle with memory limit or time limit you cannot change it if
the script calls another script via proc_open or exec without applying INI
file setting, even a CLI option won't help here but an environment variable
could. - In modern stacks like k8s or Docker when a container is immutable per
se, you cannot modify for eg. memory_limit, or enable/disable OPcache, tune
OPcache flags, enable/disable Xdebug without changing INI files but you
could do that easily by an environment variable, via docker-compose
environment settings, docker -e options, or by editing a deployment on k8s
by hand to apply different settings for investigation purposes.
I'd like to hear other opinions about it.
Cheers,
Michał Marcin Brzuchalski