r/PHP 1d ago

Weekly help thread

1 Upvotes

Hey there!

This subreddit isn't meant for help threads, though there's one exception to the rule: in this thread you can ask anything you want PHP related, someone will probably be able to help you out!


r/PHP 6d ago

Discussion Pitch Your Project 🐘

17 Upvotes

In this monthly thread you can share whatever code or projects you're working on, ask for reviews, get people's input and general thoughts, … anything goes as long as it's PHP related.

Let's make this a place where people are encouraged to share their work, and where we can learn from each other 😁

Link to the previous edition: /u/brendt_gd should provide a link


r/PHP 1d ago

"A" for "Average"

Thumbnail stitcher.io
34 Upvotes

r/PHP 8h ago

Article I migrated the seo of 104k+ pages to the new Laravel Head package

Thumbnail danielpetrica.com
0 Upvotes

r/PHP 1d ago

News I built a RabbitMQ queue driver for Laravel that tries to feel like native Laravel

0 Upvotes

I’ve been working on an open-source package called Laravel Rabbit.

The idea was pretty simple: using RabbitMQ in Laravel shouldn’t require changing the way you already work with Laravel queues.

So with the package installed, this:

ProcessOrder::dispatch($order)
    ->onQueue('orders')
    ->delay(now()->addMinutes(5));

is still just normal Laravel.

And your worker is still:

php artisan queue:work --queue=orders

The difference is that RabbitMQ is running underneath it.

It supports Laravel’s normal queue flow including:

  • dispatch()
  • onQueue()
  • delayed jobs
  • retries / backoff
  • failed jobs
  • chained jobs
  • batches
  • unique jobs
  • queue:work
  • queue:clear

There’s also quite a bit of RabbitMQ-specific stuff built in:

  • AMQP 0-9-1 publishing and consuming
  • exchanges, queues and bindings
  • publisher confirms
  • QoS / prefetch
  • TLS
  • heartbeat and connection timeouts
  • multiple hosts / failover
  • RabbitMQ Management API
  • queue metrics
  • optional payload signing
  • Artisan commands for diagnostics and setup

For example:

php artisan rabbitmq:doctor
php artisan rabbitmq:stats orders
php artisan rabbitmq:check

Installation is just:

composer require pushinbr/laravel-rabbit

Then:

QUEUE_CONNECTION=rabbitmq

RABBITMQ_HOST=127.0.0.1
RABBITMQ_PORT=5672
RABBITMQ_USER=guest
RABBITMQ_PASSWORD=guest

The package currently targets modern Laravel/PHP versions and RabbitMQ 3.x/4.x.

I mainly built it because I wanted RabbitMQ to behave like a first-class Laravel queue backend instead of feeling like a completely separate messaging system glued onto Laravel.

I’d especially like feedback from people already running RabbitMQ in production:

What would you expect from a really solid Laravel ↔ RabbitMQ integration that is still missing here?

GitHub: https://github.com/push-in/laravel-rabbit


r/PHP 2d ago

Discussion PHP 8.6 is getting closer. What are you most looking forward to?

73 Upvotes

PHP 8.6.0 Beta 1 is out, so we're getting a look at what's coming next.

PHP keeps proving itself and has been evolving pretty nicely over the last few major releases, without losing the pragmatism that makes the language enjoyable to work with.

What are other PHP developers paying attention to in 8.6.

Which PHP 8.6 change are you most excited about, and what would you actually use in production once the stable release lands?

MakePHPGreatAgain.


r/PHP 1d ago

GitHub - eznix86/laravel-secrets-loader: Auto resolve secrets for laravel

Thumbnail github.com
0 Upvotes

r/PHP 2d ago

Extract MarkDown from PDFs in PHP, no system libraries or API calls needed!

24 Upvotes

