PHP Reddit – Telegram
PHP Reddit
34 subscribers
294 photos
39 videos
25K links
Channel to sync with /r/PHP /r/Laravel /r/Symfony. Powered by awesome @r_channels and @reddit2telegram
Download Telegram
Is refactoring bool to enum actually makes code less readable?

Is refactoring bool to enum actually makes code less readable?

I'm stuck on a refactoring decision that seems to go against all the "clean code" advice, and I need a sanity check.

I have methods like this:

private function foo(bool $promoted = true): self {
// ...
}


Everyone, including me, says "use enums instead of booleans!" So I refactored to:

enum Promoted: int {
case YES = 1;
case NO = 0;
}

private function foo(Promoted $promoted = Promoted::NO): self {
// ...
}


But look at what happened:

- The word "promoted" now appears three times in the signature
- Promoted::YES and Promoted::NO are just... booleans with extra steps?
- The type, parameter name, and enum cases all say the same thing
- It went from foo(true) to foo(Promoted::NO) - is that really clearer?

The irony is that the enum was supposed to improve readability, but now I'm reading "promoted promoted promoted" and my eyes are glazing over. The cases YES/NO feel like we've just reinvented true/false with more typing.

My question: Is this just a sign that a boolean should stay a boolean? Are there cases where the two-state nature of something means an enum is actually fighting against the language instead of improving it?

Or am I missing a better way to structure this that doesn't feel like stuttering?

How would you all handle this?


https://redd.it/1qjxp9t
@r_php
Livewire 4 and Flux the best way to build web projects. It offers an excellent development experience, and the page rendering speed is incredibly fast.

Hello everyone, I was the one complaining that Flux was too slow. I don't know what Caleb did but Livewire 4 and Flux are great. This was my old post;

https://www.reddit.com/r/laravel/comments/1lg6ljv/is\_flux\_too\_slow\_or\_am\_i\_missing\_something/

I wrote Flux dropdown rendering speed is 1.7 seconds. I built a whole page with flux used many components and page speed is 94 ms. This is unbelievable. I swear everyone can build a saas project using Livewire and Flux in one day without using AI tools.



https://redd.it/1qk51s8
@r_php
Laravel API or Not

I am realizing you can still go the decoupled way (API) and avoid frontend frameworks.

I thought once you go decoupled you also have to pick a frontend framework.

But it seems that’s not the case at all. You can still go the API way and still keep Blade.

https://redd.it/1qk8ffo
@r_php
Forcibly run Garbage Collector after closing connection?

1. With PHP I've got a lot of expired session files just sitting on my servers that should have been deleted when the session expired.
2. PHP assigns deleting the session files when it runs GC (garbage collection).
3. PHP doesn't run GC very often or, apparently, ever.
4. Running GC uses resources.

Okay, with the basics out of the way let's do this the smart way. I don't want to hurt the server's response time to client requests. So let's force GC to execute after the connection to the client has closed:

<?php
//This should be after your </html> closing tag for the html element:
$c = ob_get_contents();

header('Content-Length: '.ob_get_length());
header('Connection: close');

ob_end_clean();
ob_start('ob_gzhandler');

echo $c;

//Close session or it will create conflicts:
session_write_close();

ob_end_flush();
ob_flush();
flush();

//Connection closed; continue processing:

// *** How do we force GC to run here? ***
// *** How do we force GC to run here? ***
// *** How do we force GC to run here? ***

?>

You can put a sleep(5); near the bottom and do something like put some dummy text in a flat file to verify that PHP is still executing. This also makes sure that the request uses GZIP compression.

Now I've already tried testing setting the INI settings:

<?php
ini_set('session.gc_probability',1);
ini_set('session.gc_divisor',1);
?>

However PHP complains since headers were already sent. Well, the point is to do this after we close the connection to the client! The probability issue is that when it does run (0.1% of the time apparently) it's resource intensive and is triggered when a session is started which is never going to be after closing the connection to the client! How wonderfullly backwards. 🙄

So how do we manually trigger garbage collection at the bottom of the primary noscript? I'm using PHP 8.2 and higher.

