This component may look complex, weird and full of hacks but it is a game changer for how we run PHP applications.

Related tags

Frameworks runtime
Overview

PHP Runtimes

In early 2021, Symfony created a "Runtime component". This component may look complex, weird and full of hacks but it is a game changer for how we run PHP applications.

With the Runtime component, we can look at each application as a "black box". A box that has no connection to globals like $_SERVER or $_GET. To run the application you need (you guessed it) a Runtime. It is a class that looks at the black box to figure out what input it requires and handles the output.

Consider this small application that returns an UUID.

namespace Acme;

class Application
{
    public function run() {
        return Uuid::uuid4()->toString();
    }
}

To use this application with the Runtime component. We need our front-controller to return a callable that will create the application.

// index.php

return function() {
    return new Acme\Application();
}

If you want to use this application in a CLI environment, you need a Runtime that knows how to run an Acme\Application object and print the output on CLI. If you want to use it with Nginx/PHP-FPM then you need another Runtime that converts the application's output to a HTTP response.

Why is this a good thing?

Since your application is not connected to the global state, it is very portable. It is easy to create a Runtime to run the application with Bref, Swoole or ReactPHP without making any change to the application itself.

Since most modern PHP application is based on Symfony's HttpKernel, PSR-7 or PSR-15 we don't need too many different runtimes. This organization holds many PHP packages with runtimes for the most popular environments. It is not "the source of all runtimes", but rather a temporary place where runtimes can live before they move in to Bref/Swoole/RoadRunner etc.

All runtimes have hard dependencies to make installation easier. Everything should "just work".

Read more at the Symfony documentation.

Available Runtimes

Bref

Run your application on AWS Lambda with Bref.

Google Cloud

Run your application on Google Cloud.

ReactPHP

Event-driven, non-blocking I/O with ReactPHP.

RoadRunner

Spin up multiple PHP processes with Golang using RoadRunner.

Swoole

Build high-performance, scalable, concurrent HTTP services with Swoole.

PHP-FPM and traditional web servers

These runtimes are for PHP-FPM and the more traditional web servers one might use for local development.

Laravel

A runtime for Laravel and Artisan.

PSR-7 and PSR-15

Use the popular PSR architecture.

Symfony

The runtime for Symfony is included in the runtime component.

Contribute

Contributions are always welcomed. Send your PR or open an issue here: https://github.com/php-runtime/runtime

