PHPackages                             timostamm/symfony-twirp-handler - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. timostamm/symfony-twirp-handler

ActiveLibrary[API Development](/categories/api)

timostamm/symfony-twirp-handler
===============================

Helps implementing Twirp in a Symfony application

v0.0.5(3y ago)03031MITPHPPHP &gt;=7.1

Since Aug 19Pushed 2y ago1 watchersCompare

[ Source](https://github.com/timostamm/symfony-twirp-handler)[ Packagist](https://packagist.org/packages/timostamm/symfony-twirp-handler)[ RSS](/packages/timostamm-symfony-twirp-handler/feed)WikiDiscussions master Synced today

READMEChangelog (1)Dependencies (7)Versions (6)Used By (0)

Symfony Twirp Handler
=====================

[](#symfony-twirp-handler)

Helps implementing Twirp in a Symfony application.

Most simple way
---------------

[](#most-simple-way)

Lets say you have this service defined in a proto file:

```
syntax = "proto3";
service SearchService {
    rpc Search (SearchRequest) returns (SearchResponse);
}
```

First you generate PHP code with protoc, for example:

```
protoc --proto_path protos/ --php_out out-php protos/example-service.proto
```

Then you create a controller for the corresponding Twirp routes:

```
// SearchServiceController.php
/**
 * @Route("/twirp/SearchService")
 */
class SearchServiceController
{

    use TwirpControllerTrait;

    /**
     * @Route("/MakeHat")
     */
    public function makeHat(Request $request): Response
    {
        /** @var SearchRequest $input */
        $input = $this->readTwirp($request, SearchRequest::class);
        // ...

        $output = new SearchResponse();
        // ...

        return $this->writeTwirp($request, $output);
    }

}
```

Twirp route URLs are constructed like this: `twirp/{proto package name}.{proto service name}/{proto method name}`.

`readTwirp()` and `writeTwirp()` will do content negotiation for you.

Supporting errors properly
--------------------------

[](#supporting-errors-properly)

Twirp has its own error format. To convert exceptions automatically, you can use the `TwirpErrorSubscriber`:

```
// services.yaml
SymfonyTwirp\TwirpErrorSubscriber:
    arguments:
        $requestTagAttribute: "_request_id"
        $debug: '%kernel.debug%'
        $prefix: "twirp"
```

If you have this subscriber set up, you can also throw your own `TwirpError` (with full control over twirp error code and meta data). For documentation about the arguments of `TwirpErrorSubscriber`, check the PHPdoc.

Advanced use
------------

[](#advanced-use)

Writing symfony routes for every RPC is tedious and error-prone.
Enable `php_generic_services` to generate a PHP interface for each service:

```
// example-service.proto
syntax = "proto3";

option php_generic_services = true;

service SearchService {
    rpc Search (SearchRequest) returns (SearchResponse);
}
```

From this file, protoc generates a generic service interface `SearchServiceInterface.php`. Create a new class `SearchService` and implement the interface:

```
// SearchService.php
class SearchService implements SearchServiceInterface
{

    public function search(SearchRequest $request)
    {
        $response = new SearchResponse();
        $response->setHits(['a', 'b', 'c']);
        return $response;
    }

}
```

To serve this service via Twirp, you can use the `TwirpHandler`. You only need a single route for one or more services. The handler takes care of the routing, content negotiation, parsing and serializing and automatically invokes the correct method on your service.

Create a route that matches all twirp/ requests and use the TwirpHandler as follows:

```
// TwirpController.php
/**
 * @Route( path="twirp/{serviceName}/{methodName}" )
 */
public function execute(RequestInterface $request, string $serviceName, string $methodName): Response
{
    $resolver = new ServiceResolver();

    $resolver->registerInstance(
        SearchServiceInterface::class, // the interface generated by protoc
        new SearchService() // your implementation of the interface
    );

    // alternatively, you can register a factory
    // $resolver->registerFactory(SearchServiceInterface::class, function() {
    //    return new SearchService();
    // });

    // .. or a PSR container with $resolver->registerContainer()

    $handler = new TwirpHandler($resolver);

    return $handler->handle($serviceName, $methodName, $request);
}
```

###  Health Score

23

—

LowBetter than 27% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity13

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity43

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 75% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~211 days

Total

5

Last Release

1244d ago

PHP version history (2 changes)v0.0.1PHP ^7.1

v0.0.5PHP &gt;=7.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/6364011a12f22cb5046056371bde6170218218c560eddfdc08b4644b7648af78?d=identicon)[timostamm](/maintainers/timostamm)

---

Top Contributors

[![timostamm](https://avatars.githubusercontent.com/u/4289451?v=4)](https://github.com/timostamm "timostamm (9 commits)")[![ducrot](https://avatars.githubusercontent.com/u/3525119?v=4)](https://github.com/ducrot "ducrot (3 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/timostamm-symfony-twirp-handler/health.svg)

```
[![Health](https://phpackages.com/badges/timostamm-symfony-twirp-handler/health.svg)](https://phpackages.com/packages/timostamm-symfony-twirp-handler)
```

###  Alternatives

[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M647](/packages/sylius-sylius)[nelmio/api-doc-bundle

Generates documentation for your REST API from attributes

2.3k63.6M232](/packages/nelmio-api-doc-bundle)[api-platform/core

Build a fully-featured hypermedia or GraphQL API in minutes!

2.6k48.1M235](/packages/api-platform-core)[shopware/platform

The Shopware e-commerce core

3.3k1.5M3](/packages/shopware-platform)[sulu/sulu

Core framework that implements the functionality of the Sulu content management system

1.3k1.3M152](/packages/sulu-sulu)[prestashop/prestashop

PrestaShop is an Open Source e-commerce platform, committed to providing the best shopping cart experience for both merchants and customers.

9.0k15.4k](/packages/prestashop-prestashop)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
