Reading view

Where modern PHP stands in 2026: deployment, architecture, typing, and concurrency

Hello everyone,

I know I'll be preaching to the choir here, but I've put together a small article rounding up the PHP advancements I find most exciting as of 2026.

It covers modern deployment (FrankenPHP, Docker), software architecture (modular monoliths, the Symfony kernel, agents), the type system and its tooling (PHPStan, PHP CS Fixer), and the state of concurrency (ReactPHP, Swoole, the True Async RFC).

Full article: https://morice.live/posts/your-next-project-will-run-on-php/

Let me know if I missed anything, or if you'd like me to go deeper on a specific topic!

submitted by /u/andre_ange_marcel to r/PHP
[link] [comments]

PHP Polling API RFC pass the vote

The RFC voting phase has officially concluded, and it passed with an overwhelming 33–1 vote for inclusion in PHP 8.6!

A big thank you to everyone on PHP Internals who supported it. I'm genuinely excited about PHP 8.6 and can't wait to see what async library maintainers build with the new capabilities this release will bring.

submitted by /u/rc0604 to r/PHP
[link] [comments]

New Yii3 Demo: Document Summarizer

We’ve added a new Yii3 demo application:

https://github.com/yiisoft/demo-summarizer

It started as a practical way to test yiisoft/queue together with AMQP and Redis/Valkey drivers in Yii3 application, but it turned into a useful demo on its own.

The app lets you upload documents, extract readable markdown, summarize content with a local OpenAI-compatible llama.cpp service, and track processing progress through Yii Queue workers. It supports multiple queue drivers, background workers, S3-compatible storage via Garage, retries, deletion, and clearing all stored data and pending jobs.

By default, it runs with AMQP protocol, two RabbitMQ workers, Kreuzberg extraction, Garage storage, and a small CPU-friendly Gemma model through llama.cpp.

It is useful if you want to see:

  • Yii3 app structure in practice.
  • Native yiisoft/queue worker usage.
  • AMQP and Redis/Valkey queue drivers.
  • Docker-based local development.
  • File upload validation and processing.
  • S3-compatible storage integration.
  • Local LLM integration through an OpenAI-compatible API.

Try it with:

make build make up make -- yii migrate:up -y 

Then open http://127.0.0.1/

Feedback and improvements are welcome.

submitted by /u/sam_dark to r/PHP
[link] [comments]

PHP 8.5.7 released, let's talk about tracing JIT!

TL;DR: tracing JIT fixes are only ported to actively supported branches (e.g. 8.4 and 8.5, not 8.2 and 8.3). Tracing JIT is causing a lot of crashes. If you are on any previous version of PHP, you should update to an actively supported branch (8.4.22+/8.5.7+), or disable tracing JIT (maybe use function JIT or turn JIT off altogether).

Hey everyone, I'm Levi Morrison. I've been working on fixing crashes for our customers at Datadog, and lately I've been investigating tracing JIT because it appears as if many of our customer crashes are caused by it. I've not been authorized (yet) to share numbers, but it's a lot of crashes each week.

It's important enough to repeat: tracing JIT is causing a lot of crashes every week\*.

The good news is that fixes for tracing JIT are being shipped at a regular cadence. Here I stripped duplicates, keeping only the lowest version it was shipped to (except the 3 fixes for 8.5.7, since 8.4.22 hasn't been released quite yet):

PHP version Date Tracing JIT fix
8.5.7 04 Jun 2026 Fixed tracing JIT crash when a VM interrupt is handled during an observed user function call.
8.5.7 04 Jun 2026 GH-21746: Segfault with tracing JIT.
8.5.7 04 Jun 2026 GH-22004: Assertion failure at ext/opcache/jit/zend_jit_trace.c.
8.4.21 07 May 2026 Fixed faulty returns out of zend_try block in zend_jit_trace().
8.4.20 09 Apr 2026 GH-21267: JIT tracing infinite loop on FETCH_OBJ_R with IS_UNDEF property in polymorphic context.
8.4.18 12 Feb 2026 GH-20818: Segfault in Tracing JIT with object reference.
8.4.14 23 Oct 2025 GH-19669: Assertion failure in zend_jit_trace_type_to_info_ex.
8.4.7 08 May 2025 GH-18136: Tracing JIT floating point register clobbering on Windows and ARM64.
8.4.3 16 Jan 2025 GH-17140: Assertion failure in JIT trace exit with ZEND_FETCH_DIM_FUNC_ARG.
8.4.1 21 Nov 2024 GH-15178: Assertion in tracing JIT on hooks.
8.3.19 13 Mar 2025 GH-17868: Cannot allocate memory with tracing JIT.
8.2.27 19 Dec 2024 GH-16770: Tracing JIT type mismatch when returning UNDEF.
8.1.15 02 Feb 2023 Fix zend_jit_find_trace() crashes.
8.1.15 02 Feb 2023 Added missing lock for EXIT_INVALIDATE in zend_jit_trace_exit.
8.1.8 07 Jul 2022 GH-8591: Tracing JIT crash after private instance method change.
8.1.7 09 Jun 2022 GH-8461: Tracing JIT crash after function/method change.
8.0.15 20 Jan 2022 #81679: Tracing JIT crashes on reattaching.

PHP 8.5.7/8.4.22 have 3 tracing JIT fixes, which is why I'm writing this now: plan to go upgrade next week!

Now for the bad news: tracing JIT fixes generally don't qualify as security defects, so they are only shipped to branches with active support, which at the moment means 8.4 and 8.5 only. There have been at least 10 tracing JIT fixes which are unique to PHP 8.4/8.5!

The bad news continues because there's a pretty big chunk of the community that is using PHP 8.3 or older (go look at Zend's PHP Landscape Report). In fact, if you look at that report, you'll see that the majority of the ecosystem is on 8.3 or older. This big chunk is not getting fixes for tracing JIT crashes.

