However, even that doesn't handle in-flight requests that have their view of the files swapped out from under them. Yes, that's a small time window for an error to happen, but it's definitely not instantaneous.
The safer solution would be to update the server config to point at the new directory and reload the webserver, but now you're way past just uploading the new files.
I dont think its very different from changing proxy to point to different port.
$conn->query('SELECT * FROM giant_table ORDER BY foo LIMIT 1');
require 'old.php';
such that there's a significant interval between the request being spawned and it later including another file. The duration of the query is the opportunity for 'old.php' to go away, which would cause a 500 error.The difference is that you can have 2 ports listening at once and can close the first once it's drained of connections.
There's no fundamentally safe way to upgrade a bucket-of-files PHP app without tooling complex enough to rival another language's deployment.
In any case you would have to hit some few milisecond window in this opcache generation to break single request but even that might be unlikely thanks to how filesystems read files?
But you are right there is no reason why you couldn't have two instances of the php app runing and switch between them. For some reason the PHP deployment services i've used seem to use the filesystem approach and i doubt it's laziness or incompetence.
And all that may be true for a trivial website. If you've written a personal project with 10,000 hits per year, YOLO. Go for it. The odds of it affecting one of those users is vanishingly tiny, and so what if it does? But if you're hosting something like a Wordpress site for a large company with lots of traffic, it's crucial to understand why "just rsync the files over" is not an acceptable deployment method.