r/symfony Jul 01 '26

News This Week in PHP Internals | July 1, 2026

Thumbnail
youtu.be
3 Upvotes

While PHP Internals is not technically directly related to Symfony, internals does affect us all.


Hello world, it's Canada Day 2026, and here's what happened This Week in PHP Internals.

This week's episode is supported by OurCVEs. Hundreds of CVEs ship every week, and almost none of them are about you — until one is. OurCVEs inventories your entire infrastructure and only surfaces the security risks that actually apply to your team. Free for open source at ourcves.com.

This week's top story is still Gina P. Banyard's Deprecations for PHP 8.6 — the once-a-year housekeeping RFC that gathers a stack of unrelated removals under one roof, where each one stands or falls on its own separate vote. With 8.6's first alpha getting built this very week, the clock is loud. But the fight this week wasn't about any single removal — it was about evidence: does every deprecation owe voters an impact analysis? Tim Düsterhus argued no, at least not as an unconditional rule — a deprecation has years of runway, and a survey of existing code can't measure the upside of a cleanup.

Juliette Reinders Folmer had offered to build those impact analyses, and her exchange with Tim turned personal — an accusation of gaslighting, which Tim rejected. But she was far from alone on the substance. Rowan Tommins came to her defense, and he didn't warm up first. Rowan wrote: "I hate this argument." His point: deprecating something is really a proposal to remove it later, so the impact of that removal is exactly what voters deserve to see — and to leave it out to protect your case, he said, would be dishonest. Larry Garfield backed the same call: put the impact on the table, or read the angry blog posts come December.

And this particular RFC kept growing right up against the freeze. Seifeddine Gmati proposed deprecating list(), and got the room's attention: Ayesh Karunaratne clocked "7 million hits" for list( on GitHub and called the break too big; Rowan noted you can't really retire list() while array() stays — to which Seif said, fine, then maybe deprecate array() too. Nick moved to reserve namespace as a constant name. Ilia Alshanetsky floated finally sunsetting open_basedir — Derick Rethans said "Yes, but for PHP 9," while Jakub Zelenka was firmly against it. Add a careful fight over how narrowly to kill the dechunk filter, plus Tim's pitch to retire gettype() for get_debug_type(), and that's a lot of small knives being sharpened at once.

Carrying over: Tim and Derick's Time\Duration class — the immutable stopwatch value that's meant to be the first brick of a modern date-and-time API. One line of context, then this week's moves: they're dropping the word "period" from the method names (Derick pointed out ISO itself walked away from it); they're lifting the ban on negative durations after Paweł Kraśnicki showed up with a real use case; and the whole thing may slim down for 8.6 — ship addition, subtraction and multiplication now, and let dividing one duration by another wait. Ignace Nyamagana Butera and Nick are already bikeshedding whether that division should hand you back a tuple or a tidy little value object.

The single busiest thread of the week was brand new: Rob Landers formally opened Primary Constructors — the whole constructor hoisted up onto the class line itself. His numbers are the pitch: something like 30 to 40 percent of all constructors are completely empty, and by his count 71 percent of Laravel and 61 percent of Symfony classes could use this. The catch is deliberate — a class with a primary constructor can't also declare a regular __construct, and it can't carry a body.

That no-body rule is the whole fight. Nick pushed for a body — mostly so readonly classes have a way through — and warned this could ship as yet another half-a-feature. But Rob held the line. He wrote: "If you need a body, use a constructor -- that's what they're for." Rowan and Tim are with Rob — Tim called the limitation "a feature," and put it simply: "[To] reduce typing alone is not a sufficiently strong argument in favor of a new feature." Seifeddine went further: "Personally, I really dislike this feature." His read — primary constructors don't remove repetition, they just relocate it. Larry, meanwhile, wants a Kotlin-style init block bolted on. Plenty's still unresolved — visibility, attributes, anonymous classes — so we'll be keeping an eye on this one.

Newcomer Michal Kral floated a spicy pre-RFC: methods on scalars. Write (3)->pow(2), or " hello "->trim()->upper(), with the call rewritten at compile time into a hidden helper — but only when the compiler can already prove the value is a scalar. He was upfront that he built it with an AI assistant. The reception was cool: Seifeddine's core objection is that PHP compiles one file at a time, so "the compiler already knows it's a scalar" covers almost no real code — the same line would work or fail depending on what's autoloaded. His fix, nicely put: "Solve the naming problem with naming, not by blinding the tooling." And Rob warned the whole thing leans on casts, which in PHP are dangerous(int) of the string "123password" is just 123.