So... here are my recommendations for people using tracing JIT:

  • If you can, upgrade to PHP 8.5.7 (or 8.4.22, which should be released soon), and be prepared to update every single month to the latest PHP 8.5.x or 8.4.x if there are tracing JIT fixes.
  • If you can't upgrade, then either "downgrade" to function JIT or disable JIT altogether. I recommend disabling JIT for web SAPIs and downgrading to function JIT for the CLI.

* There is a detail here worth sharing: one of the bugs fixed in PHP 8.5.7 is related to PHP's internal vm_interrupt leading to crashes with tracing JIT. Datadog products set vm_interrupt, especially the profiler, so the reported volumes of crashes that Datadog sees are perhaps higher than the community's at large. However, you can see above a stream of tracing JIT fixes being shipped throughout PHP's lifetime and it's not slowing down: PHP 8.4 and 8.5 have more tracing JIT fixes than other releases.

submitted by /u/MorrisonLevi to r/PHP
[link] [comments]

xphp: generics for PHP via compile-time monomorphization

TL;DR

xphp is a PHP superset: you write class Box<T> and new Box<User>(), and a compiler monomorphizes it into plain PHP -- one concrete class per instantiation, native typehints baked in, nothing generic left at runtime.

Disclosure up front: I'm the author and I built this with heavy AI assistance (Claude) in every stage -- design, code, and tests. It's all v0.1. I'm after honest technical feedback more than stars, and "an AI wrote it so it's slop" is fair game too if the code earns it.

The idea

You write .xphp files with class Box<T> and new Box<User>(). The compiler monomorphizes them into plain PHP: one concrete class per instantiation, native typehints baked in, zero generics left at runtime. It compiles to vanilla PHP -- no extension, no runtime. You can drop a single .xphp file into an existing app and compile just that.

Box<int> and Box<User> each become a real class after compilation.

final class T_6da88c34 implements \App\Box { public function __construct(public readonly int $value) {} public function get(): int { return $this->value; } } 

The template itself compiles to an empty interface Box {}, and every specialization implements it -- so instanceof Box still works across all Box<...>.

How it parses syntax PHP can't

<T> is a syntax error -- to PHP and to nikic/php-parser, < is the comparison operator.

Forking the grammar is a maintenance black hole, so instead:

  1. Tokenize with PhpToken (strings and comments handled correctly).
  2. Walk the tokens, detect class IDENT <...>, function name<...>, and Name<...> call sites, recording each with its byte range and a parsed type-arg tree.
  3. Replace each <...> clause with equal-length whitespace -- the result is valid PHP whose byte offsets and line numbers are byte-identical to the original.
  4. Parse that with nikic/php-parser.
  5. Walk the AST and reattach the generic metadata by matching (line, name) plus order.

It's being built as an ecosystem, not a monolith