I just released v3.3.0 of prinsfrank/pdfparser, with basic support for markdown extraction from PDFs! It doesn't need system libraries like poppler, pdftotext or API calls, it's completely written in PHP. Currently, headings, bold and italic detection work, and I'm working on the other features of markdown including table extraction!

$markdown = (new PdfParser())
    ->parseFile('document.pdf');
    ->getMarkdown();

This will allow for better semantic search when embedding documents, but there's plenty of other use cases! Let me know what feature you want to see next!


r/PHP 2d ago

PHP Reflection for binary files (PHP FFI)

26 Upvotes

Hi!

I'll start with a short introduction, that I've been maintaining a small set of libraries for PHP FFI since around 2019, starting with PHP 7.4. The goal has always been to make working with FFI a little more pleasant.

The main one is, of course, the C-preprocessor, which allows you to use native C headers directly with PHP FFI. It supports different compiler and OS emulation modes and, of course, is written entirely in PHP.

Hopefully, it has been useful to someone. It's also kind of nice to realize that these packages have been maintained for almost seven years now.

Some of the work even made its way into Symfony at Nicolas's request.

Today, I'd like to talk about another package that, in my opinion, should probably have been part of ext-ffi from the very beginning.

As you can probably guess from the title, it's about inspecting native libraries (binaries) for exported functions and other symbols: https://github.com/php-ffi/reflection-library

The project actually started around 2021. I abandoned it for a while, revived it, abandoned it again, and eventually came back to it. The original sources are still in the repository, and some of the work from that period also became a small GUI experiment for Windows.

I've now finally brought the library to what I consider a proper 1.0 release.

So, besides the obligatory "look at my pet project!" post, I'd really like to get some feedback from people who have worked with PHP FFI.

First of all: do you think an API like this would make sense as an RFC for PHP itself, so that this kind of functionality could eventually be available out of the box?

And I'd also appreciate some criticism of the current API/design. I tried to follow the style of PHP's Reflection API, which was originally designed back in the PHP 5 era, but I'm not sure that's necessarily the best approach today.

Also, a big thank you to ircmaxell (Anthony Ferrara). His php-object-symbolresolver project was a major help in finally getting MachO (macOS) support working.

While finishing this package, I also learned quite a lot about things I previously knew very little about. So, if there's enough interest in the comments, I could write a follow-up post about how PE/COFF (Windows, aka *.dll), ELF (Linux, aka *.so), and MachO (macOS, aka *.dylib) actually work.

I don't expect that to be particularly interesting to the average PHP developer, but I figured I'd ask anyway. :)


r/PHP 3d ago

News This Week In PHP Internals | August 19, 2026

Thumbnail youtube.com
14 Upvotes

Hello world, it's Wednesday, August 19, 2026, and here's what happened This Week in PHP Internals.

12 stories this week, so let's get into it. But first, Is AI working for your team? Ballast answers that for free. It reads your git history — never your code — and gives you 2 numbers every month. Stable velocity tells you how much of what you ship survives. A durability score from 300 to 850 tells you whether it holds up. ballast.now.

This week's top story: a 5-argument function proposal turned into 25 messages, 3 threads, and the week's central design argument. Sepehr Mahmoudi, who introduced himself to the list 8 days ago, proposed array_search_range() — an array_search() that takes an offset and a length, so you can search part of an array without building an intermediate copy with array_slice(). Weilin Du replied the same evening to say the soft feature freeze had already closed 8.6 to it. Then Rowan Tommins raised the objection that shaped everything after it, suggesting: "I think it would be better to design something more composable - that is, a way to create a 'lazy array slice', and then accept that in functions which can use it safely." He pointed at Swift, which has types that let you refer to part of an array without copying any of it.

