TempestTempest

Tempest Alpha 2

It's been three weeks since we released the first alpha version of Tempest, and since then, many people have joined and contributed to the project. It's been great seeing so many people excited about Tempest, on Reddit, Twitter, Discord, and on GitHub.

Over the past three weeks, we made lots of bug fixes and added lots of new features as well! In this blog post, I want to show the most prominent highlights: what's new in Tempest alpha 2!

By the way, this blog is new, we'll use it for Tempest-related updates. You can subscribe via RSS if you want to!

composer require tempest/framework:1.0-alpha2

Authentication and Authorization

Being able to log in and protect routes is a pretty important feature of any framework. For alpha 2, we've laid the groundwork to build upon: Tempest handles user sessions, and checks their permissions with a clean API:

$authenticator->login($user);
final readonly class AdminController
{
    #[Get('/admin')]
    #[Allow(UserPermission::ADMIN)]
    public function admin(): Response
    { /* … */ }
}

What we haven't tackled yet, is user management — account registration, password resets, etc. We've deliberately left those features in the hand of framework users for now, since we're unsure how we want to handle these kinds of "higher level features".

The main question is: how opinionated should Tempest be? Should we provide all forms out of the box? How will we allow users to overwrite those? Which frontend stack(s) should we use? This is something we don't yet have an answer for, and would like to hear your feedback on as well.

New website

You can't miss it: the Tempest website has gotten a great new design. Thanks to Matt who put a lot of effort into making something that's much nicer than what I could come up with! I like how the website visualizes Tempest's vision: to be modern and clean, sometimes a little bit slanted: we dare to go against what people take for granted, and we dare to rethink and venture into uncharted waters.

Thanks, Matt, for helping us visualize that vision!

str() and arr() helpers

Next, we've added classes that wrap two of PHP's primitives: StringHelper and ArrayHelper. In practice though, you'd most likely use their str() and arr() shorthands.

Ideally, PHP would have built-in object primitives, but while we're waiting for that to ever happen, we wrote our own small wrappers around strings and arrays, and it turns out to be really useful.

Here are a couple of examples, but there is of course much more to it. I still need to write the docs, so for now I'll link to the source code, it's no rocket science to understand what's going on!

Here are a couple of examples:

if(str($path)
    ->trim('/')
    ->afterLast('/')
    ->matches('/\d+-/')
) {
    // …
}
$arr
    ->map(fn (string $path) => /* … */ )
    ->filter(fn (string $content) => /* … */)
    ->map(fn (string $content) => /* … */ )
    ->mapTo(BlogPost::class);

By the way, we're always open for PRs that add more methods to these classes, so if you want to contribute to Tempest, this might be a good starting point!

Cache

We also added a cache component, which is a small wrapper around PSR-6. All PSR-6 compliant libraries can be plugged in, but we made the user-facing interface much simpler. I was inspired by an awesome blogpost by Anthony Ferrera, which talks about a cleaner approach to PSR-6 — a must-read!

Here's what caching in Tempest looks like in a nutshell:

final readonly class RssController
{
    public function __construct(
        private Cache $cache
    ) {}
    
    public function __invoke(): Response
    {
        $rss = $this->cache->resolve(
            key: 'rss',
            cache: function () {
                return file_get_contents('https://stitcher.io/rss')
            },
            expiresAt: (new DateTimeImmutable())->add(new DateInterval('P1D'))
        );
    }   
}

You can read all the details about caching in the docs.

Discovery improvements

Finally, we made a lot of bugfixes and performance improvements to discovery, one of Tempests most powerful features. Besides bugfixes, we've also started making discovery more powerful, for example by allowing vendor classes to be hidden from discovery:

#[DoNotDiscover(except: [MigrationDiscovery::class])]
final class HiddenMigration implements Migration
{
    /* … */
}

On top of that, Enzo is working on a #[CanBePublished] attribute, which is going to make third-party package development a lot easier. But that'll have to wait until alpha 3.

Up next

Of course, there are a lot more small things fixed, changed, and added. You can read the full changelog here: https://github.com/tempestphp/tempest-framework/releases/tag/1.0-alpha2.

So, what's next? We keep on working towards the next alpha version: Aidan's working on a filesystem component, Enzo works on that #[CanBePublished] attribute, Sergiu is working on extended regex support for routing, and I'll tackle async command handling.

There's a lot going on, and we're super excited for it! Make sure to either subscribe via RSS or join our Discord if you want to stay up-to-date!

Until next time

Tempest