paint-brush
Introducing Resonance, A New PHP Framework Built on Top of Swooleby@distantmagic
322 reads
322 reads

Introducing Resonance, A New PHP Framework Built on Top of Swoole

by Mateusz CharytoniukOctober 27th, 2023
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Resonance is new, and it's my first open-source project of this magnitude.
featured image - Introducing Resonance, A New PHP Framework Built on Top of Swoole
Mateusz Charytoniuk HackerNoon profile picture

I spent the last year working on the new PHP framework to push this programming language further into the modern era.


I firmly believe that the future of PHP lies in Fibers, Coroutines, and libraries like Swoole.

The Bright Future of PHP

Most people know PHP just as a website framework, but it's much more - it can serve as a communication hub in your infrastructure that interconnects all your services through REST API, GraphQL, WebSockets, gRPC, and more.


It's effortless to prototype and write new features in PHP. PHP is also straightforward to extend; if necessary, replacing parts of your application with code written in a different language is simple. It's the perfect starting point when creating new applications.

About Resonance

Resonance is centered around this idea - to quickly start from the ground up in the asynchronous environment and be able to set up all the necessary services and APIs and then swap, replace, or expand all the application's components.

Attributes First

Everything is as modular as possible, with only minimal central configuration files - everything is configured through Attributes. For example:

<?php

namespace App\HttpResponder;

use App\DatabaseEntity\BlogPostForDisplay;
use App\HttpRouteSymbol;
use Distantmagic\Resonance\Attribute\RespondsToHttp;
use Distantmagic\Resonance\Attribute\RouteParameter;
use Distantmagic\Resonance\Attribute\Singleton;
use Distantmagic\Resonance\HttpInterceptableInterface;
use Distantmagic\Resonance\HttpResponder;
use Distantmagic\Resonance\HttpResponder\HttpController;
use Distantmagic\Resonance\RequestMethod;
use Distantmagic\Resonance\SingletonCollection;
use Distantmagic\Resonance\TwigTemplate;

#[RespondsToHttp(
    method: RequestMethod::GET,
    pattern: '/blog/{blog_post_slug}',
    routeSymbol: HttpRouteSymbol::BlogPostShow,
)]
#[Singleton(collection: SingletonCollection::HttpResponder)]
final readonly class BlogPostShow extends HttpController
{
    public function handle(
        #[RouteParameter(from: 'blog_post_slug')]
        BlogPostForDisplay $blogPost,
    ): HttpInterceptableInterface {
        return new TwigTemplate('turbo/website/blog_post.twig', [
            'blog_post' => $blogPost,
        ]);
    }
}

Asynchronous GraphQL in PHP

You can build the entire GraphQL schema in PHP using attributes:

<?php

use GraphQL\Type\Definition\ObjectType;
use GraphQL\Type\Definition\Type;
use Distantmagic\Resonance\Framework\Attribute\Singleton;
use Distantmagic\Resonance\Framework\SwooleFuture;

#[Singleton]
final class PingType extends ObjectType
{
    public function __construct()
    {
        parent::__construct([
            'name' => 'Ping',
            'description' => 'Test field',
            'fields' => [
                'message' => [
                    'type' => Type::string(),
                    'description' => 'Always responds with pong',
                    'resolve' => $this->resolveMessage(...),
                ],
            ],
        ]);
    }

    private function resolveMessage(): SwooleFuture
    {
        return new SwooleFuture(function () {
            sleep(1);

            return 'pong';
        });
    }
}

This query is going to take 1 second (instead of 3), since the field is resolved asynchronously:

query MultiPing() {
    ping1: ping { message }
    ping2: ping { message }
    ping3: ping { message }
}

Promise-like Objects in PHP

Swoole's coroutines are wrapped inside a SwooleFuture object, which provides easy access to asynchronous features:

<?php

use Distantmagic\Resonance\SwooleFuture;

$future1 = new SwooleFuture(function (int $value) {
    assert($value === 1);

    return $value + 2;
});

$future2 = $future1->then(new SwooleFuture(function (int $value) {
    assert($value === 3);

    return $value + 4;
}));

assert($future2->resolve(1)->result === 7);

Much more

The project is free and open source.


Resonance is new, and it's my first open-source project of this magnitude. Currently, I am working on it full-time. If you try it out and Resonance will help you with your projects, I'd be the happiest man alive.


If you find the project interesting please leave me a star on GitHub!


Also published here.