PHP Reddit
31 subscribers
308 photos
40 videos
25.3K links
Channel to sync with /r/PHP /r/Laravel /r/Symfony. Powered by awesome @r_channels and @reddit2telegram
Download Telegram
How to set up automatic SSL for every site in a multi-site CMS —
wildcard subdomains + custom domains, zero manual cert management
/r/cms/comments/1sgubts/how_to_set_up_automatic_ssl_for_every_site_in_a/

https://redd.it/1sgudgg
@r_php
Flow PHP PostgreSql Symfony Bundle

Working with PHP, PostgreSql and Symfony?

You might want to check Flow PHP Symfony PostgreSql Bundle - it's the latest package I have been working on as a part of Flow PHP project.

https://flow-php.com/documentation/components/bridges/symfony-postgresql-bundle/

Features:

\- query builder with full PostgreSql syntax support

\- migrations

\- schema definition in php/yaml

\- SQL AST Parser/Deparser

\- client that supports static analysis types narrowing, no more return array<mixed>

https://redd.it/1sfmlha
@r_php
Array intersection benchmarks

I’m trying to optimize my hot code path where array intersection is used a lot. I got curious and decided to compare the various intersection algorithms that I know of.

<?php

// Source - https://stackoverflow.com/a/9276284
// Posted by kingmaple, modified by community. See post 'Timeline' for change history
// Retrieved 2026-04-08, License - CC BY-SA 4.0

// Source - https://stackoverflow.com/a/53203232
// Posted by slaszu, modified by community. See post 'Timeline' for change history
// Retrieved 2026-04-08, License - CC BY-SA 4.0

iniset('memorylimit', '2048M');

function formatBytes(int $bytes): string {
$units = 'B', 'KB', 'MB', 'GB';
$i = 0;
while ($bytes >= 1024 && $i < count($units) - 1) {
$bytes /= 1024;
$i++;
}
return sprintf("%.2f %s", $bytes, $units$i);
}

function benchmark(callable $fn, string $label): array {
gccollectcycles();
gcmemcaches();
memoryresetpeakusage();
$mem = -memory
getpeakusage();
$time = -hrtime(true);
$fn();
$time += hrtime(true);
$mem += memorygetpeakusage();
return [
'label' => $label,
'time
ms' => $time / 1e6,
'memused' => $mem,
];
}

function manual
intersect($arrayOne, $arrayTwo) {
$index = arrayflip($arrayOne);
foreach ($arrayTwo as $value) {
if (isset($index[$value])) {
unset($index[$value]);
}
}
foreach ($index as $value => $key) {
unset($arrayOne[$key]);
}
return $arrayOne;
}

function flipped
intersect($arrayOne, $arrayTwo) {
$index = arrayflip($arrayOne);
$second = array
flip($arrayTwo);
$x = arrayintersectkey($index, $second);
return arrayflip($x);
}


function runBenchmarks(int $n): void {
echo "\n=== Array Intersection Benchmark for " . number
format($n) . " elements ===\n";

// Generate test arrays
$one = ;
$two = ;
for ($i = 0; $i < $n; $i++) {
$one = rand(0, 1000000);
$two = rand(0, 100000);
$two = rand(0, 10000);
}

$one = arrayunique($one);
$two = array
unique($two);

$results = ;

$results = benchmark(
fn() => $res = manualintersect($one, $two),
'manual
intersect()'
);

$results = benchmark(
fn() => $res = arrayintersect($one, $two),
'array
intersect()'
);

$results = benchmark(
fn() => $res = flippedintersect($one, $two),
'flipped
intersect()'
);

// --- Print Table ---
echo strrepeat('-', 60) . "\n";
printf("%-25s | %-14s | %-15s\n", 'Method', 'Time (ms)', 'Memory');
echo str
repeat('-', 60) . "\n";

foreach ($results as $r) {
printf("%-25s | %11.3f ms | %15s\n",
$r'label',
$r'time_ms',
formatBytes($r'mem_used')
);
}
echo strrepeat('-', 60) . "\n";
}

// Run for various sizes
foreach ([20, 20000, 200000, 1000000] as $n) {
runBenchmarks($n);
}

I run this on PHP 8.4 on Core I7 11700F

=== Array Intersection Benchmark for 20 elements ===
------------------------------------------------------------
Method | Time (ms) | Memory
------------------------------------------------------------
manual
intersect() | 0.007 ms | 1.98 KB
arrayintersect() | 0.029 ms | 3.02 KB
flipped
intersect() | 0.002 ms | 3.97 KB
------------------------------------------------------------

=== Array Intersection Benchmark for 20,000 elements ===
------------------------------------------------------------
Method | Time (ms) | Memory
------------------------------------------------------------
manualintersect() | 1.169 ms | 1.75 MB
array
intersect() | 41.300 ms | 1.88 MB
Array intersection benchmarks

I’m trying to optimize my hot code path where array intersection is used a lot. I got curious and decided to compare the various intersection algorithms that I know of.