Also yes, I am aware we can manually destroy session files though the goal is to get PHP to do it's job! Thanks in advance for competent replies.

https://redd.it/1qkicao
@r_php
Hi PHP developer need your advice

Hi everyone,

I’m working on a small project using a vibe-coding, and part of it is already built in PHP. I’m now at a crossroads and could use some advice.

1. Should I continue using PHP and integrate new features into the existing code, or would it be better to start fresh and rebuild the entire project using MERN? If MERN is the better choice, why?
2. What is the best database to use with PHP for a small to medium project?
3. What kind of complications or limitations should I expect if I stick with PHP?

The project will use in in real life so please give answer accordingly
Any insights or real-world experiences would be appreciated. Thanks!

https://redd.it/1qkjc8t
@r_php
I built a package to stop hardcoding Stripe price IDs everywhere

I've been working with Stripe quite a bit recently and was wondering if there could be something better than having Stripe price and product IDs hard-coded in env files, trying to match resources between sandboxes and production, and having our checkout crash if we forgot to add some values somewhere.

I've built this little package and it's been quite useful on some freelancing gigs, and I wanted to release it here to gather some feedback, in order to make it as useful as possible.

The idea is to define your products and prices in a config file, deploy them to Stripe with a single command, and then access them with type-safe keys, like so:

// config/billing.php
'products' => [
'pro' => [
'name' => 'Pro Plan',
'prices' => [
'monthly' => [
'amount' => 2999,
'currency' => 'usd',
'recurring' => ['interval' => 'month'],
],
],
],
],

This creates/updates everything in Stripe, caches it locally in your DB, and auto-generates enums for your IDE, and provides you with a facade to access all your resources easily.

// Before

`$user->checkout('price_1ABC123xyz789');`

// After

`$user->checkout(BillingRepository::priceId(ProductKey::Pro, PriceKey::Monthly));`

What it gives you:

* Version control for billing - Your pricing structure lives in git, not just in the Stripe dashboard
* No API calls at runtime - IDs are cached in your DB
* Auto-generated enums - IDE autocomplete, catch typos at dev time
* Two-way sync - Deploy config → Stripe, or import existing Stripe setup → config
* Handles Stripe's immutable fields - When you change a price amount, it detects this and lets you archive the old price or create a duplicate

**Importing existing setup:**

If you already have products in Stripe, you can pull them into a config file:

`php artisan billing:import --generate-config`

It's essentially infrastructure-as-code for your billing setup.

I've released it as 0.9.0 as I haven't implemented it yet in a large production codebase, so use at your own risk.

\---