Comments
  • `StreamedResponse` not streaming with swoole integration, when using a `symfony/http-kernel`-based application

    `StreamedResponse` not streaming with swoole integration, when using a `symfony/http-kernel`-based application

    While investigating the suitability of runtime/swoole:0.3.0, I ran into a blocker caused by streamed responses.

    I was evaluating runtime/swoole because I ran into a problem similar to https://github.com/php-runtime/runtime/issues/50, and as of https://github.com/roadrunner-server/roadrunner/issues/923#issuecomment-817113479, I also couldn't use RoadRunner (which I much prefer to Swoole, at first glance).

    A controller producing large, slow responses

    Testing this in automation is a bit of a mess (suggestions welcome though), but the idea is that I can stream a response as follows:

    final class MyGiantCsvDownloadController
    {
        public function someAction(): Response
        {
            return new StreamedResponse(function () {
                foreach (range(1, 5) as $i) {
                    echo str_repeat((string) $i, 100000), "\n";
                    sleep(1);
                }
            }, Response::HTTP_OK, [
                'Content-Type' => 'text/plain',
            ]);
        }
    }
    

    First problem: Symfony\Component\HttpKernel\EventListener\StreamedResponseListener

    When interacting with this controller, through runtime/swoole, the respone is not sent via \Runtime\Swoole\SymfonyHttpBridge, where it should happen:

    https://github.com/php-runtime/runtime/blob/420d39e651580bd11904655dec3c7d3411a6f6c2/src/swoole/src/SymfonyHttpBridge.php#L48-L57

    In this block, $response->write($buffer); should receive a massive chunk of 111111...22222...<SNIP>...55555, but instead, all output is sent to STDOUT in the worker (not to the response object), and a warning is produced:

    <SNIP>55555555555
    PHP Warning:  Swoole\Http\Response::write(): data to send is empty in /srv/share/vendor/runtime/swoole/src/SymfonyHttpBridge.php on line 50
    

    Effectively, this write produces nothing, because the response was already sent by symfony/http-kernel:

    https://github.com/php-runtime/runtime/blob/420d39e651580bd11904655dec3c7d3411a6f6c2/src/swoole/src/SymfonyHttpBridge.php#L50

    After some investigation, I found that the culprit is that symfony/http-kernel sends StreamedResponse through a listener:

    https://github.com/symfony/symfony/blob/82e8d23788940421e0ad6e30163242db3ba27a02/src/Symfony/Component/HttpKernel/EventListener/StreamedResponseListener.php#L27-L51

    I disabled this listener by monkey-patching (while trying out stuff), but if you know a "clean" way to remove it completely from my application, lemme know.

    Second problem: response buffer is completely sent in one shot

    Assuming we disabled the StreamedResponseListener (clean solution pending), the response content now makes it to Swoole\Http\Response#write($buffer);, but in one big chunk: the HTTP client sees the first byte when swoole finished collecting the whole response.

    This is because of this ob_start() call not having a defined buffer size specified:

    https://github.com/php-runtime/runtime/blob/420d39e651580bd11904655dec3c7d3411a6f6c2/src/swoole/src/SymfonyHttpBridge.php#L49-L53

    According to the documentation for ob_start():

    If the optional parameter chunk_size is passed, the buffer will be flushed after any output call which causes the buffer's length to equal or exceed chunk_size. The default value 0 means that the output function will only be called when the output buffer is closed.

    Given that PHP uses a default buffer size of 4096, perhaps it would be a good idea to add one here too? I tried it locally, and my HTTP client starts receiving bytes much earlier than 5 seconds, this way :)

    opened by Ocramius 12
  • Bref\SymfonyRequestBridge using proxy settings instead of sourceIp

    Bref\SymfonyRequestBridge using proxy settings instead of sourceIp

    I'm using the Bref runtime to run a Symfony application in Lambda with CloudFront in front of it. Getting the source ip address with that layout is hard, esp. because the SymfonyRequestBridge is overriding the proxy configuration when starting up.

    While reading the code I was wondering, why the Bridge is using the proxy configuration at all, instead of using the Lambda provided clientIp which already contains the correct value.

    By replacing (SymfonyRequestBridge:40)

                'REMOTE_ADDR' => '127.0.0.1',
    

    with

                'REMOTE_ADDR' => $event->getRequestContext()['http']['sourceIp'],
    

    I was able to fix this issue for me while testing.

    bug 
    opened by rmbl 11
  • Fix #115 - buffer each `StreamedResponse` chunk when sending data to swoole worker output

    Fix #115 - buffer each `StreamedResponse` chunk when sending data to swoole worker output

    This change ensures that, when converting a StreamedResponse to output within php-runtime/swoole, the output is streamed chunk-by-chunk, instead of being buffered in its entirety, and then being sent out to the swooler server all in one shot.

    This should fix some obvious performance, latency and memory issues related to streaming common responses assembled by PHP-side processes.

    Note: you will still need to disable symfony's StreamedResponseListener when working with this package.

    Fixes #115

    bug 
    opened by Ocramius 9
  • [Swoole] Support Symfony Session

    [Swoole] Support Symfony Session

    When using Swoole, we need to maintain session (cookie)

    Ref: https://github.com/k911/swoole-bundle/blob/develop/src/Bridge/Symfony/HttpFoundation/Session/SetSessionCookieEventListener.php

    opened by ad3n 8
  • [FrankenPHP] Relax php requirement - allow 8.0

    [FrankenPHP] Relax php requirement - allow 8.0

    Allows playing with https://github.com/dunglas/frankenphp-demo with PHP 8.1 installed locally and without need to tweak the README instructions. Otherwise:

    Screenshot 2022-10-16 at 15 38 36

    Let's revisit this only once php 8.2 stable gets released.

    opened by chalasr 7
  • Adding Swoole's Server mode and settings

    Adding Swoole's Server mode and settings

    Closes #58 by

    $_SERVER['APP_RUNTIME_OPTIONS'] = [
        'settings' => [
            \Swoole\Constant::OPTION_ENABLE_STATIC_HANDLER => true,
            \Swoole\Constant::OPTION_DOCUMENT_ROOT => dirname(__DIR__).'/public'
        ]
    ];
    
    opened by leocavalcante 6
  • Difference between swoole and swoole-nyholm

    Difference between swoole and swoole-nyholm

    It would be nice were the difference between the two runtimes documented; I'm unsure which runtime to select, or whether they are production-ready (the version number doesn't indicate so).

    Could you clarify the documentation a little?

    opened by Radiergummi 5
  • Fixed server key case and manually setting headers

    Fixed server key case and manually setting headers

    This PR changes the key case of the $server array so matches can be made. It also manually sets the HeaderBag because headers are not sent as HTTP_* keys on Swoole's Request $server.

    opened by leocavalcante 5
  • [Bref] What's the correct configuration for Console app?

    [Bref] What's the correct configuration for Console app?

    I'm trying to migrate my Symfony app with Bref to use Runtime, and I can't get the Lambda function with Symfony Console to work correctly. I also get the same behaviour for Nyholm/bref-runtime-demo.

    By "work correctly", I mean that if I execute a command with vendor/bin/bref cli, I can't see any output in my console. The command seems to be executed correctly, its output is logged in CloudWatch, but I can't see the output on my machine.

    The readme in this project implicates that console function should keep using bref:layer.console layer:

    # pluggins and other options omitted
    provider:
      environment:
        APP_RUNTIME: Runtime\Bref\Runtime
    
    functions:
      console:
        handler: bin/console
        layers:
          - ${bref:layer.php-80}
          - ${bref:layer.console}
    

    The demo project suggests that console functions should use bref-extra:symfony-runtime-php-80 layer:

    # pluggins and other options omitted
    provider:
      environment:
        APP_RUNTIME: Runtime\Bref\Runtime
    
    functions:
      console:
        handler: bin/console
        layers:
          - ${bref:layer.php-80}
          - ${bref-extra:symfony-runtime-php-80}
    

    Either way, the function seems to be executed correctly, but there is no local output.

    I was able to display the function's output locally with the following config by forcing it to use GenericRuntime.

    # pluggins and other options omitted
    provider:
      environment:
        APP_RUNTIME: Runtime\Bref\Runtime
    
    functions:
      console:
        environment:
          APP_RUNTIME: Symfony\Component\Runtime\GenericRuntime
        handler: bin/console
        layers:
          - ${bref:layer.php-80}
          - ${bref:layer.console}
    

    With this setup, the function is executed correctly, its output is logged to CloudWatch, and I can see the output locally in my console. In other words, it works exactly in the same way as the "old" bin/console without Runtime did. But I'm not sure this is the correct approach.

    It's probably fine for a console function to write only to stderr if it's a cron, but for functions executed remotely with vendor/bin/bref cli (e.g. DB migrations), their output should be transferred back to the client.

    Am I missing something?

    opened by vhenzl 3
  • Psr-17 does not work with Runtime 6.0 on PHP 8.0

    Psr-17 does not work with Runtime 6.0 on PHP 8.0

    Fatal error: Declaration of Runtime\Psr17\Runtime::getArgument(ReflectionParameter $parameter, ?string $type) must be compatible with Symfony\Component\Runtime\GenericRuntime::getArgument(ReflectionParameter $parameter, ?string $type): mixed in /srv/middleware/vendor/runtime/psr-17/src/Runtime.php on line 53

    opened by yyeltsyn 2
  • Roadrunner Nyholm - Add information about Roadrunner server env config to README

    Roadrunner Nyholm - Add information about Roadrunner server env config to README

    I did not know that I have to provide env to the .rr.yaml config file and as a newbie, I put it only to the .env file. These systems work differently than Symfony I had to spend a lot of time to find this information.

    opened by Ferror 2
  • [Bref] Added support for handle timeouts

    [Bref] Added support for handle timeouts

    We want to give the application some time to cleanup and write logs.

    This feature was originally suggested in https://github.com/brefphp/bref/pull/895, but it has not been merged because it did not work with the PHP-FPM layer. We are not using PHP-FPM so we are good to go.

    opened by Nyholm 2
  • Problems integrating Functions when PHP74 is not preview anymore

    Problems integrating Functions when PHP74 is not preview anymore

    Hi Tobias.

    We are developing with Symfony and Google Functions. It's fresh so there are changes probably. Today we are facing some bad news.

    We have problem from today as Coposer 1 run by deploy script from google forces to install their own router and crashes on it.

    When I do it myself before, there starts to be conflict and google in autoload and router is invoked as the first so your library is out of work.

    Maybe we are not the only one or we deploy differently. Do you have any suggestions?

    Is there any way to share knowledge around your project than mailing you?

    -------------------- Not installing Google's router:

    ERROR: (gcloud.functions.deploy) OperationError: code=3, message=Build failed: Warning from https://repo.packagist.org: Support for Composer 1 is deprecated and some packages will not be available. You should upgrade to Composer 2. See https://blog.packagist.com/deprecating-composer-1-support/ Warning from https://repo.packagist.org: Support for Composer 1 is deprecated and some packages will not be available. You should upgrade to Composer 2. See https://blog.packagist.com/deprecating-composer-1-support/ ./composer.json has been updated Loading composer repositories with package information Warning from https://repo.packagist.org: Support for Composer 1 is deprecated and some packages will not be available. You should upgrade to Composer 2. See https://blog.packagist.com/deprecating-composer-1-support/ Updating dependencies (including require-dev) Restricting packages listed in "symfony/symfony" to "5.3.*" Your requirements could not be resolved to an installable set of packages.

    Problem 1 - Conclusion: don't install google/cloud-functions-framework v0.7.2 - Conclusion: don't install google/cloud-functions-framework v0.7.1 - Conclusion: remove guzzlehttp/psr7 2.0.0 - Installation request for google/cloud-functions-framework ^0.7 -> satisfiable by google/cloud-functions-framework[v0.7.0, v0.7.1, v0.7.2]. - Conclusion: don't install guzzlehttp/psr7 2.0.0 - google/cloud-functions-framework v0.7.0 requires guzzlehttp/psr7 ^1.6 -> satisfiable by guzzlehttp/psr7[1.6.0, 1.6.1, 1.7.0, 1.8.0, 1.8.1, 1.8.2]. - Can only install one of: guzzlehttp/psr7[1.7.0, 2.0.0]. - Can only install one of: guzzlehttp/psr7[1.8.0, 2.0.0]. - Can only install one of: guzzlehttp/psr7[1.8.1, 2.0.0]. - Can only install one of: guzzlehttp/psr7[1.8.2, 2.0.0]. - Can only install one of: guzzlehttp/psr7[1.6.0, 2.0.0]. - Can only install one of: guzzlehttp/psr7[1.6.1, 2.0.0]. - Installation request for guzzlehttp/psr7 (locked at 2.0.0) -> satisfiable by guzzlehttp/psr7[2.0.0].

    Installation failed, reverting ./composer.json to its original content.; Error ID: caafae72

    -------------- Installing Google's router

    Nothing to install, update or remove Generating optimized autoload files Warning: Ambiguous class resolution, "Google\CloudFunctions\CloudEvent" was found 2x: in "D:/www/cg-platby-test/app/vendor/google/cloud-functions-framework/src/CloudEvent.php" and "D:/ww w/cg-platby-test/app/vendor/runtime/google-cloud/google\CloudEvent.php", the first will be used. Warning: Ambiguous class resolution, "Google\CloudFunctions\Context" was found 2x: in "D:/www/cg-platby-test/app/vendor/google/cloud-functions-framework/src/Context.php" and "D:/www/cg-p latby-test/app/vendor/runtime/google-cloud/google\Context.php", the first will be used. Warning: Ambiguous class resolution, "Google\CloudFunctions\LegacyEventMapper" was found 2x: in "D:/www/cg-platby-test/app/vendor/google/cloud-functions-framework/src/LegacyEventMapper.p hp" and "D:/www/cg-platby-test/app/vendor/runtime/google-cloud/google\LegacyEventMapper.php", the first will be used. 37 packages you are using are looking for funding. Use the composer fund command to find out more!

    --------------- and then deployed:

    *5 FastCGI sent in stderr: "PHP message: PHP Fatal error: Uncaught InvalidArgumentException: Function target is not callable: "throwException" in /workspace/vendor/google/cloud-functions-framework/router.php:68 Stack trace: #0 /workspace/vendor/google/cloud-functions-framework/router.php(77): {closure}()

    opened by petr-ekl-itcube 1
  • StreamedResponse not supported in Roadrunner

    StreamedResponse not supported in Roadrunner

    More as a reference here currently there is no way to use a StreamedResponse inside roadrunner. This is because things output with echo, var_dump, flush or any other php internal method is not supported by roadrunner and is in this case ignored.

    The issue on the roadrunner side is here: https://github.com/spiral/roadrunner/issues/2.

    opened by alexander-schranz 4