The design choice throughout is to plug into existing tools instead of replacing them, and to have everything reuse the compiler's own core rather than reimplement semantics. That's the only way the surrounding tools stay honest -- and the shape an ecosystem needs, even if it's all day-one right now:

  • Editor support: a language server that reuses the compiler's own AST, instantiation registry, and type hierarchy directly -- so definition, references, rename, completion, hover, inlay hints, and diagnostics run on the same semantics the compiler uses, not a second guess. Ships as a PHAR, works with any LSP-capable editor, and a PhpStorm plugin bundles it.
  • Framework integration: a Symfony bundle that hooks compilation into cache:warmup, so the generated PHP falls out of your normal build as a deploy artifact with no extra pipeline step. It can also register a specialization like CachedFinder<User> as an autowired service, so you inject the concrete type straight from the container. (Requires Symfony 8 / PHP 8.4.)

Compiler, editor tooling, framework integration: separate repos, one shared core.

What honestly does not work [yet]

  • The < disambiguation is a heuristic. You can't write bare-identifier comparison chains like FOO < BAR > BAZ in an .xphp file -- it gets misread as a generic and dies with a confusing parse error that points at the stripped source, not your code. Variables, parens, and :: all defuse it, so it's narrow, but it's a real hole.
  • Foo<Bar>[] (array of a generic) is not supported.
  • Generic methods only on non-generic classes for now.
  • The LSP is explicitly partial; the PhpStorm plugin isn't on the Marketplace yet (install from disk).

Prior art I'm not pretending to replace

The long-running generics RFC, the PHP Foundation writeups on why reified generics are hard, Hack/HHVM. This does not attempt runtime reification -- it sidesteps it the way Rust and C++ do, by specializing at build time.

Two questions I actually want answered

  1. Is a build step plus a generated namespace an acceptable tradeoff in a real project, or an instant dealbreaker for you?
  2. Where would this earn its place over docblock generics with PHPStan/Psalm, which already give you the static safety without the codegen?

Repos are under the xphp-lang org on GitHub. Roast welcome.

submitted by /u/Embarrassed-Total609 to r/PHP
[link] [comments]

new PDFParser release with encrypted document support!

A while ago I posted here about the new pdfparser i've been working on: https://github.com/PrinsFrank/pdfparser With the just released version 3 it now also supports encrypted documents! No vibecoded project, just a developer that loves spending his free time on actually solving projects by hand. Let me know what you think and what I should work on next!

submitted by /u/TheTreasuryPetra to r/PHP
[link] [comments]

PHP acronym

So I had a small debate with my professor about what PHP stands for.
I said the official name is “PHP: Hypertext Preprocessor”, since PHP is a recursive acronym. He said the correct answer is simply “Hypertext Preprocessor”.
My point was that “Hypertext Preprocessor” only gives the initials HP, not PHP.
Who’s technically correct?

submitted by /u/almenzarr to r/PHP
[link] [comments]

externals.io has been rewritten to Laravel

externals.io is a website to read the PHP #internals mailing list more easily.