GitHub: [https://github.com/valentin-morice/laravel-billing-repository](https://github.com/valentin-morice/laravel-billing-repository)

Packagist: [https://packagist.org/packages/valentin-morice/laravel-billing-repository](https://packagist.org/packages/valentin-morice/laravel-billing-repository)

\---

https://redd.it/1qklho3
@r_php
Life Timeline: Real-time multiplayer app built with Swoole + Mezzio

Demo: [https://timeline.zweiundeins.gmbh](https://timeline.zweiundeins.gmbh)
Github: [https://github.com/mbolli/php-timeline](https://github.com/mbolli/php-timeline)

I just put my Life Timeline app in production. It's a horizontal timeline app (think Google Sheets timeline view meets Adobe Premiere's track layout) with real-time multiplayer.

I was interested in Swoole's performance but found most examples are either single-file noscripts or custom frameworks. I wanted to see if you could build a "proper" PHP application (PSR-15 middleware, dependency injection, structured architecture) while still benefiting from Swoole's persistent workers. Spoiler: you can, and Mezzio makes it pretty seamless.

**The real-time architecture:** The multiplayer sync uses a pattern I really like:

* **CQRS (Command Query Responsibility Segregation):** Write operations go through Command Handlers, reads through Query Handlers. Each command handler does its thing (update database) and then emits an event.
* **Event Bus:** When a command completes, it fires a `TimelineChangedEvent` to a Swoole-based event bus. This is just a simple pub/sub: The bus holds subscriber callbacks in memory (works because Swoole workers are persistent).
* **SSE (Server-Sent Events):** When clients connect to `/updates`, they subscribe to the event bus. The connection stays open (Swoole coroutines handle this efficiently). When any client makes a change, the event fires, all subscribers get notified, and we push a re-rendered HTML fragment to each client using [Datastar](https://data-star.dev/)'s `PatchElements` format.

The nice thing is there's no WebSocket complexity, no separate pub/sub server (Redis, etc.) — it's all in-process because Swoole workers persist. Obviously this only works for single-server deployments, but for many apps that's fine (or just replace the event bus with NATS).

Feedback welcome. Have you already used this pattern?

https://redd.it/1qklpup
@r_php
I built my own server dashboard using a Laravel health package API
https://redd.it/1qkskxo
@r_php
Is this naming convention any good? Asking for a friend...
https://redd.it/1qkvfg9
@r_php
A new simple library for reading EXIF data

I'm building an application that allows users to upload photos to it. I needed access to the EXIF data if available, so I assumed I could just use exif_read_data() and save the results as a JSON blob in the database.

Not so simple. I assumed EXIF data was just basic ASCII text, but I assumed wrong. Some values are byte arrays or enums that are encoded with NUL bytes and attempting to serialized them as JSON to be stored in at UTF-8 column failed.

Additionally, I didn't realize that coordinates weren't stored as floating point latitude, longitude pairs that we're familiar with. The EXIF standard doesn't support floating point numbers, so they're encoded as a list of strings that represent the degrees, minutes, and seconds as a fraction (and cardinal direction as a string).

Packagist showed a few existing EXIF libraries, but they looked like overkill for what I needed. So, like every PHP developer, I wrote yet another package named exif-tools.

It's dependency free (aside from the bcmath, ctype, and exif extensions) and handles a lot of headaches I ran into.

Check it out, I'd love to hear your feedback: https://github.com/1tomany/exif-tools

https://redd.it/1qkxgc8
@r_php
Replacement for Encryption-Bundle

In my old Symfony 5 projects, I used the michaeldegroot/doctrine-encrypt bundle to store encrypted data in the database. The bundle worked well and transparently. Now, the project needs to be updated to a current Symfony version, but the encryption bundle no longer works because it only supports ORM2.

Which encryption bundle is currently state-of-the-art for Symfony 7.4/8 and runs as smoothly as the encryption bundle?

https://redd.it/1qkvxjz
@r_php
Sharing our PHP libraries

Hey r/PHP,
We have been building and using our own PHP libraries internally for many years across various projects. Figured they might be useful to others.

We're calling them the "Perfect" collection (mainly because our main internal project was called PerfectApp). They're modern, and fully tested with 100% coverage.

After writing our own framework inspired by Laravel for in-house use we went the way of Symfony and made standalone library's that can be used in any modern project. Most of them were developed by real Engineers before the AI boom.

All public releases: https://packagist.org/packages/krubio/

https://redd.it/1qlc71s
@r_php
What's your opinion about routes that start with /index.php?

I've noticed that, when using the ServerSideUP fpm-nginx image with a Laravel project, adding /index.php before the path causes the page to render.

These Docker images are used by Laravel Cloud, so all projects hosted there work the same.

For example, for the Laravel docs page, these routes render the same content:

[https://laravel.com/docs/12.x](https://laravel.com/docs/12.x)
https://laravel.com/index.php/docs/12.x

The same occurs for the Laravel News blog:

[https://laravel-news.com/speeding-up-laravel-news-with-cloudflare](https://laravel-news.com/speeding-up-laravel-news-with-cloudflare)
https://laravel-news.com/index.php/speeding-up-laravel-news-with-cloudflare

I don't know if that's expected, but I personally would expect to remove the /index.php part or even return a 404 Not Found error if the path starts with /index.php because that route doesn't exist in the web.php file.

I’ve noticed this because Bing's index started indexing a bunch of URLs with the /index.php part.

https://redd.it/1qlth8e
@r_php