Owner
Runtime
Runtime
πŸš€ This is a utility library that contains tools you may use everywhere.

Utilities Someday I will write documentation for this library, but for now, you can use it and see how it works. Introduction Some documentation will

Utilities for PHP 6 Sep 16, 2022
Framework X – the simple and fast micro framework for building reactive web applications that run anywhere.

Framework X Framework X – the simple and fast micro framework for building reactive web applications that run anywhere. Quickstart Documentation Tests

Christian LΓΌck 620 Jan 7, 2023
FreeSWITCH's Event Socket Layer is a TCP control interface enabling the development of complex dynamic dialplans/workflows

Asynchronous Event Socket Layer library for PHP Quickstart FreeSWITCH's Event Socket Layer is a TCP control interface enabling the development of comp

rtckit 3 Oct 11, 2022
Leaf is a PHP framework that helps you create clean, simple but powerful web apps and APIs quickly and easily.

Leaf is a PHP framework that helps you create clean, simple but powerful web apps and APIs quickly and easily. Leaf introduces a cleaner and much simpler structure to the PHP language while maintaining it's flexibility. With a simple structure and a shallow learning curve, it's an excellent way to rapidly build powerful and high performant web apps and APIs.

Leaf Framework 706 Jan 3, 2023
The Runtime Component enables decoupling applications from global state.

