Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Where to begin?

- No proper connection pooling with circuit breakers.

- No proper multithreading (that works in web environment) or parallelism in general.

- Almost everything blocks (even `new PDO('mysql:...')` can block for whatever the execution time limit is, if there is an issue with connection or MySQL server).

- Most libraries are implemented in C instead of in PHP, whereas with other languages people try to avoid native code as much as possible. This means that code is not memory safe, and understanding or contributing is close to impossible.

The reason for this is because PHP doesn't support many things that are expected in any other language.

PHP C API is hard to understand, hard to use, and documentation is subpar.

- There is no way to easily share memory between processes. You have to rely on APCu (hack), because this cannot be implemented in PHP.

- Did I mention that almost anything can block? ODBC? PDO? Some 3rd party library? Even set_time_limit cannot help you here. Handling this gracefully is close to impossible.



Something being written in C does not mean "understanding or contributing is close to impossible". That's as much of a boogeyman as I've ever seen.


It is when discussing the merits of a given language, and the assumption is "a person knows the language under discussion".

I.e., for the criticism to not apply in this context, a solid PHP developer...has to also be a solid C developer. Given the context is "using PHP", the former is likely, the latter, not so likely. Exactly how likely I don't know (I don't use PHP, so don't really have an opinion anywaay), but most discussions I've seen around PHP don't also presume the adoption of C.


- No proper multithreading

Maybe you are not familiar with PHP multithreading in recent times but I have been using https://github.com/krakjoe/pthreads and works perfectly. No process forking.


Haven't been following php in years, but from back in the day I remember many different approaches trying to introduce threads and none could guarantee safety for the fundamental reason that the language itself is implemented unsafely. The runtime was done in C with unsafe features from the start. So process forking was the only sane reason to run php. I don't know how much of that is still true, though.


still, no proper multithreading, in comparison with Java, C#, Elixir...


Define proper please.


No native support for concurrency operators, no real event loop implementation, lack built-in support for non-blocking IO... I do Elixir regularly and Actor Model is not something PHP developers know


> I do Elixir regularly and Actor Model is not something PHP developers know

/me clutches pearls

What a travesty! I wish, I, a lowly, stupid PHP developer was smart enough to know about the Actor model!

/s


Look into ReactPHP, Swoole and Spatie


Is this just a long way of saying it doesn’t have “async” because threads are a perfectly fine concurrency primitive that you can build event loops on top of.


There is async in PHP


Not being a BEAM language is not unique to PHP or it's relevant peer languages.


"No true Scotsman," I'd wager.


> There is no way to easily share memory between processes

What about https://www.php.net/manual/en/ref.shmop.php ?


Yeah, that comment stuck out to me as I've used shared memory segments in PHP before and these functions work just fine.


not atomic


Where to begin indeed!

> - No proper connection pooling with circuit breakers.

PHP has had a "shared nothing" architecture since the very beginning, that includes DB connections. It helps it to scale (think micro-services being stateless in a modern context): nothing is shared between requests, again including connections, by design.

> - No proper multithreading (that works in web environment) or parallelism in general.

