Better development streamlining of the built-in server

php.internals

John D'Orazio

1 year ago

Christoph Becker

1 year ago
On 19.11.2024 at 03:33, John D'Orazio wrote:
> […] I even recently discovered the great > feature that was introduced in PHP 7.4 `PHP_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 a `development` 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

John D'Orazio

1 year ago

Weirdan

1 year ago
> 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 of `development` 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 ```php if (php_sapi_name() === 'cli-server') { $_ENV['APP_ENV'] = 'development'; } ``` in your entry point script?
-- Best regards, Bruce Weirdan mailto: weirdan@gmail.com

John D'Orazio

1 year ago

Bilge

1 year ago
On 19/11/2024 12:52, John D'Orazio wrote:
> 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

John D'Orazio

1 year ago

Bilge

1 year ago
On 19/11/2024 13:26, John D'Orazio wrote:
> 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

Hammed Ajao

1 year ago
On Tue, Nov 19, 2024, 6:38 a.m. Bilge <bilge@scriptfusion.com> wrote:
> On 19/11/2024 13:26, John D'Orazio wrote: > > 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

Rowan Tommins [IMSoP]

1 year ago
On 19/11/2024 13:48, Hammed Ajao wrote:
> > 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]

Bilge

1 year ago
On 19/11/2024 23:14, Rowan Tommins [IMSoP] wrote:
> On 19/11/2024 13:48, Hammed Ajao wrote: >> >> 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. >
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