Runtime Component Symfony Runtime enables decoupling applications from global state. This Component is experimental. Experimental features are not cov

Symfony 409 Jan 3, 2023
A easy way to install your basic yii projetc, we have encrypt database password in phpfile, my class with alot funtions to help you encrypt and decrypt and our swoole server install just run ./yii swoole/start and be happy!

Yii 2 Basic Project Template with swoole and Modules Yii 2 Basic Project Template is a skeleton Yii 2 application best for rapidly creating small proj

null 3 Apr 11, 2022
Run Browsershot on AWS Lambda with Sidecar for Laravel

Run Browsershot on AWS Lambda with Sidecar for Laravel This package allows you to run Browsershot on AWS Lambda through Sidecar. You won't need to ins

Stefan Zweifel 121 Dec 21, 2022
Run laravel with workman ,1 artisan command, 10x speed up

Laraman Run laravel with workman , 1 artisan command, 10x speed up Installation Via Composer # install package composer require itinysun/laraman # i

null 13 Jun 3, 2023
CleverStyle Framework is simple, scalable, fast and secure full-stack PHP framework

CleverStyle Framework is simple, scalable, fast and secure full-stack PHP framework. It is free, Open Source and is distributed under Free Public Lice

Nazar Mokrynskyi 150 Apr 12, 2022
Flare is a PHP full-stack web framework that is light, fast, flexible, and secure.

