PHP code example of zfegg / callable-handler-decorator

1. Go to this page and download the library: Download zfegg/callable-handler-decorator library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

zfegg / callable-handler-decorator example snippets



// File config/config.php
// Add ConfigProvider 

new ConfigAggregator([
  Zfegg\PsrMvc\ConfigProvider::class,
]);


// config/autoload/global.php
use Zfegg\PsrMvc\Container\HandlerFactory;

return [
    // Add scan controllers paths
    \Zfegg\PsrMvc\Routing\RouteMetadata::class => [
        'paths' => ['path/to/Controller'],
        'cacheFile' => 'data/cache/route-meta.php', // For cache routes
    ]
];

// path/to/Controller/HomeController.php
public class HomeController
{
    #[Route("/")]
    #[Route("/home")]
    #[Route("/home/index")]
    #[Route("/home/index/{id?}")]
    public index(?int $id)
    {
        return new HtmlResponse();
    }

    #[Route("/home/about")]
    #[Route("/home/about/{id}")]
    public about(?int $id)
    {
        return new HtmlResponse();
    }
}


return [
  RouteMetadata::class => [
    // Scan controller paths.
    'paths' => [
       'path/Controller',
    ],
  ],
]


public class HomeController
{
    #[Route("/")]
    #[Route("/home")]
    #[Route("/home/index")]
    #[Route("/home/index/{id?}")]
    public index(?int $id)
    {
        return new HtmlResponse();
    }

    #[Route("/home/about")]
    #[Route("/home/about/{id}")]
    public about(?int $id)
    {
        return new HtmlResponse();
    }
}

use Psr\Http\Message\ResponseInterface;

#[Route("/api/[controller]")] // Route prefix `/api/products`
class ProductsController {

    #[HttpGet]   // GET /api/products
    public function listProducts(): array {
        return $db->fetchAllProducts();
    }
    
    // Route path `/api/products/{id}`
    #[HttpGet('{id}')] // GET /api/products/123
    public function getProduct(int $id): object {
        return $db->find($id);
    }
    
    #[HttpPost]  // POST /api/products
    public function create(#[FromBody(root: true)] array $data): object {
        $db->save($data);
        // ...
        return $db->find($lastInsertId);
    }
}

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

/*
POST /api/example/hello?page=1
Host: localhost
Cookie: PHPSESSION=xxx

name=foo
*/

class ExampleController {
    #[HttpPost('/api/[controller]/[action]')] 
    public function post(
        #[FromQuery]
        int $page,              // 1
        #[FromBody]
        string $name,           // "foo"
        #[FromContainer('db')]
        \PDO $container,        // object(PDO)
        #[FromCookie('PHPSESSION')]
        string $sessionId,      // "xxx"
        #[FromHeader]
        string $host,           // "localhost"
        #[FromServer('REMOTE_ADDR')]
        string $ip,             // "127.0.0.1"
    ): void {
        return ;
    }
    
    // Default binding params
    #[HttpPost('/api/[controller]/[action]/{id}')] 
    public function hello(
       ServerRequestInterface $request,  // Default bind `$request`.
       int $id,    // Default bind `$request->getAttribute('id')`.
       Foo $foo,   // If container exists the `Foo`, default bind `$container->get('id')`.
       Bar $bar,   // Default bind `$request->getAttribute(Bar::class, $request->getAttribute('bar'))`.
    ): void {
    }
}



class ExampleController {
    #[HttpPost('/api/[controller]/[action]/{id}')] 
    public function hello(
       ServerRequestInterface $request,  // Default bind `$request`.
       int $id,    // Default bind `$request->getAttribute('id')`.
       Foo $foo,   // If container exists the `Foo`, default bind `$container->get('id')`.
       Bar $bar,   // Default bind `$request->getAttribute(Bar::class, $request->getAttribute('bar'))`.
    ): void {
    }
}

class ExampleResponseController {
    #[HttpPost('/hello-void')]  // `void` -> HTTP 204 No Content
    public function helloVoid(): void {
    }

    /*
     *  If result is string, then convert to `HtmlResponse` object.
     *  `new HtmlResponse($result)`
     */
    #[HttpPost('/hello-string')]
    public function helloString(): string {
      return '<h1>Hello</h1>';
    }
    
    /*
     *  If result is array, default convert to `JsonResponse` object.
     *  `new JsonResponse($result)`
     */
    #[HttpPost('/hello-array')]
    public function helloArray(): array {
      return ['foo' => 'a', 'bar' => 'b'];
    }
}

class ExampleResponseController {
    #[HttpPost('/hello-void')]  // `void` -> HTTP 204 No Content
    public function helloVoid(): void {
    }

    /*
     * Serialize by `symfony/serializer`.
     * The serialization format is parsed by `FormatMatcher`.
     * <code>
     * $result = $serializer->serialize($result, $format);
     * $response->withBody($result);
     * </code>
     */
    #[HttpPost('/hello-foo')]
    public function hello(): Foo {
     return new Foo();
    }
}

use \Zfegg\PsrMvc\Preparer\SerializationPreparer;
use Zfegg\PsrMvc\Attribute\PrepareResult;

class ExampleResponseController {
    #[HttpPost('/hello-void')]  // `void` -> HTTP 204 No Content
    public function helloVoid(): void {
    }

    /*
     * 选用 `SerializationPreparer` 预处理器, 处理结果.
     */
    #[HttpPost('/hello-foo')]
    #[PrepareResult(SerializationPreparer::class, ['status' => 201, 'headers' => ['X-Test' => 'foo']])]
    public function hello(): Foo {
     return new Foo();
    }
}

// Class file HelloController.php

class HelloController {
  public function say(
    \Psr\Http\Message\ServerRequestInterface $request, // Inject request param
    string $name, // Auto inject param from $request->getAttribute('name').
    Foo $foo     // Auto inject param from container.
  ) {
    return new TextResponse('hello ' . $name);
  }
}


// File config/config.php
// Add ConfigProvider 

new ConfigAggregator([
  Zfegg\PsrMvc\ConfigProvider::class,
]);


// config/autoload/global.php
// Add demo class factories

use Zfegg\PsrMvc\Container\HandlerFactory;

return [
    'dependencies' => [
        'invokables' => [
            Hello::class,
        ],
        'factories' => [
            Hello::class . '@say' => HandlerFactory::class, 
        ],
    ]
];


// config/autoload/global.php
// Add demo class factories

use Zfegg\PsrMvc\Container\CallbackHandlerAbstractFactory;

return [
    'dependencies' => [
        'factories' => [
            ExampleController::class . '@fooMethod' => CallbackHandlerAbstractFactory::class, 
        ],
    ]
];

$app->get('/foo-method', ExampleController::class . '@fooMethod')


// config/autoload/global.php
// Add demo class factories

use Zfegg\PsrMvc\Container\CallbackHandlerAbstractFactory;

return [
    'dependencies' => [
        'invokables' => [
            Hello::class,
        ],
        'abstract_factories' => [
            CallbackHandlerAbstractFactory::class, 
        ],
    ]
];

class User {
  function create() {}
  function getList() {}
  function get($id) {}
  function delete($id) {}
}

// CallableHandlerDecorator abstract factory.
$container->get('User@create');
$container->get('User@getList');
$container->get('User@get');
$container->get('User@delete');

use \Zfegg\PsrMvc\Exception\AccessDeniedHttpException;
use \Zfegg\PsrMvc\Attribute\HttpGet;

class FooController {
  #[HttpGet("/api/foo")]
  public function fooAction() {
    throw new AccessDeniedHttpException("Foo", code: 100);
  }
}


use Laminas\Stratigility\Middleware\ErrorHandler;
use Zfegg\PsrMvc\Container\LoggingError\LoggingErrorDelegator;

return [
    'dependencies' => [
        'delegators' => [
            ErrorHandler::class => [
                LoggingErrorDelegator::class,
            ],
        ],
    ],
];