<?php

// Source - https://stackoverflow.com/a/9276284
// Posted by kingmaple, modified by community. See post 'Timeline' for change history
// Retrieved 2026-04-08, License - CC BY-SA 4.0

// Source - https://stackoverflow.com/a/53203232
// Posted by slaszu, modified by community. See post 'Timeline' for change history
// Retrieved 2026-04-08, License - CC BY-SA 4.0

ini_set('memory_limit', '2048M');

function formatBytes(int $bytes): string {
$units = ['B', 'KB', 'MB', 'GB'];
$i = 0;
while ($bytes >= 1024 && $i < count($units) - 1) {
$bytes /= 1024;
$i++;
}
return sprintf("%.2f %s", $bytes, $units[$i]);
}

function benchmark(callable $fn, string $label): array {
gc_collect_cycles();
gc_mem_caches();
memory_reset_peak_usage();
$mem = -memory_get_peak_usage();
$time = -hrtime(true);
$fn();
$time += hrtime(true);
$mem += memory_get_peak_usage();
return [
'label' => $label,
'time_ms' => $time / 1e6,
'mem_used' => $mem,
];
}

function manual_intersect($arrayOne, $arrayTwo) {
$index = array_flip($arrayOne);
foreach ($arrayTwo as $value) {
if (isset($index[$value])) {
unset($index[$value]);
}
}
foreach ($index as $value => $key) {
unset($arrayOne[$key]);
}
return $arrayOne;
}

function flipped_intersect($arrayOne, $arrayTwo) {
$index = array_flip($arrayOne);
$second = array_flip($arrayTwo);
$x = array_intersect_key($index, $second);
return array_flip($x);
}


function runBenchmarks(int $n): void {
echo "\n=== Array Intersection Benchmark for " . number_format($n) . " elements ===\n";

// Generate test arrays
$one = [];
$two = [];
for ($i = 0; $i < $n; $i++) {
$one[] = rand(0, 1000000);
$two[] = rand(0, 100000);
$two[] = rand(0, 10000);
}

$one = array_unique($one);
$two = array_unique($two);

$results = [];

$results[] = benchmark(
fn() => $res = manual_intersect($one, $two),
'manual_intersect()'
);

$results[] = benchmark(
fn() => $res = array_intersect($one, $two),
'array_intersect()'
);

$results[] = benchmark(
fn() => $res = flipped_intersect($one, $two),
'flipped_intersect()'
);

// --- Print Table ---
echo str_repeat('-', 60) . "\n";
printf("%-25s | %-14s | %-15s\n", 'Method', 'Time (ms)', 'Memory');
echo str_repeat('-', 60) . "\n";

foreach ($results as $r) {
printf("%-25s | %11.3f ms | %15s\n",
$r['label'],
$r['time_ms'],
formatBytes($r['mem_used'])
);
}
echo str_repeat('-', 60) . "\n";
}

// Run for various sizes
foreach ([20, 20000, 200000, 1000000] as $n) {
runBenchmarks($n);
}

I run this on PHP 8.4 on Core I7 11700F

=== Array Intersection Benchmark for 20 elements ===
------------------------------------------------------------
Method | Time (ms) | Memory
------------------------------------------------------------
manual_intersect() | 0.007 ms | 1.98 KB
array_intersect() | 0.029 ms | 3.02 KB
flipped_intersect() | 0.002 ms | 3.97 KB
------------------------------------------------------------

=== Array Intersection Benchmark for 20,000 elements ===
------------------------------------------------------------
Method | Time (ms) | Memory
------------------------------------------------------------
manual_intersect() | 1.169 ms | 1.75 MB
array_intersect() | 41.300 ms | 1.88 MB
flipped_intersect() | 0.634 ms | 2.55 MB
------------------------------------------------------------

=== Array Intersection Benchmark for 200,000 elements ===
------------------------------------------------------------
Method | Time (ms) | Memory
------------------------------------------------------------
manual_intersect() | 8.781 ms | 16.00 MB
array_intersect() | 290.759 ms | 16.00 MB
flipped_intersect() | 6.196 ms | 20.00 MB
------------------------------------------------------------

=== Array Intersection Benchmark for 1,000,000 elements ===
------------------------------------------------------------
Method | Time (ms) | Memory
------------------------------------------------------------
manual_intersect() | 35.547 ms | 58.00 MB
array_intersect() | 882.681 ms | 42.00 MB
flipped_intersect() | 26.764 ms | 58.00 MB
------------------------------------------------------------

The built-in functions mock me!

https://redd.it/1sh13gh
@r_php
I got tired of coding the same CRUDs and admin panels for years, so I open-sourced my own PHP framework (built on CodeIgniter 4)

Hey everyone.

If you build software for the educational or administrative sector, you know the drill: ever-changing requirements, massive databases, and the headache of rewriting the exact same logic for views, tables, pagination, and permissions for every new system.