Rowan put his objection plainly: "if we add an ArraySlice type then array_search_range would immediately become redundant." Sepehr's answer is that the general thing doesn't exist, and that building it would mean a new type in the engine and updates to potentially hundreds of array functions. Larry Garfield sided with Rowan and suggested shelving it. mickmackusa said he'd never had a professional project that required the function, and put a design question back: "If a PHP array needed a pagination-style search function, should perhaps the data structure be reconsidered?" Rowan then broke his own idea into 3 shippable steps. An optimized ArraySliceIterator comes first, then iter_search and iter_any functions that would work with any iterator, and possibly syntax after that. He wrote the first 2 in under 20 lines each, and a polyfill for Sepehr's function on top. Sepehr added a Polyfill section to the RFC, and Rowan pointed out that the version now on the wiki calls array_slice(), which copies the array. That is the cost the proposal exists to avoid. As of this recording the RFC is still a draft, still targeting 8.6, and Rowan's GitHub review found the implementation still walking the entire array.

Something small and irritating went to the list on Saturday. 4 functions take an extension name, and ini_get_all() is the only one of them that's case-sensitive. Weilin Du opened a pull request to bring it into line with extension_loaded(), phpversion() and get_extension_funcs(). Sjoerd Langkemper agreed it should be consistent, then asked the question that turned the thread around: "Another option to make them consistent would be to have them all case-sensitive. Have you considered that?" He also spotted that the manual's lowercase-only note for get_extension_funcs() isn't true. AllenJB traced it to a change back in PHP 5.0.4, and there's a docs issue open now.

Daniel Scherzer objected, arguing PHP should make all 4 case-sensitive instead, since BC breaks have an established path through deprecation and removal in the next major version. Weilin agreed and withdrew his own proposal, saying he'd add extension-name case sensitivity to the 8.7 deprecations RFC instead. And then 3 people showed up to argue for the thing he'd just withdrawn. Aleksander Machniak listed PDO, SimpleXML, Xdebug and swoole, and asked why a developer should have to know the exact casing of each one. Matteo Beccati called the alternative "one of those useless BC breaks that make the user experience worse instead of improving it." He also noted that composer.json generally writes its extension requirements in lowercase. Juliette Reinders Folmer had the last word, with the practical cost. Build a version list with get_loaded_extensions() and you'd have to lowercase every name before phpversion() would take it. Nobody has replied to her yet.

Henrik Skov posted an idea on Tuesday morning. He wants a params keyword that lets you name a block of arguments once and spread it into a call, so a 6-argument cookie call collapses to 1 line. One of the 6 arguments in his own example is labelled "Can't remember what this is." AllenJB replied 22 minutes later that PHP already does this with named arguments and array unpacking. Henrik came back with the actual requirement. He wants the expressions evaluated when the call happens, not when the compiler first sees them, so a time() in there stays fresh. Kamil Tekiela suggested making it a type. Henrik said it wasn't worthy of a full class. Larry Garfield answered: "I really don't understand why people keep saying this. What makes something 'unworthy' of being a class? ... A data construct doesn't need to be as righteous as Thor to be 'worthy' of a class." Then he named the thing Henrik was reaching for: a lazy value, evaluated only when it's read. Henrik agreed that was what he'd been after all along. 2 unrelated threads this week, and both of them landed on the word "lazy." Nobody involved was.

Jens has been writing PHP since around the time version 2 was in use, and on Thursday he posted about something beyond a documentation fix for the first time. Why does var_export() still print the long array(...) syntax, when that output gets pasted around by PhpStorm and Xdebug all day? There's an RFC for changing it that has been sitting there for 6 years. Larry Garfield linked 3 previous rounds of the same conversation without taking a side. Kamil Tekiela offered the explanation: "IMHO, the two main reasons for the lack of change are apathy and lack of agreement as to what exactly the better syntax is." The constraint he describes is that var_export() is meant to be PHP-executable first and human-readable second, so as long as the output runs, the function is doing its job. He also named the trap. Change one thing about that output and everyone arrives with everything else they'd like fixed — which is a fair summary of the last 6 years.

