Here is a bug in a name-parsing library I use at work: // theiconic/name-parser $name = $parser->parse('Jane Doe DDS'); $name->getLastname(); // "Dds" $name->getMiddlename(); // "Doe" The dental credential is now her last name. The real surname got shoved into the middle-name field. Every row with a trailing credential and no comma had some version of this, and in a list of clinicians that is most of them. The library is theiconic/name-parser, a small, genuinely useful PHP package that splits a full-name string into salutation, first name, initials, last name, suffix, and nickname. I use it at work. It does the boring parts well. But the upstream repo went quiet around 2020, and bugs like the one above never got fixed. So I forked it. Today I'm releasing iliaal/nameparser, a maintained fork that fixes the credential handling, adds a confidence signal for the cases it genuinely can't decide, and targets PHP 8.3+. Most of the fix is unglamorous boundary work. One part of it rests on a single ide...

Update, June 21 2026. This post went up at 0.2.1. Since then 0.3.0 and 0.4.0 have shipped, and one claim below is already out of date: result streaming, which I describe as the next thing on the list, now exists. Set PDO::DUCKDB_ATTR_UNBUFFERED and a large SELECT streams row by row instead of buffering. Also new since publication: DuckDB config options on the DSN or through PDO::DUCKDB_ATTR_CONFIG, real per-column types from getColumnMeta(), an appender that accepts PHP arrays for nested columns like LIST, STRUCT, and MAP, GEOMETRY decoding, and duckdbTableNames() / duckdbLastProfile() for query introspection. The walkthrough below is otherwise current. Full list in the changelog. DuckDB is the closest thing the analytics world has to SQLite. It runs in-process, needs no server, reads and writes a single file, and chews through columnar aggregate queries that would make a row-store sweat. PHP has shipped PDO_SQLite in core for twenty years. Until now it had no equivalent for Du...

I generate a lot of UUIDs. Primary keys, cache keys, event IDs, request-trace IDs. Probably too many, if I'm honest about it. On a busy request path the same function gets called dozens of times before the response is even assembled, and across a fleet that adds up to a number of UUIDs per second I would rather not write down. For years that cost was invisible to me, the way a single random_bytes() call is invisible until you make a few billion of them. Then it showed up in a profile, sitting higher than it had any right to, and I started paying attention to where the time actually went. It went to two places: pulling fresh entropy from the kernel once per UUID, and formatting 16 raw bytes into the 36-character canonical string. Both are cheap. Neither is free. Multiply by "too many" and you get a real slice of CPU spent doing nothing but minting identifiers. So I wrote fast_uuid, a PHP extension that does UUID generation in pure C. This post is about why the two existing options each left a gap, what...

I've reached for igbinary on nearly every PHP project I've shipped in the last decade. It's smaller and faster than PHP's native serialize(), it's stable, and it has been the obvious default for so long that reaching for it stopped being a decision. So phpser started as curiosity, not a complaint. igbinary is good. Could a serializer built specifically for cache workloads do better? I wanted two things from it. It should be fast on the shapes a cache actually holds, where a value is decoded far more often than it's encoded. And it should be safe to decode bytes from a store an attacker might reach, because unserialize() on untrusted input is one of PHP's oldest exploit primitives. igbinary gives you the speed; the safety you bolt on yourself. phpser builds in both. On the shapes that matter for caches it encodes 10 to 70% faster than igbinary and decodes 12 to 75% faster, with packed numeric data also 65% smaller on the wire. Its signed mode refuses to decode any payload that wasn't produced with yo...

Couple of weeks ago I shipped fastchart 0.2.0 and wrote it up here. One extension, 19 chart types, server-side rendering through ext/gd. The idea was right, but execution not quite there. After the launch I spent a few days actually looking at the output side by side with what plutovg can do on the same primitives. The libgd-rendered charts were fine for what libgd is, which is a 1990s 2D rasterizer with no subpixel-precise anti-aliasing. Diagonal lines were jaggy. Glyph edges grainy at small sizes. The output read as "a chart drawn by ext/gd in 2026" instead of "a chart." A couple of Reddit threads (r/PHP and r/laravel) pointed at the same thing without me having to ask. So I rewrote it. fastchart 1.1.1 is the current stable of that rewrite, following a number of stabilization tweaks and refinements, the end result being SVG promoted to the canonical render format, and the chart-family count up from 19 to 26. What was wrong with the libgd output libgd's anti-aliasing is gdAntiAliased plus the...

  • «
  • 1