I once asked Rasmus about this face-to-face, during one of his presentations, specifically his thoughts about the pThread extension (https://www.php.net/manual/en/intro.pthreads.php), and he responded that it was not required in a web context, as web servers already have threads per request so its a mute point.

> - Almost everything blocks (even `new PDO('mysql:...')` can block for whatever the execution time limit is, if there is an issue with connection or MySQL server).

Well, it depends on your code of course, but pretty hard to proceed with some code that works with a DB when the connection can't be established, so proceed with what exactly other than error handling? Seems like a strange example. And as mentioned above, no (excluding optional pThreads) support for asynchronous threads in the language, so...?

> - Most libraries are implemented in C instead of in PHP, whereas with other languages people try to avoid native code as much as possible. This means that code is not memory safe, and understanding or contributing is close to impossible.

Ok now you have just thrown away one of the main benefits of PHP. Remember, Rasmus is a C programmer, not a PHP programmer, so he wanted to leverage that HUGE library of existing C-code from his new scripting language, from the very beginning, deliberately by design.

> The reason for this is because PHP doesn't support many things that are expected in any other language.

Yes it does, via the C-extensions, see above.

> PHP C API is hard to understand, hard to use, and documentation is subpar.

Yes programming in C is hard.

> - There is no way to easily share memory between processes. You have to rely on APCu (hack), because this cannot be implemented in PHP.

Deliberate design choice, "shared nothing architecture", stateless between requests, as above.

> - Did I mention that almost anything can block? ODBC? PDO? Some 3rd party library? Even set_time_limit cannot help you here. Handling this gracefully is close to impossible.

Yes because each request is a synchronous thread, as described above above. By design.


> Yes programming in C is hard.

I'm not anti-PHP, so I'm not supporting the grandparent post in general. But as someone who is working on a PHP extension right now, I agree that PHP's C API is under-documented.

The best semi-official documentation I have found is http://www.phpinternalsbook.com/, but it is incomplete. Some important chapters are just blank, eg http://www.phpinternalsbook.com/php7/internal_types/zvals/me.... A lot of questions I can only answer by grepping the source code of the extensions in the PHP distribution itself.

I don't think this is just a case of "programming in C is hard." Some C APIs are amazingly well-documented, especially Lua. If you open up Lua's reference manual (https://www.lua.org/manual/5.3/manual.html#4), it explains just about everything you need to know to write good C extensions. Every public function, macro, and constant is documented. Python's C API is pretty well-documented too.


> Well, it depends on your code of course, but pretty hard to proceed with some code that works with a DB when the connection can't be established, so proceed with what exactly other than error handling? Seems like a strange example. And as mentioned above, no (excluding optional pThreads) support for asynchronous threads in the language, so...?

What to proceed with? Well, any other code of course! Does all code in a current task depend on writing something to a database or reading from it? What if you need to get data from multiple sources? It would be stupid to wait for every single connection to be made sequentially, instead of proceeding with the next one.

This is just one example. This is actually what Node is often lauded for, making a lot of use of single cores, due to putting one "task" at rest and asynchronously proceeding with the next, not blocking.


  I once asked Rasmus about this face-to-face, during one of his presentations, specifically his thoughts about the pThread extension (https://www.php.net/manual/en/intro.pthreads.php), and he responded that it was not required in a web context, as web servers already have threads per request so its a mute point.
if each web server thread that serves a request ends up spawning a full PHP process then it's not a mute point.

  pretty hard to proceed with some code that works with a DB when the connection can't be established, so proceed with what exactly other than error handling? 
proceed with all the rest of the bootstrapping code in parallel instead of blocking and waiting for each.

  is a synchronous thread, as described above above. By design.
it's a synchronized full forked process. Because the runtime was written using memory unsafe C features from the start. By design doesn't excuse it being a bad design.


It's php-fpm persistent threads (seperate Daemon listening on port or socket), not web server threads, just to be specific. You have a lot of control of how many PHP threads you will allow per web node using php-fpm, very reliable tech. The days of mod_php are long gone.

So I meant one thread per request at the php-fpm level, not Nginx/HTTPD level.

* Edit for spelling


> PHP threads

Still, my understanding is that php-fpm spawns processes, not threads. What is "persistent" is the php-fpm daemon itself that's connected to nginx, but each request spawns a whole process which has to bootstrap your whole framework every time. That's the reason frameworks like symfony run almost mandatorily with something like opcache.


Oh I see, yes you are correct each request will bootstrap your PHP code stack framework each time (mitigate with opcache). Seems weird I know, but it goes back to that "shared nothing" principal: nothing is kept in memory between requests. On the plus side of that principal: nothing is kept in memory between requests that is not currently being used.

Coming from a Java background into PHP, this really confused me at first, until I started to think about PHP's approach as some kind of super-agressive garbage collection: everything gets released in that reqest thread once it's completed.

It's a fundemental design choice of the language that you have to embrace if you want to use PHP (I love it now, simplifies so much), or move on to another language.


> PHP has had a "shared nothing" architecture since the very beginning, that includes DB connections. It helps it to scale (think micro-services being stateless in a modern context): nothing is shared between requests, again including connections, by design.

A bit ironic that you compare it to microservices, because that exact property of PHP makes it massively unsuitable for microservices and scaling, because it requires another layer in between the microservice platform handling the scaling, and the actual application.

PHP has it's uses, but I wouldn't go beyond a classic monolith or "backend/frontend" style application with it, with very little, manual scaling. If you go beyond that, you could probably manage to do that with a proper architecture and doing wonky stuff, but would it be a good fit? Absolutely not.


I've been hearing that "PHP does not scale" arguement for many, many, years, in many, many, variations.

When you really have to scale, infrastructure, resources, and networks will rapidly overtake any concerns around your choice of language. You can develop crappy architectures in any language, and the inverse is true.


Not my experience. At scale, once you go down the 'cloud native' (kubernetes) path, the infrastructure part becomes relatively straight-forward, but PHP's weaknesses become very apparent.

Doesn't work very well with message queues. Sure, pushing messages is not a problem, but consuming? Something has to do it? But it won't be written in PHP. It doesn't work very well with SQL databases, and with that I mean not the querying etc, but connection pooling, so the database server doesn't suddenly gets flooded by thousands of connections because a service is autoscaled due to heavier load (and sadly, that's a real-world example that brought down a database cluster). Tracing is doable, but not ideal, metrics are hacky due to the need of weird extensions to support shared memory, or rely on an external database such as Redis, which kinda defeats the point of metrics being lightweight. And tuning the PHP runtime almost rivals the JRE...


> but pretty hard to proceed with some code that works with a DB when the connection can't be established

When you can't query your DB, you hit your resident memory cache. Redis, Memcached, etc. You probably have background threads that do cache invalidation, queue management, etc.

You frequently have to be more reliable than your database.

> he responded that it was not required in a web context, as web servers already have threads per request so its a mute point.

I use multiple threads in a single request flow frequently. Dispatching requests to other services or data stores, updating in-memory caches or queues (not Redis, but living within the app itself), etc. It's an important tool.

> Ok now you have just thrown away one of the main benefits of PHP. Remember, Rasmus is a C programmer, not a PHP programmer, so he wanted to leverage that HUGE library of existing C-code from his new scripting language, from the very beginning, deliberately by design.

Good for him. I don't see why that matters for anyone else. It's ugly and inconsistent, takes time to memorize, and leads to errors.

> Yes because each request is a synchronous thread, as described above above. By design.

This limits you to writing basic CRUD. And so many other languages offer this.


> When you can't query your DB, you hit your resident memory cache. Redis, Memcached, etc.

You would query those first surely, before loading the DB? Regardless, I've been using Redis and Memcache for years from PHP, so mute point.

> I use multiple threads in a single request flow frequently.

So how do you track those? And for how long do they live after the parent request has been processed, or do they block the parent? Gets complicated quickly.

> It's ugly and inconsistent, takes time to memorize, and leads to errors.

Rasmus will admit the same, but he will also admit he does not care (I've seen him say this during a talk). Nobody bought your product because it had beautiful, consistent code.

> This limits you to writing basic CRUD. And so many other languages offer this.

99.9% of web apps are CRUD.


> You would query those first surely, before loading the DB? Regardless, I've been using Redis and Memcache for years from PHP, so mute point.

You probably want to report a degraded status so any traffic that can be bled off into another cluster can do so.

> So how do you track those?

There's a thread pool.

> And for how long do they live after the parent request has been processed.

They might live on after the request flow if they're still doing work.

> or do they block the parent?

Depends on the job and the nature of the API.

> Gets complicated quickly.

That's engineering.

> Rasmus will admit the same, but he will also admit he does not care (I've seen him say this during a talk). Nobody bought your product because it had beautiful, consistent code.

That's why I buy a lot of things. It's also one of many reasons why I don't buy PHP.

> 99.9% of web apps are CRUD.

Now that platforms have taken over, I don't think this is the case. Large systems have sophisticated needs that don't always map to a traditional relational data store. PubSub, feeds, queues, concurrency, eventual consistency, vector clocks, etc.

Platforms are going to eat the long tail in the search for growth.


Just FYI since you've done it twice and might want to know, it's not mute point. It's moot point.


LOL thank you, English is hard (like engineering) ;-)


> The reason for this is because PHP doesn't support many things that are expected in any other language.

And the reason for this is that those parts are handled by web servers and php doesn't need to handle them. Isolation decision that simplifies things significantly infrastructure wise and that allowed for shared hosting to exist - which in turn brought the costs down and made web as popular and massive as it is today.

BTW, this architecture is not that different from what node and others are doing. Instead of having a language/framework that acts as a web server (but too simple, so you still need nginx in front), and then you need a queue service to delegate the jobs, you have a web server that delegates the jobs (requests) to isolated php processes. Model is the same and that's the model that's used everywhere today, just that the moving parts are partitioned a bit differently in different languages.

Of course, it's not a perfect solution to every problem, but works very good for any not-real-time web site/app and in the end RoR, Django, Symfony, etc. they all work in a very similar way (minus the syntactical nuances). For a massive traffic or language level high parallelism just use something else, no one argues against that.


> - Most libraries are implemented in C instead of in PHP, whereas with other languages people try to avoid native code as much as possible. This means that code is not memory safe, and understanding or contributing is close to impossible.

You want this in any scripting language if you don’t want memory use and cycles to balloon out of control for simple tasks. Most any scripting language looking for performance is going “how can I GTFO of myself and into C (or assembly, or maybe these days Rust I guess, in some circles) as fast as possible”.


i think it's where the glue goes. do you implement an algorithm/write a generic library in c and then glue it to your high level language in your high level language, or do you write a plugin for your high level language in c?

in both cases you need to understand pointers and function pointers and the difference between your integer type and a c int, but in one case you're at home while you do it. in one case, you could plug in to any existing c library without writing additional c, so if the problem is already solved you just use the ffi and you're done. in the other case, your problem is just beginning


i think the whole point is that some of those things are not 100% necessary to build great stuff.


Simple blocking IO and no real multithreading are features of PHP.

It's all about simplicity.

In a web app you "multithread" using the web server...




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: