...

East Foundation

Create PHP applications following the #East programming philosophy.


To integrate your code, following the #east programming philosophy, to your framework, while keeping this paradigm.

This library implement a middleware pattern to allow additional behavior or feature, like session or translation.

This library is built on the Recipe library, and redefine only some interfaces to be more comprehensive with HTTP context.

  • Middleware are actions, but must implement a specific interface.
  • The HTTP workflow is defined into a Recipe, able to be extended.
  • Chef became a manager, to execute the workflow when a request is accepted.
  • Usable with any PSR-11 Framework, Symfony implementation is also provided.
...

To understand “east”, think of a map, like north, south, east, west; the idea, as far as I understand, is that west-oriented is stateful (you call methods and work on the return values), while east-oriented is stateless (you pass lambdas or interface implementations).

http://www.draconianoverlord.com/2013/04/12/east-oriented-programming.html

Features


East

Can implement your #East package in your framework while keeping this philosophy.

PSR-7

Interoperable with any code following the PSR-7 recommendation.

PSR-11

Interoperable with any framework implementing the PSR-11 recommendation.

Extendable

Thanks to Recipe, can be extendable only via the DI's configuration.

GitHub


Fork the project on GitHub

It is open source! It's hosted, developed, and maintained on GitHub by folks like you.


View GitHub Project

Example



<?php

use function DI\decorate;
use 
DI\ContainerBuilder;
use 
Psr\Http\Message\ResponseInterface;
use 
Psr\Http\Message\ServerRequestInterface;
use 
Teknoo\East\Foundation\Http\ClientInterface;
use 
Teknoo\East\Foundation\Manager\ManagerInterface;
use 
Teknoo\East\Foundation\Middleware\MiddlewareInterface;
use 
Teknoo\East\Foundation\Recipe\RecipeInterface;
use 
Teknoo\East\Foundation\Router\Result;
use 
Teknoo\East\Foundation\Router\RouterInterface;
use 
Zend\Diactoros\ServerRequest;
use 
Zend\Diactoros\Response\TextResponse;

require_once 
'vendor/autoload.php';

/**
 * Simulate client, accepts responses from controller and pass them to the "framework" or lower layer to send them
 * to the brower.
 */
$client = new class implements ClientInterface {
    
/**
     * @var ResponseInterface
     */
    
private $response;

    public function 
updateResponse(callable $modifier): ClientInterface
    
{
        
$modifier($this$this->response);

        return 
$this;
    }

    public function 
acceptResponse(ResponseInterface $response): ClientInterface
    
{
        
$this->response $response;

        return 
$this;
    }

    public function 
sendResponse(ResponseInterface $response null bool $silently false): ClientInterface
    
{
        if (
$response instanceof ResponseInterface) {
            
$this->acceptResponse($response);
        }

        print (string) 
$response->getBody().PHP_EOL;

        return 
$this;
    }

    public function 
errorInRequest(\Throwable $throwable): ClientInterface
    
{
        print 
$throwable->getMessage();

        return 
$this;
    }
};

/**
 * First controller / endpoint, dedicated for the request /foo
 * @param ServerRequestInterface $request
 * @param ClientInterface $client
 */
$endPoint1 = function (ServerRequestInterface $requestClientInterface $client) {
    
$client->sendResponse(new TextResponse('request /bar, endpoint 1, value : '.$request->getQueryParams()['value']));
};

/**
 * Second controller / endpoint, dedicated for the request /bar
 * @param ClientInterface $client
 * @param string $value
 */
$endPoint2 = function (ClientInterface $clientstring $value) {
    
$client->sendResponse(new TextResponse('request /bar, endpoint 2, value : '.$value));
};

/**
 * Simulate router
 */
$router = new class($endPoint1$endPoint2) implements RouterInterface {
    
/**
     * @var callable
     */
    
private $endPoint1;

    
/**
     * @var callable
     */
    
private $endPoint2;

    public function 
__construct(callable $endPoint1 , callable $endPoint2)
    {
        
$this->endPoint1 $endPoint1;
        
$this->endPoint2 $endPoint2;
    }

    public function 
execute(
        
ClientInterface $client ,
        
ServerRequestInterface $request ,
        
ManagerInterface $manager
    
): MiddlewareInterface
    
{
        
$result null;
        
$uri = (string) $request->getUri();
        switch (
$uri) {
            case 
'/foo':
                
$result = new Result($this->endPoint1);
                break;
            case 
'/bar':
                
$result = new Result($this->endPoint2);
                break;
        }

        
$request $request->withAttribute(RouterInterface::ROUTER_RESULT_KEY$result);
        
$manager->continueExecution($client$request);

        return 
$this;
    }
};

$builder = new ContainerBuilder();
$builder->addDefinitions('vendor/teknoo/east-foundation/src/universal/di.php');
$builder->addDefinitions([
    
RecipeInterface::class => decorate(function ($previous) use ($router) {
        if (
$previous instanceof RecipeInterface) {
            
$previous $previous->registerMiddleware(
                
$router,
                
RouterInterface::MIDDLEWARE_PRIORITY
            
);
        }

        return 
$previous;
    })
]);

$container $builder->build();

//Simulate Server request reception
$request1 = new ServerRequest([], [], '/foo''GET');
$request1 $request1->withQueryParams(['value' => 'bar']);
$request2 = new ServerRequest([], [], '/bar''GET');
$request2 $request2->withQueryParams(['value' => 'foo']);

$manager $container->get(ManagerInterface::class);
$manager->receiveRequest($client$request1);
//Print: request /bar, endpoint 1, value : bar
$manager->receiveRequest($client$request2);
//Print: request /bar, endpoint 2, value : foo