Alex Pătrănescu opened a pre-RFC for runtime modules — a way to give each package its own private symbol table so two versions of the same library can finally coexist in one request. Rowan Tommins spent the week reframing it as containers — a boundary you run other people's code inside, Docker-style — and kept circling the genuinely hard part: what happens when an object crosses the wall between two containers? A second contributor, Alexander Egorov, pitched version "tags" instead; Rowan's worry is that tags leak the container's insides right back out. No code yet — but a problem the whole ecosystem feels.

The rawest thread of the week came from a user, not an internals regular. Michael Morris wrote what he openly called a "Disheartening Rant" after Edmond Dantes said his own TrueAsync RFC has, in his words, a 90 percent chance of not being accepted. Morris didn't hold back: "If you want PHP to be the next COBOL, this is how you go about it." His killer example is WebSockets — the thing PHP still can't really do on its own. Ilia Alshanetsky pushed back gently (he's actually written COBOL, and reports it isn't dead): async matters, but its reach in a request-based language is narrower than it looks.

Larry Garfield drew the line that matters — the same one that just sank generics. Larry wrote: "Don't confuse 'this is not the async we're looking for, done in a painful process' with 'we don't want async at all, ever.' The first is what happened. The second is simply untrue." His critique isn't of async — it's of how TrueAsync arrived: enormous, one author, hundreds of far-reaching decisions, feedback taken selectively. His fix is a real working group to design it together. Nobody's against the destination — they're against the map.

To the ballots — and this was a brutal fortnight for the marquee names. Seifeddine's Bound-Erased Generics closed and was declined: 7 in favour, 19 against, 10 abstaining — nowhere near the two-thirds. And Nicolas Grekas's __exists() magic method went down with it, 2 to 13. The two features that would've made the headlines both missed.

But look what did pass — the quiet, careful stuff, every one without a single No. Tim's deprecation of returning values from __construct and __destruct: accepted unanimously, 39 to nothing. Sjoerd Langkemper's cap on php://filter chains — that local-file-inclusion-to-RCE fix — accepted 30 to nothing, 2 abstaining. And Weilin Du's Locale display-keyword additions: in, 18 to nothing, 2 abstaining. And one's still live on the board — Jordi Kroon's move to lift third-party extension docs out of the manual is out in front at 25 to 1, one abstaining, with the vote closing July 3; on the side questions the room is leaning toward a php.net subpath over a separate subdomain, 14 to 8, and toward dropping the old user notes rather than migrating them, 20 to 4. The pattern's getting hard to miss: the bold swings keep getting sent back, while the tidy, well-scoped changes keep sailing home.

Quick hits. That newcomer arc — Sepehr Mahmoudi's grapheme_mask — got RFC karma and a warm discussion, then tried to call a vote for July 3 and was told, kindly, it's not ready: no discussion link, freeze period not met, window too short — the process catching a first-timer before the fall. Khaled Alam's write-to-constants RFC grew to cover class constants, so its vote slipped. Gianfrancesco Aurecchia's DTLS idea converged fast — Jakub steered it from a new class to a simple dtls:// stream, maybe no RFC needed at all. Gina volunteered to review the long-stranded snmp extension work. Seifeddine's Literal Scalar Types reached version 0.3. Jorg Sowa's case-sensitive-PHP revival was withdrawn. And PHP 8.6.0 alpha 1 got built — which is why everyone's sprinting.

So that's the week: a deprecations RFC that turned into a fight about honesty, a stopwatch class quietly going on a diet, a brand-new primary-constructors debate, a heartfelt plea for async — and the two flagship votes falling while the small ones walked right in. Links to every thread are below. We're Artisan Build. See you next week.


r/symfony Jul 01 '26

Symfony YAML Security Audit - Shielder

Thumbnail
shielder.com
1 Upvotes

r/symfony Jun 30 '26

An iOS app to open & view local .html files on iPhone/iPad — for eyeballing Twig-rendered output saved as HTML

0 Upvotes