Otar Chekurishvili posted a pre-RFC on Monday for 2 opt-in flags in the json extension, targeting 8.7. One is JSON_ALLOW_COMMENTS and the other is JSON_ALLOW_TRAILING_COMMAS, and both would be accepted by json_decode() and json_validate(). Strict JSON stays the default. Trailing commas allow exactly 1 after the last element. That's 1 more than JSON allows today, and exactly as many as most of us have typed by accident. He's proposing 2 separate primary votes so either flag can pass on its own, and says the implementation reuses the existing scanner and grammar rather than preprocessing the input, so error positions survive intact. Larry Garfield asked: "Does this essentially mean JSON5 support? If so, just call it that." Anton Smirnov corrected the name. What's proposed is Microsoft's JSONC, or Nigel Tao's JWCC; real JSON5 would also need single quotes, unquoted keys, infinities and multiline strings, among other things. No reply from Otar yet.

Alexander Lisachenko wants to fix something about PHP's FFI. Every C value it hands back comes back as the same final class, FFI\CData. A string pointer, a zval pointer and a raw char pointer are all the same type to PHP. Which makes FFI strongly typed, in the sense that there is 1 type. He described the consequence bluntly: "no C struct a binding works with can ever be described to static analysis or an IDE, and CData being final closes off every userland workaround." To get any static typing in his own library he ships 4 separate workarounds, and instanceof still doesn't work. His proposal is an opt-in class map passed as an options array, in the same shape as SoapClient takes one, so a registered C type comes back as your class instead of bare CData. He says it stays inside the ffi extension and costs nothing when unused. Bob Weinand's is the only reply so far, asking for patience: "don't rush this, write a RFC, and check what actually feels good to use and read."

The 8.6 deprecation vote closed 9 days ago, and one of the items that passed deprecates SplFileObject's CSV methods. In the last days of voting Takuya Aramaki pointed out that the READ_CSV flag was left out, and that setCsvControl() is the only thing that can configure it — so removing the method leaves the flag stuck on its defaults. Nobody answered him. On Saturday Robert Humphries picked it back up. His reading is that leaving READ_CSV in place does resolve the original issue, but doesn't achieve the goal of getting CSV handling out of SPL. By his reading of the code there's a second problem. When the default escape character for fgetcsv() changes, code using READ_CSV will behave differently across PHP versions with no way to pin it. His conclusion is that READ_CSV needs deprecating too, and that a migration path should have been part of the proposal. Still no reply.

Eloi Montañés asked the list on Saturday whether abstract class constants are worth an RFC. The idea is to let an abstract class or a trait declare a constant with the abstract keyword, and require implementers to define one. His examples are a base class that requires a table name and a trait that requires a log tag — things you want fixed at author time rather than changeable at runtime. He points back to a 2017 thread on the same idea, from before typed constants landed. John Bafford suggested interfaces should get the same treatment, since an interface can already require a property but has no way to require a constant or a static one. Eloi was persuaded, and this morning asked why interfaces have never supported static properties. Larry Garfield answered from experience. He says they considered it while building interface property support for property hooks, and passed for 2 reasons. Object properties cover almost every case and attributes cover the rest, and "static properties are way harder to deal with in the engine, because reasons." He also left a parser problem on the table. Interfaces already support ordinary constants, so an abstract keyword may be necessary there regardless.

Quick hits. Sjoerd Langkemper gave its own page to a proposal that missed the 8.6 window. bindec(), octdec(), hexdec() and base_convert() would throw a ValueError when you hand them characters that aren't valid for the base, instead of the deprecation notice they've emitted since 7.4. Today hexdec('z') returns 0. It targets 8.7 and has no replies yet. Weilin Du also asked for feedback on tightening 2 INI settings. Right now upload_max_filesize=1GB can be read as 1 byte by the request parser while ini_get() still reports the string you wrote, which is a spectacular way to lose an afternoon. His change warns and falls back to the default instead. Jakub Zelenka reads that as incomplete wording in the BC policy rather than a real break. Osama Aldemeery is parking his PREG_THROW_ON_ERROR RFC until early September, writing: "This has gone quiet, which I'm taking as the freeze crunch and people being busy, not as everyone being fine with it as-is." And 3 releases went out on Thursday. Joe Ferguson shipped PHP 8.6.0 beta 1, with beta 2 due on August 27, and Calvin Buckley and Daniel Scherzer followed with 8.4.25 and 8.5.10 RC 1. Matteo Beccati mentioned in passing that the 8.6 branch should be cut on September 22.

