PHP is more like “imperative core, functional shell”. After all, a PHP request is a pure stateless function call. The only way it can modify state anywhere is with IO (eg store something in the database, write something to the session store, etc) and all data you accumulate in your PHP code gets purged after each request.
Throwing away what you know with every request is orthogonal to being functional. You really have to squint and turn your head sideways to think of PHP+SQL as being functional, even though PHP is stateless.
From the outside it's stateful, because well you are interacting with a DB.
From within the PHP codebase, it's imperative and requires discipline and extended knowledge of any API you call to understand whether something mutates.
The only time you can view it as actually stateless and somewhat functional is when you test or debug an integration from idempotent requests to responses without interleaving mutations.
That's a hard disagree. The absolute VAST MAJORITY of SQL complexity is in the select queries (joins, groups, aggregation, window functions, cursors, filtering, procedures...), which are mostly not about mutation.
You’re right about SQL the language, but I think the role of MySQL in a PHP application is much more to manage state than to provide interesting SELECT queries. The popularity of ORM in this world shows that what 95% of applications are looking for is native-ish collections that can be mapped to disk and updated concurrently. PHP’s shared nothing architecture means it must externalize this responsibility, and MySQL/Postgres are the customary choices.
With actual SQL, most people don’t get beyond JOIN, which they mainly need in order to deserialize nested or pointer structures from normal form. I learned aggregation, grouping, and windowing working with Spark and Hive on warehouse replicas of my DBs/topics to troubleshoot and analyze my stuff. Never used one in an actual request handler.
IMO you need to see how the SELECT queries are 100% functional to understand properly the power of it which is based on its relational algebra and the closure property of that algebra. Then the basic relational algebra was augmented with a lot of stuff but it's still functional in the end.
This is my perspective as well. I look at SQL as a defacto functional-relational programming language precisely as advertised in Out of the Tar Pit - Chapter 9.
Mutation is fine in pragmatic functional programming and IMO is not the defining feature what makes it so good for industrial use cases. Functional programming must allow easy immutable programs, and you can do that in SQL by never erasing anything (which will require a bit more bookkeeping for sure).
I don't think it is "all about mutation". Indeed it has create/update/delete, but there are a ton of functional capabilities. So much of what SQL offers is related to data shaping. You can have a huge read-only data store and do amazing things with it.
SQL is a weird beast. Very much on the contrary, the language has a relational core (note that functional is a special case of relational), at least in principle, but it’s been grafted with so many imperative-style hacks over time.