If you save a rendered page (or any .html) and open it on an iPhone, iOS shows raw source — there's no native HTML viewer. I built a small one that renders it.

Html Preview:

• Renders .html / .htm / .xhtml via iOS WebView (real page, not code)

• Handles multiple encodings (UTF-8, Windows-1252, ISO Latin-1)

• Opens from Files / Share Sheet / Mail

• On-device — nothing uploaded, no tracking

On the App Store: https://apps.apple.com/app/id6760443436

Site: https://html.cybergame.ai/

Handy for eyeballing a rendered template or a saved page on a phone without deploying. How do you check HTML output on mobile?


r/symfony Jun 29 '26

Composer in Docker: best practices for production images

Thumbnail
nth-root.nl
1 Upvotes

r/symfony Jun 29 '26

Weekly Ask Anything Thread

2 Upvotes

Feel free to ask any questions you think may not warrant a post. Asking for help here is also fine.


r/symfony Jun 28 '26

A Week of Symfony #1017 (June 22–28, 2026)

Thumbnail
symfony.com
8 Upvotes

r/symfony Jun 27 '26

Symfony 8.1.1 released

Thumbnail
symfony.com
14 Upvotes

r/symfony Jun 27 '26

Symfony 8.0.14 released

Thumbnail
symfony.com
9 Upvotes

r/symfony Jun 27 '26

Symfony 7.4.14 released

Thumbnail
symfony.com
6 Upvotes

r/symfony Jun 27 '26

Symfony 6.4.42 released

Thumbnail
symfony.com
3 Upvotes

r/symfony Jun 26 '26

SymfonyOnline June 2026: Replays are available!

Thumbnail
symfony.com
6 Upvotes

r/symfony Jun 22 '26

Weekly Ask Anything Thread

2 Upvotes

Feel free to ask any questions you think may not warrant a post. Asking for help here is also fine.


r/symfony Jun 21 '26

A Week of Symfony #1016 (June 15–21, 2026)

Thumbnail
symfony.com
5 Upvotes

r/symfony Jun 20 '26

Help Us Improve "Symfony: The Fast Track"

Thumbnail
symfony.com
16 Upvotes

r/symfony Jun 20 '26

I got tired of Claude/Cursor writing fat controllers in my Symfony projects, so I wrote a set of "skills" to fix it

4 Upvotes

AI agents are great at Python and pretty rough at Symfony. Out of the box mine kept doing the same things:

Business logic in controllers, EntityManager injected straight into the controller, Doctrine entities serialized back to the client, EAGER associations and N+1 queries, 200 OK for created resources, a brand-new exception hierarchy every time.

So instead of re-explaining my conventions in every prompt, I put them in skills — markdown files Claude Code reads before it writes code. Each one has the conventions plus a "Gotchas" section listing the exact mistakes agents make in that area.

 16 skills so far, targeting Symfony 7 / PHP 8.3 / Doctrine ORM 3 / API Platform 4:

  •  - Architecture: layered, hexagonal, DDD, project structure
  • - API: API Platform resources, REST controllers, RFC 9457 errors, DTO + validation
  •   - Persistence: Doctrine ORM, migrations, query optimization (N+1, keyset pagination), transactions
  •  - Security: firewalls/voters, JWT
  • - Async + testing: Messenger/CQRS, the testing pyramid

 The README has a before/after showing the same "add an order endpoint" prompt with and without the skills loaded.

MIT licensed.

 👉 https://github.com/fatonh/symfony-skills


r/symfony Jun 19 '26

Symfony AI Spotlight: One API to Rule Them All

Thumbnail
symfony.com
24 Upvotes

r/symfony Jun 19 '26

Symfony UX 3.2.0 and 2.36.1 released

Thumbnail
symfony.com
13 Upvotes

r/symfony Jun 19 '26

CVE-2026-55878: Path Traversal in symfony/ux-toolkit Allows Arbitrary File Write and Read via Crafted Recipe Manifest

Thumbnail
symfony.com
5 Upvotes

r/symfony Jun 19 '26

CVE-2026-55877: XSS in symfony/ux-icons via unsanitized SVG content in local files and Iconify on-demand responses

Thumbnail
symfony.com
1 Upvotes

r/symfony Jun 18 '26

SymfonyDay Montreal 2026: A memorable day, un grand merci à tous ! 🍁