It got to a point where my job felt like 80% repetitive boilerplate and 20% actual business logic.

To fix this and keep my sanity, I decided to build a higher-level layer leveraging the speed of CodeIgniter 4 and MariaDB. The core philosophy is simple: Configuration over Programming. I wanted to be able to define a "Data Dictionary" (a simple array) and have the system automatically render the dashboard, filters, data exports, and handle security (SQLi, XSS, RBAC) without touching a single manual view.

The result is Ragnos, a framework I use daily for production systems, which I've decided to release 100% Open Source for the community.

Also, because everything is based on configuration arrays, its declarative architecture is perfect for using AI (ChatGPT/Claude) to generate entire modules in seconds.

Where to check it out? You can find the project's philosophy, initial docs, and the direct link to the GitHub repository here: 🔗**ragnos.build**

For those who want to dive deep into the architecture or implement it at an enterprise level, I also just published the complete official manual (Ragnos from Zero to Pro) on Leanpub, but the heart of this launch is the free open-source tool.

I’d love for you to take a look at the code, install it, break it, and give me your feedback. If you find the tool useful, dropping a star on the GitHub repo helps tremendously with project visibility.

Thanks for reading and happy coding!

https://redd.it/1sh28gf
@r_php
This media is not supported in your browser
VIEW IN TELEGRAM
[Showcase] I got tired of building SaaS billing from scratch, so I made an open-source Laravel package with a Filament admin panel. Sets up in 15 mins.

https://redd.it/1shjxj5
@r_php
Tired of terminal hopping? I built a native GNOME extension to manage Symfony CLI servers 🐘🐧
https://redd.it/1shnh7v
@r_php
With PHP 8.4 Property Hooks, Should Booleans Be Properties or Methods?

PHP 8.4 property hooks let us put logic directly inside properties, and it's forcing me to revisit a convention I thought was settled: should boolean-returning values be properties or methods?

$user->isActive   // property?
$user->isActive() // method?


The old rule felt obvious properties hold state, methods hold logic. But now that properties can hold logic, I'm not sure that rule holds anymore.

What makes it worse is naming. isActive, hasPermission, canAccess all read like questions, and questions feel like they belong behind parentheses. Seeing $user->isActive without them genuinely bothers me and even if it works.

So which side are you on, and has PHP 8.4 changed anything for you?



https://redd.it/1shstdr
@r_php
What distroless image do you guys use for PHP?

There don't seem to be many, and they seem like small projects. Do you have any recommendations?

^(\(I use Podman btw\))

https://redd.it/1sif09j
@r_php
Lemmon Validator: A Zod-inspired, type-safe validation library for PHP 8.3

Hey everyone,

I’ve been working on **Lemmon Validator**, a schema-first validation library that brings the fluent API patterns of TypeScript libraries like **Zod** and **Valibot** to modern PHP.

It is designed for developers who want a predictable, type-safe way to validate and transform input data while maintaining zero external dependencies.

# The Core Idea

Most validation in PHP happens against "loose" arrays. Lemmon Validator focuses on building a schema that not only validates but also **coerces** and **transforms** the data into a reliable state (either as a typed array or an object).

# Key Features:

* **Zod-inspired Fluent API:** Highly readable, chainable schema definitions.
* **Form-Safe Coercion:** A common pain point in PHP is handling HTML form inputs where an empty string (`''`) should be treated as `null` rather than `0` or `false`. Lemmon Validator handles this natively when `coerce()` is enabled.
* **Transformation Pipelines:** Use `transform()` to change types (e.g., String to DateTime) or `pipe()` for sanitization (e.g., trim/lowercase).
* **Nested Error Aggregation:** Deeply nested schemas return a structured error map, making it easy to map errors back to UI fields.
* **Zero Dependencies:** Lean, focused, and easy to drop into any project.

# Quick Example:

use Lemmon\Validator\Validator;

$schema = Validator::isAssociative([
'name' => Validator::isString()->notEmpty()->required(),
'email' => Validator::isString()->email()->required(),
'age' => Validator::isInt()->min(18)->coerce(),
'roles' => Validator::isArray()
->items(Validator::isString()->in(['admin', 'user']))
->default(['user']),
]);

try {
// $_POST: ['name' => 'John', 'email' => 'invalid', 'age' => '25']
$data = $schema->validate($_POST);
// $data is now a validated, coerced, and typed array
} catch (ValidationException $e) {
$errors = $e->getFlattenedErrors();
// Returns: [['path' => 'email', 'message' => 'Value must be a valid email address'], ...]
}

# Why PHP 8.3?

The library leverages modern PHP features like readonly properties, enums, and strict typing to ensure the internal engine is as robust as the schemas you build with it.

I'm looking for feedback on the API ergonomics and any specific "edge case" format validators you find yourself constantly rewriting.

**Repo:** [https://github.com/lemmon/validator-php](https://github.com/lemmon/validator-php)

Happy to answer any questions!

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