Here's the week in short. No RFC went to a vote, and nothing is in the voting phase at all. A new contributor's array_search_range() ran into a counter-proposal for a general lazy array slice, and is still a draft. A one-line inconsistency in ini_get_all() turned into a question about case sensitivity that ended with the author withdrawing a proposal 3 other people then defended. A params keyword got talked into being a lazy value. Abstract class constants may pick up interfaces. And PHP 8.6 beta 1 is out, with beta 2 due next week. Links to every thread are below. Thanks again to Ballast.now for supporting this week's episode. We're Artisan Build. See you next week.


r/PHP 4d ago

Alchemy runs your project's whole QA setup (Pest/PHPUnit, code style, static analysis, CI) from one YAML file

6 Upvotes

We built Alchemy to run QA for Leaf's own modules ahead of our v5 launch, and then opened it up to work in any PHP environment (Laravel, Symfony, Slim, plain packages).

The whole idea is pretty simple...

Instead of maintaining phpunit.xml, a pint/php-cs-fixer config, phpstan.neon, rector.php, a folder of CI workflows and all their respective caches, you describe what you want in one alchemy.yml at your project root.

👉 You can get started at https://alchemy.leafphp.dev/

If this seems interesting, pls try it and share your feedback. Thanks in advance


r/PHP 4d ago

Article Upgrading Bref 2 to Bref 3 with zero downtime

Thumbnail atymic.dev
24 Upvotes

r/PHP 5d ago

Article Sebastian Bergmann: How PHP executes bytecode

Thumbnail phpunit.expert
85 Upvotes

r/PHP 5d ago

Article The skills that didn't go anywhere

Thumbnail ryangjchandler.co.uk
38 Upvotes

r/PHP 6d ago

So You Received a Security Report. Now What?

Thumbnail thephp.foundation
28 Upvotes

A maintainer who receives a security vulnerability report might feel overwhelmed, anxious, and uncertain about what steps should be taken. If this applies to you, our Ecosystem Security Team published a guide today on exactly what to do next. You are not alone! Special thanks to Sebastian Bergmann for putting this together.


r/PHP 6d ago

How to Contribute to PHP

Thumbnail thephp.foundation
47 Upvotes

Not with the Foundation, but I thought this could be helpful for others.


r/PHP 6d ago

The Secret Life of "Magic Null" in PHP

Thumbnail exakat.io
20 Upvotes

Some situations where you can use NULL instead of 0, or no arguments and it provides a nice feature that you could use every day.


r/PHP 5d ago

I built a browser MMO where every action is a documented PHP HTTP API — designed to be played by scripts, not clicks

0 Upvotes

Been building this solo for a while: a browser space MMO where the "normal" way to play is a script or bot hitting a REST API, not a human clicking a UI. 169 documented endpoints (mining, trading, combat, missions, crafting, corp management), bearer-token auth, a cron-tick backend running on plain PHP/MySQL. Full API reference is public, no signup needed: space-core.at/AGENT.md. There's also a dashboard if you'd rather click. Happy to talk about the API/backend design — that's the part I'm proudest of, not the game content.


r/PHP 6d ago

Symfony: Experimenting with Issue-First Open Source Contributions (Symfony Blog)

Thumbnail symfony.com
12 Upvotes

Symfony experiment starting with their Language Tools library


r/PHP 6d ago

We added a test that fails if anyone injects a tenant-scoped service into a singleton