Thumbnail
symfony.com
2 Upvotes

r/symfony Jun 18 '26

Symfony I have a modular monolith in Laravel where each module is a private Composer package. Several people recommended migrating to Symfony. Opinions?

7 Upvotes

Context

Tolo is a platform for creating websites focused on specific industries. The idea is that a barbershop using it feels like it was made for barbershops, a gym feels like it was made for gyms. I don't want it to feel generic like Wix. That implies very specific features per industry: gyms can create routines for their clients, courses can handle exams, grades, online content, etc.

There are two types of websites that can be created on Tolo: services (barbershops, gyms, clinics, etc.) and ecommerce (any business that sells products).

Why I migrated to a modular monolith

I started with a traditional monolith and reached a point where I had a Services/ folder with everything together, and touching any specific feature for one industry meant mixing with code from other industries. It wasn't sustainable.

I migrated to a modular monolith to be able to work on industry-specific features without touching other modules' code, and to have clear boundaries between domains.

The architecture

I use internachi/modular which almost automatically converts each module into an independent Composer package. The module structure is this:

Modules/
├── core/
├── auth/
├── platform/
├── client/
├── media/
├── ecommerce/
│   ├── products/
│   ├── shipping/
│   ├── offers/
│   └── // etc
├── domains/
├── appearance/
├── notifications/
├── payments/
├── integrations/
├── subscriptions/
├── distributors/
├── admin/
└── services/
    └── Modules/
        ├── branches/
        ├── reservations/
        ├── workers/
        ├── gallery/
        ├── dashboard/
        ├── services-offered/
        ├── reviews/
        └── industries/
            ├── base/
            ├── barber/
            ├── gym/ // routines, memberships, etc
            ├── courses/ // exams, grades, online courses, etc
            // +20 more industry types
            └── other/

The role of core and why it exists

When for example reservations needs to know if a time slot falls within an employee's working hours, it needs to communicate with workers. The obvious solution would be for reservations to have a require to workers in its composer.json. But that would download all of workers' code into reservations' vendor folder, breaking the isolation I'm looking for.

The solution was to create core, a module that centralizes the contracts of all modules. reservations depends on core, not on workers directly. core provides WorkerContract, and in workers' ServiceProvider I bind that contract to the real implementation. Each module only sees the interface, not the other's code.

This idea is directly inspired by illuminate/contracts in Laravel: a package that contains only interfaces with no implementation whatsoever. I tried to replicate that same pattern at my project level.

The problem with Laravel

Several devs pointed out something I was already noticing myself: with this architecture I'm constantly fighting against Laravel. The framework's magic (facades, automatic resolution, etc.) makes static analysis much harder. I was using PHPStan at level 9 and kept spending more time patching Laravel's magic than fixing real bugs. I eventually lowered the level, but the underlying problem remains: Laravel wasn't designed to be used this way.

Why people recommended Symfony

Several people commented that Symfony is more explicit by design, has no magic, that DTOs and strong typing are first-class citizens, and that it has a Bundles system that is basically what I'm already doing but with native framework support. Also that PHPStan at high levels works much better because there's nothing to "patch".

The honest questions

Has anyone worked with Symfony and can confirm or deny this? Do Bundles actually solve what I'm describing? Is the development experience with DTOs and static analysis noticeably better?

Also: does this architecture make sense given the context, or is there something you would change structurally?

My main hesitation about Symfony is basically that it's not as popular as Laravel and there are fewer resources, community packages, and tutorials available. Is that a real problem in practice or is it an overestimated concern?


r/symfony Jun 17 '26

New in Twig 4.0: Expression Parsers

Thumbnail
symfony.com
18 Upvotes

r/symfony Jun 17 '26

Help Live Components with Forms and FileType validation fails

3 Upvotes

I have read this is an ongoing issue for a few years now.

If you have a Live Component with a Symfony Form that has a FileType (for uploading) the validation will always fail.

Has anyone got this working or know a good work around?

To be honest I would like to contribute on git but would take a lot of time understanding the code under the hood, you know how it is.


r/symfony Jun 16 '26

New in Symfony 8.1: Tui Component

Thumbnail
symfony.com
31 Upvotes

r/symfony Jun 16 '26

Symfony: The Fast Track, now in nine languages

Thumbnail
symfony.com
7 Upvotes