Reading List

The most recent articles from a list of feeds I subscribe to.

Don't skip `else` with octane

I came across a subtle Octane but last week. We needed to disable Inertia’s history encryption in some places in the app. By default, it’s enabled everywhere. So we added a route check to the middleware to turn it off.

class HandleInertiaRequests
{
    public function handle(Request $request, Closure $next)
    {
        if ($request->is('admin/*')) {
            Inertia::encryptHistory(false);
        }
        
        // …
    }
}

The problem is, if you’re running Octane and make a request to an admin/* route, history encryption will be disabled, and there’s nothing to re-enable it for the next request.

The fix is to make sure both sides of the statement are executed.

class HandleInertiaRequests
{
    public function handle(Request $request, Closure $next)
    {
        if ($request->is('admin/*')) {
            Inertia::encryptHistory(false);
        } else {
            Inertia::encryptHistory(true);
        }
        
        // …
    }
}

Or more succinct:

class HandleInertiaRequests
{
    public function handle(Request $request, Closure $next)
    {
        Inertia::encryptHistory(! $request->is('admin/*'));
 
        // …
    }
}

Zig's anti-LLM contribution policy

As shared by on Simon Willison’s blog, Zig has an interesting anti-LLM policy for contributions in their code of conduct.

Zig values contributors over their contributions. Each contributor represents an investment by the Zig core team - the primary goal of reviewing and accepting PRs isn’t to land new code, it’s to help grow new contributors who can become trusted and prolific over time.

I don’t think an anti-LLM policy makes sense for most projects. But a programming language requires considerate intent and deep knowledge for changes. It’s an interesting fit there.

In addition:

If a PR was mostly written by an LLM, why should a project maintainer spend time reviewing and discussing that PR as opposed to firing up their own LLM to solve the same problem?

We’ve historically preferred PR contributions over issues, because it puts the contributor in the position to do most of the work. But if a PR is just a contributor prompting an LLM, is a well-written issue preferable? When writing code becomes cheaper, might as well let the maintainer get it done using their taste.

Time for lower level languages?

I’ve always been intrigued by Go. It’s powerful, fast (I really like fast), and simple. The tradeoff? It’s simple. Coming from higher level languages like PHP & JavaScript, Go can feel crude.

As I’ve recently written, this blog went back to Hugo. Hugo is also fast and crude. But with LLMs, the crudeness of things doesn’t hurt as much as before. I don’t need to deal with writing it anymore, and crude is still readable.

From Just Fucking Use Go:

The boring choice is the right choice. It always was.

I agree. More than ever, I have an urge to dabble into lower level languages. AI is a huge layer of complexity we’re adding to our tooling. Let’s use it to trim the fat from our outputs.

Sanding UI

This is an older post from Jim Nielsen on building user interfaces I came back to last week.

With software, the fact is that sometimes there are just too many variables to know and test and smooth out. So I click around, using the UI over and over, until I finally cannot give myself any more splinters.

I feel this. I’m better at my job when I’m actually using something. Even better when I’m using something because I want to use it.

I’ve been building a side project on and off for a few months now. Having it my phone’s homescreen and actually using it every day gives me a different perspective on it than just building it and shipping it to others, like is often the case for client work.

Sand it, feel the grain, get a splinter, sand again, and repeat until smooth.

Introducing Piper: a pipe operator-first PHP utility library

When I experimented with Elixir a few years ago, I fell in love with the pipe operator |>. Since then, I’ve always dreamt of a similar tool in PHP.

Last year, we finally got it! Unfortunately, the standard array & string manipulation functions in PHP aren’t exactly known for their API consistency, which makes the pipe operator awkward to use.

I ported Laravel’s excellent collection & string helpers to a pipe operator-optimized API. Piper is an attempt to wrap the standard library to make it compatible with the pipe operator.

use function Spatie\Piper\Arr\{filter, join, map};
use function Spatie\Piper\Str\{prefix, suffix};

[1, 2, 3, 4, 5, 6]
    |> filter(fn (int $i) => $i % 2 === 0)
    |> map(fn (int $i) => pow($i, 2))
    |> join(', ', ', and ')
    |> prefix('The winning numbers are ')
    |> suffix('.');

// "The winning numbers are 4, 16, and 36."

I wrote a technical introduction to the package on the Spatie blog. Documentation can be referenced here, and the repository is hosted on GitHub.

The sad part (maybe?)

I’ve never seen a coding agent return code using a pipe operator unless I’ve explicitly asked it to. That makes sense: the models we use are trained on years of historical data, and the pipe operator is a fairly new feature.

I might never use this library. I might never use the pipe operator at all. Agentic coding is pushing syntax to a standstill. New programming APIs that bring benefits to execution will be pushed forward. But the whole fight for making code look good seems to have been extinguished as AI is slowly moving us to focus on outcomes more than line-by-line code cleanliness. That’s not necessarily a bad thing, but part of our craft might get lost along the way.

Ironically, I convinced myself to actually write this because I have AI at my disposal. Manually porting 234 functions and a full test suite is not something I was looking forward to. Instead, the time spent building and refining this package is measurable in hours.

Either way, this is a fun experiment to conduct. And I look forward to tinkering further and giving it a shot in some real projects.