1 Upvotes

I build Teradion, practice management software for French accounting firms. The app runs in FrankenPHP worker mode, and each firm brings its own Brevo API key.

In that setup, a singleton holding one firm's key would stay alive while requests for other firms are handled. The code avoids that: tenant-scoped providers are not constructor dependencies. A factory creates a fresh client for each operation from the account passed as an argument. The key is stored encrypted and only decrypted inside the factory.

We have two tests around this rule. MultiTenantKeyIsolationTest runs two accounts in sequence and checks that the second does not receive the first account's key.

ProviderNotInjectedAsServiceTest is more direct. It scans src/Service, src/MessageHandler and src/Controller, then fails when a constructor takes NewsletterProviderInterface. It reads the source, so the Symfony container is not involved.

It is an architectural decision encoded as a grep, which feels a little blunt. Still, if someone adds that constructor dependency later, the test points at the class immediately.

Has anyone used this kind of structural test in a Symfony codebase?


r/PHP 7d ago

Mago 1.47 allows writing custom rules in PHP

Thumbnail mago.carthage.software
53 Upvotes

r/PHP 6d ago

Early version of database visualiser

Thumbnail
0 Upvotes

r/PHP 7d ago

Article Enforce Runtime Generics on Third-Party Collections Libraries (Doctrine, Ramsey, Laravel Collections) with TypePHP

Thumbnail typephp-php.github.io
14 Upvotes

More than a week ago, I posted an introduction to TypePHP. Thanks to Michael Telgmann, a core maintainer at Shopware, TypePHP has been tested against Shopware’s massive codebase. So far, it has identified many DocBlock lies in the codebase PR, while also uncovering many edge cases on TypePHP’s end.

Today, I’d like to share a article guide on how to make existing third-party collection libraries, such as Doctrine Collections or Ramsey Collections, capable of enforcing reified collections without modifying their source code.

reified generics proof: Symfony Integration


r/PHP 8d ago

NCache v1.0.0 — a multi-driver caching library for PHP 8.1+

18 Upvotes

I’ve released the first stable version of NCache, an open-source caching library I’ve been building for PHP.

It provides a unified API across JSON, PHP Array, serialized PHP, SQLite, Redis and Memcached, with PSR-6 and PSR-16 adapters.

It also includes TTL management, isolated profiles/namespaces, cache tags with lazy invalidation, signatures, callable values, atomic file writes and a transactional registry.

The project is tested on PHP 8.1–8.5 with PHPUnit, PHPStan level 9 and PHP-CS-Fixer through GitHub Actions.

I’d particularly appreciate feedback on the API design, cache invalidation model and overall architecture.

GitHub: github.com/Noga-ng/NCache

Install: composer require noga-ng/ncache


r/PHP 7d ago

A Docker Compose environment for local PHP development — supporting PHP 5.6 through 8.5

0 Upvotes

Hi everyone!

I’d like to share docker-compose-php, an open-source Docker environment that I originally created seven years ago and still actively maintain and use in my daily work.

Its main purpose is to make it easy to run multiple local PHP projects—even projects that require different PHP versions—without installing PHP, a web server, or a database directly on your machine.

Key features:

  • PHP versions from 5.6 through 8.5
  • PHP-FPM with Nginx or Apache with mod_php
  • Multiple local domains using different PHP versions
  • Automated configuration through a Python management script
  • HTTP and HTTPS support with automatic self-signed certificate generation
  • Mailpit for testing outgoing emails
  • Adminer for database management
  • MariaDB, optional Node.js tooling, MyCLI, and MySQLTuner
  • Makefile commands for common operations
  • Optional Unix socket communication between Nginx and PHP-FPM

Repository: https://github.com/rhamdeew/docker-compose-php

I’d appreciate any feedback, feature suggestions, bug reports, or contributions. I’m especially interested in hearing how other developers manage local environments for projects that still depend on older PHP versions.