Flare framework is a PHP full-stack web framework that is simple ,powerful , fast , flexible, and secure with long-term support.

Flare framework 3 Oct 24, 2022
CodeIgniter - a PHP full-stack web framework that is light, fast, flexible and secure

CodeIgniter 4 Development What is CodeIgniter? CodeIgniter is a PHP full-stack web framework that is light, fast, flexible and secure. More informatio

CodeIgniter 4 web framework 4.5k Jan 4, 2023
Spiral Framework is a High-Performance PHP/Go Full-Stack framework and group of over sixty PSR-compatible components

Spiral HTTP Application Skeleton Spiral Framework is a High-Performance PHP/Go Full-Stack framework and group of over sixty PSR-compatible components.

Spiral Scout 152 Dec 18, 2022
High performance, full-stack PHP framework delivered as a C extension.

Phalcon Framework Phalcon is an open source web framework delivered as a C extension for the PHP language providing high performance and lower resourc

The Phalcon PHP Framework 10.7k Jan 8, 2023
πŸš€ PHP Microservice Full Coroutine Framework

PHP microservice coroutine framework δΈ­ζ–‡θ―΄ζ˜Ž Introduction Swoft is a PHP microservices coroutine framework based on the Swoole extension. Like Go, Swoft

Swoft Cloud 5.5k Dec 28, 2022
A Faster Lightweight Full-Stack PHP Framework

A Faster Lightweight Full-Stack PHP Framework δΈ­ζ–‡η‰ˆγ€€ Docker env Just one command to build all env for the easy-php How to build a PHP framework by ourse

Zhan Shi 769 Dec 8, 2022
FlyCubePHP is an MVC Web Framework developed in PHP and repeating the ideology and principles of building WEB applications, embedded in Ruby on Rails.

FlyCubePHP FlyCubePHP is an MVC Web Framework developed in PHP and repeating the ideology and principles of building WEB applications, embedded in Rub

Anton 1 Dec 21, 2021
Main component controls and coordinates saga participants

Saga Orchestrator Table Of Contents Introduction Requirements About package Installation Getting started Configuration Saga creation Internal License

null 17 Jan 1, 2023
Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs.

Slim Framework Slim is a PHP micro-framework that helps you quickly write simple yet powerful web applications and APIs. Installation It's recommended

Slim Framework 11.5k Jan 4, 2023
PPM is a process manager, supercharger and load balancer for modern PHP applications.

PPM - PHP Process Manager PHP-PM is a process manager, supercharger and load balancer for PHP applications. It's based on ReactPHP and works best with

PPM - PHP Process Manager 6.5k Dec 27, 2022