[…] I even recently discovered the great
feature that was introduced in PHP 7.4PHP_CLI_SERVER_WORKERS
, which I sorely
needed because my API makes a couple of requests internally to various paths of
the API, and nested requests require more than one process / worker, which
wasn't a problem for the Nginx / Apache production server but would have been a
problem on localhost using the built-in server if it weren't for this
environment variable.Seeing I have a number of people interested in contributing to the project, they
have been asking me how they can develop on localhost without the trouble of
setting up a whole WAMP environment. […]
I don't quite understand how WAMP fits into this. WAMP is Windows only,
and on Windows PHP_CLI_SERVER_WORKERS
is not supported.
In my use case, I have an API backend that I can spin up with
php -S localhost:8000
. Then when I spin up the frontend (which is also written in
PHP), it knows nothing about where to find the API backend. On the production
server, I had the host hardcoded into the frontend application. But if I want to
be able to dynamically switch between localhost and production, I need to be
able to instruct the frontend of where to find the API backend. This can easily
be achieved through dotenv files, and even better if we have an automatic
environment variable of$_ENV[APP_ENV]=development
. I see that there is a
composer package (https://github.com/vlucas/phpdotenv) that can achieve loading
dotenv files, but other than loading dotenv files by means of a composer package
it would be nice if we could at least have an automatic environment variable of
$_ENV[APP_ENV]=development
created by PHP's built-in server. Seeing that the
built-in server will pretty much always be used for easy localhost development,
I don't see any reason why adevelopment
environment variable couldn't or
shouldn't be created by the built-in server? It would make PHP localhost
development that much more user friendly in my opinion...
Besides that setting an environment globally is not necessarily
possible, this looks somewhat backwards to me, and is in my opinon way
too special – why would only the built-in development server advertize
itself as a development environment?
Christoph
I think it would be a nice feature of PHP's built-in server to do
something similar, automatically provide a$_ENV[APP_ENV]
variable with a
value ofdevelopment
so that the application logic knows whether it's
running on a localhost development environment rather than on a production
server.
Why couldn't you just do
if (php_sapi_name() === 'cli-server') {
$_ENV['APP_ENV'] = 'development';
}
in your entry point script?
--
Best regards,
Bruce Weirdan mailto:
weirdan@gmail.com
My point is, would the built-in server ever be used for anything other
than local development? If not, then it would be a simple convenience
to developers to have an automatic environment variable of
"development" when launching the built-in server. Instead of manually
creating this environment variable, it would just be there.
As a matter of best practice, an application should not need to know
which environment it is running in, let alone be designed specifically
to respond to the PHP built-in server.
Cheers,
Bilge
I don't understand why an application should not know which
environment it is running in?
I don't know if this list is the place to be discussing this, but here goes:
Typically you are injecting the environment name to have the application
switch to a different configuration to load a whole bunch of different
settings for that environment. Instead, you should be injecting all
those different settings directly. The reason is because otherwise you
are tightly coupling your application to a fixed number of known
environments, limiting deployment options. Instead, the application
should be environment agnostic, thereby enabling whomsoever deploys your
application to configure as many different environment types as they wish.
This best practice also avoids the temptation to code different logic
paths based on the environment name (very bad).
Don't worry, this is a common mistake, and even popular frameworks like
Laravel and Symfony promote this anti-pattern to some degree.
Cheers,
Bilge
I don't understand why an application should not know which
environment it is running in?I don't know if this list is the place to be discussing this, but here
goes:Typically you are injecting the environment name to have the application
switch to a different configuration to load a whole bunch of different
settings for that environment. Instead, you should be injecting all
those different settings directly. The reason is because otherwise you
are tightly coupling your application to a fixed number of known
environments, limiting deployment options. Instead, the application
should be environment agnostic, thereby enabling whomsoever deploys your
application to configure as many different environment types as they wish.This best practice also avoids the temptation to code different logic
paths based on the environment name (very bad).Don't worry, this is a common mistake, and even popular frameworks like
Laravel and Symfony promote this anti-pattern to some degree.Cheers,
Bilge
So if symfony and laravel do this, whose best practices are we going by
exactly, yours?
Switching configuration is one of many reasons an app needs to know what
environment it's running on. What if I want more verbose logging at dev
time? Or want to bypass expensive api calls with mock data? Or want to make
sure something is never called in production?
Cheers,
Hammed
So if symfony and laravel do this, whose best practices are we going
by exactly, yours?
One common citation for this is "The Twelve-Factor App"
[https://12factor.net/], a methodology/manifesto published in 2011 by
some engineers from Heroku as a way to build a particular sort of
cloud-native service-based application. Coincidentally, an open-source
project to update and expand on it was officially announced last week:
https://12factor.net/blog/open-source-announcement
The idea is that "in a twelve-factor app":
- configuration comes directly from the environment; for instance,
provided by the orchestration layer in a container-based deployment - it is not written to a file, but passed directly to the application as
environment variables - it does not indicate a named environment, but configures the
application directly
When people struggled with development environments which didn't have a
suitable place for these variables to come from, the ".env file" was
invented - a way to emulate the environment variables that a "real"
deployment would receive.
This then took on a life of its own, and eventually ".env" became just
another format for configuration files: instead of "development.ini" and
"production.ini", you have ".env.development" and ".env.production". We
came full circle, and the only thing which actually comes from the
environment is a master switch to choose the file to load.
Personally, I don't think there's anything wrong with the "master
switch" approach for a lot of applications. Not everybody works for a
company with hundreds of developers, and a dozen kubernetes clusters
running A/B tests on continuously deployed code. Sometimes you really do
know you have 2, or 3, or 4, environments to configure.
However, I don't think the master switch is something that should be
hard-coded in a server. Maybe you know that if it's running under "php
-S", it's "dev mode", and it it's running under Apache, it's "live
mode"; if so, you can look at PHP_SAPI
/ php_sapi_name()
. But maybe you
do run Apache on a dev server; or you have separate debug and QA modes.
--
Rowan Tommins
[IMSoP]
So if symfony and laravel do this, whose best practices are we going
by exactly, yours?One common citation for this is "The Twelve-Factor App"
[https://12factor.net/], a methodology/manifesto published in 2011 by
some engineers from Heroku as a way to build a particular sort of
cloud-native service-based application. Coincidentally, an open-source
project to update and expand on it was officially announced last week:
https://12factor.net/blog/open-source-announcementThe idea is that "in a twelve-factor app":
- configuration comes directly from the environment; for instance,
provided by the orchestration layer in a container-based deployment- it is not written to a file, but passed directly to the application
as environment variables- it does not indicate a named environment, but configures the
application directlyWhen people struggled with development environments which didn't have
a suitable place for these variables to come from, the ".env file" was
invented - a way to emulate the environment variables that a "real"
deployment would receive.This then took on a life of its own, and eventually ".env" became just
another format for configuration files: instead of "development.ini"
and "production.ini", you have ".env.development" and
".env.production". We came full circle, and the only thing which
actually comes from the environment is a master switch to choose the
file to load.Personally, I don't think there's anything wrong with the "master
switch" approach for a lot of applications. Not everybody works for a
company with hundreds of developers, and a dozen kubernetes clusters
running A/B tests on continuously deployed code. Sometimes you really
do know you have 2, or 3, or 4, environments to configure.However, I don't think the master switch is something that should be
hard-coded in a server. Maybe you know that if it's running under "php
-S", it's "dev mode", and it it's running under Apache, it's "live
mode"; if so, you can look atPHP_SAPI
/php_sapi_name()
. But maybe
you do run Apache on a dev server; or you have separate debug and QA
modes.
You wrote the perfect post summarising a brief history of configuration
injection and brought it back to the main point that the master switch
does not belong in the web server, and I hadn't heard about the 12factor
open source announcement so I learned something new, too! Bravo. Thanks
for posting this and agree with everything stated herein.
Cheers,
Bilge