Lots of languages have easy string interpolation, and don't do anything to prevent that being used around sql statements. I'm not sure why php is being called out in this particular case. Sure, it has warts, but in this specific area, it's no better or worse than most languages. It supports bind variables and the documentation pushes you that way.
It's not just PHP. It's too easy to do in many languages. It almost seems odd there isn't a 'libsodium but for DB access' or 'linter that makes your CI server explode on dangerous DB API use'. Things like that don't have to be foolproof but they'd be better than the current anything-goes default.
It's easy to do in any language/framework which accepts raw strings as SQL input. Which is pretty much all of them, except for ORMs and similar (and even those usually have an escape hatch, which sufficiently lazy/clueless developers can and will find eventually).
If a raw string is allowed, then the standard facilities - string concatenation, formatting etc - can be used to write injection-vulnerable code.
The only mitigation that does not require educating the end developers is to completely banish strings from the API, and require everything to go through a DSL layer instead. Said layer can then ensure that all values are properly quoted and/or parametrized prepared statements are used as needed.
"Said Leopard to Baviaan (and it was a very hot day), "Where has all the game gone?"
And Baviaan winked. He knew.
Said the Ethiopian to Baviaan, "Can you tell me the present habitat of the aboriginal Fauna?" (That meant just the same thing, but the Ethiopian always used long words. He was a grown-up.)"
It's been awhile since I used PHP but even if you're not using a framework I'm pretty sure you can just wrap your strings with mysql_escape_string or some similarly named function.
It has also been a long time since I've used php, but when I did there were a few problems here.
One is that mysql (opposed to oracle or pgsql) is kind of unusual in allowing quotes indiscriminately for all column types, so in order to do this right you have to only do it for string type columns and prevent injection on different types some other way.
Another is that most of the APIs around the more sprintf-style quoting (eg: `query("SELECT * FROM table WHERE x = %", someStr);`) are tied into prepared statements, which carry their own problems that also differ per engine.
It's actually not as simple as you might think. On top of that, php used to have the whole automatic quoting thing that just made a hash out of things.