I built it a while ago on a custom microframework (we've all been there I guess?) and of course, that became very painful. I rewrote the app to Laravel, that should make maintenance and contributions much simpler now! The rest hasn't changed.

The code is on GitHub: https://github.com/mnapoli/externals

AFAICT the performance has stayed the same:

  • 50% of requests served under 5ms
  • p90 is 40ms

Let me know if you see any slowness (or better, send a PR :p).

The app runs serverless on AWS Lambda with Bref. It serves ~2.5M requests/month, which costs ~$2.5/mo + $11 for the database. The staging costs $0 because it doesn't receive enough traffic.

Because of the migration everyone will be logged out once, sorry about that! Just log in again and things should be back to normal.

submitted by /u/mnapoli to r/PHP
[link] [comments]

phpser: a faster, HMAC-signed binary serializer for PHP cache workloads, benchmarked against igbinary

I've reached for igbinary on basically every PHP project I've shipped for the last decade. It's the obvious default for cache serialization. Two things about cache workloads kept nagging at me though, so I wrote phpser to see if a serializer built specifically for caches could do better.

The first is the read/write asymmetry. A cache decodes on every read and encodes once per write, easily 100:1 on a read-heavy cache, but igbinary (like most general serializers) balances the two sides. The second is trust: the bytes you decode often come from redis, memcached, or a cookie, any of which an attacker may be able to write to, and unserialize() on attacker-controlled input is one of PHP's oldest exploit primitives.

phpser is a C extension that goes after both. The wire format is designed around the reader (I borrowed the "make the reader do the least work" instinct from Rust's rkyv, though phpser is not zero-copy): a front-loaded string dictionary the decoder reuses by refcount instead of re-allocating, tagged scalar runs for packed numeric arrays, and pre-sized hashtables written in place. The encoder is fast too, with an O(1) pointer-hash string intern and plain objects serialized straight from their property slots.

Benchmarks vs igbinary (PHP 8.4 NTS release build, 1000 iters, median of 9 runs):

Shape Size Encode Decode
packed_1k (range 0..999) -65% -70% -75%
dto_1000 (Laravel queue shape) -12% -15% -18%
rowset_1000 (mixed assoc) +1% -55% +4%

It's not a clean sweep: mixed associative rowsets decode about 4% slower and run a few percent larger, because the front-loaded dictionary (the thing that makes everything else fast) doesn't pay off when few strings repeat. It's not streamable either, for the same reason.

On the security side there's an HMAC-SHA256 signed mode: phpser_serialize_signed($value, $key) and phpser_unserialize_signed($payload, $key). The signature is verified in constant time before any decoding happens, so a tampered or foreign-keyed payload returns null and never reaches the code that builds objects. There's also an allowed_classes option matching native unserialize().

Install is via PIE: pie install iliaal/phpser

Repo: https://github.com/iliaal/phpser Full writeup with the wire-format walkthrough and the complete benchmark table: https://ilia.ws/blog/phpser-a-fast-secure-binary-serializer-for-php-cache-workloads

I maintain php_excel and a few other PHP extensions; this one scratched a specific itch. Happy to answer questions, and I'd love feedback from anyone running heavy cache or queue traffic where decode time actually shows up in a profile.

submitted by /u/Ilia0001 to r/PHP
[link] [comments]

I built a private family video & media catalog — no cloud, no tracking, just your family's memories

Hey r/PHP

I built a small self-hosted web app for my family to store and share private memories — YouTube links (mostly unlisted), photos, and Google Photos albums — all in one place with proper access control.

Why I built it: We were spreading family videos across WhatsApp groups, shared Google Drive folders, and random YouTube playlists. Nobody could find anything. I wanted one clean catalog that everyone in the family could actually use.

What it does:

  • Add YouTube videos with auto-filled metadata (title, thumbnail, description) via YouTube Data API
  • Organize everything into events (birthdays, trips, holidays) with their own media galleries
  • Fine-grained access control — each video/event/photo can be shared with everyone, specific people, or kept private
  • Invite-only registration via 6-digit codes — no strangers can sign up
  • "What's new" notifications — a bell icon showing everything added since your last visit
  • Thumbnail uploads for events and media cards — auto-resized, EXIF-corrected; no full photo storage, your albums stay in Google Photos
  • Dark/light theme, "Remember me" sessions
  • Video participants — tag family members (or just names for non-members)
  • Comments on videos and events
  • Mobile-friendly via Bootstrap 5

Tech stack: PHP + MySQL (PDO), Bootstrap 5, no frameworks, no Composer, no Docker. Runs fine on any shared hosting.

Demo: https://serwer440097.lh.pl GitHub: https://github.com/alexfreecode/family-video-archive

It's a small project, but it solved a real problem for my family. Happy to answer questions or take feature suggestions.

The code is fully open source under MIT license — contributions welcome. It's intentionally dependency-free so anyone can deploy it on the cheapest shared hosting.

submitted by /u/Sweet_Pear3367 to r/PHP
[link] [comments]

phpsadness is outdated. what's changed since then?

phpsadness.com

This weird site highlighted many issues with PHP.
But, hasn't been updated since 2018.

Let's take a look at the changes in PHP.
I've kept the same order as on the website.

'*' is fix or changed php version

Useless Error Reporting

#16 Exception thrown without a stack frame

* php 8.5

#1 Unexpected T_PAAMAYIM_NEKUDOTAYIM

* php 8.0

#7 Parse error: syntax error, unexpected T_SL in...

* php 8.0

#54 Empty T_ENCAPSED_AND_WHITESPACE tokens

* php 8.0

INCONSISTENCY

#52 Comparison operators

* He created an example that violates PHP's type casting.

Outright Bugs

#50 Segfault during deep recursion

* php 8.3 bug fixed

#30 Ternary operator associativity

* php 8.0

#39 Declaring a function called __lambda_func() completely breaks create_function()

* php 8.0 removed the funciton

Misleading/Confusing topics

#27 Bad function names - parse_str()

* php 8.5 new URL parser class

Arbitrary Restrictions

#14 - Can't throw exceptions from __toString() functions

* php 8.0

Object-Oriented System Issues

#8 Implementing all the right methods (array) still doesn't work in array functions

* php 8.0 (deprecated because TypeError)

Wow, PHP has improved a lot over the years.
I'd like to thank everyone who works on PHP !

submitted by /u/rioco64 to r/PHP
[link] [comments]
❌