Use isset if you want to see if the variable is set, you should never be casting client input unless it’s coming from query params (or form post I guess but at that point use JSON).
“empty” is a useful tool, provided you take into account things like “is this allowed to be 0/empty-string/etc”.
Lastly:
> After a lengthy debugging session, we realized that empty() was treating 0 as "empty", causing our validation to fail unexpectedly.
Lengthy? To notice an empty check failing? Look, the codebase I work on has its warts, all older codebases do, but unless you have no XDebug, forgot how to log to file or echo to the client, and/or aren’t capable of searching a codebase for the error you got and tracing it back from there then I can’t believe that would be a “Lengthy” process to track down. Even if you are returning a generic error to the client, surely you are logging the real error to a log somewhere?