In the most primitive ways, you would at least do cache warming, which usually means "building" the app instance in a separate folder and swapping the active directory served by the web server. That's basically what a basic Capistrano deploy would do.
Nowadays I'd expect most shops to be using containers for PHP too, and that means building your container like any other language.
What I'm saying is, the days where PHP deployment was simple have been long gone, for at least a decade in my experience.
Back in the day PHP got big because most of the larger shared-hosting sites provided mod_php out of the box, along with MySQL.
If you wanted to run CGI scripts you were probably capable of doing that, whether in Perl or something else, but most of the other options came later or were unusual.
I know when I tried to setup a few sites a long long time in the past I had to get a VPS of my own, with root, to configure Apache appropriately. None of the shared hosting sites would have run the kind mods I wanted to have.
I think the "the more things change, the more they stay the same" is a great thing, and something to very much be aware of and study. The move back and forth from backend state to frontend state to slim apps to fat apps has been going on since the 60ies, and is driven by ultimately hardware and networking costs.
The underlying patterns are all fairly well understood, which means that knowing both approaches and being aware that things are going to slosh back and forth heavily simplify long term design.
I haven't written these thoughts out, but in many ways the codebase (as in, how your files are organized) is largely independent of how your code is actually deployed and where it runs. If you are aware that some business logic might one day run in the frontend on the client device, and 4 years later might make more sense ot run in a lambda, that's something you can architect for.
Serverless / stateless is ultimately "functional programming". If you write your code as a side-effect free function, leveraging technologies like WASM, you can keep the same code, and deploy it frontend or backend or both or as a lambda or as a single node worker, and the code itself won't change. These are the things that next.js and vercel and edge computation leverage, but it is true in every codebase (embedded, desktop applications, etc...).
Edit: Not sure why this is controversial. Here is a "hello world" benchmark I just ran on my machine, in units of hello worlds per second: Perl – 1020 runs/second; Python – 78 runs/second; Ruby – 30 runs/second.
Drop a file on a server, it notices filesystem change, reloads an app (or spawns a second copy of app, waits for it to initialize, kills original app and switches over to a new one)?
One problem with this approach is what happens when you're updating multiple files. If the server restarts immediately on the first change, you end up loading a mix of old and new files, which probably won't work properly. But if you delay the restart to wait for all the files, how long do you wait? If the delay is too long it's confusing and annoying (did the server restart yet?) and if it's too short you get mixed versions as before.
So it's better to explicitly signal when it's time to restart. You can still have automatic restarts in the development environment.
[1] https://docs.gunicorn.org/en/stable/settings.html#reload
Ex. First even triggers a 5 seconds wait. If before those 5 seconds have passed there is another trigger (say after 1 second) another 5 seconds wait starts, for a total of 6 seconds in this example.