Coder Social home page Coder Social logo

articus / pathhandler Goto Github PK

View Code? Open in Web Editor NEW
4.0 2.0 1.0 2.38 MB

Library for API development with Mezzio that simplifies creating operation middlewares and registering them in router

Home Page: https://articus.github.io/PathHandler/

License: MIT License

PHP 100.00%
middleware routing api dispatch laminas-mezzio

pathhandler's Introduction

Path Handler

Run tests Publish docs Coveralls Codacy

This library considerably simplifies API development with Mezzio by reducing amount of boilerplate code you have to write for each API operation. The idea is to provide a more convenient way to deal with:

  • routing - routes for all operations are registered automatically
  • consuming - each operation may have unique algorithm to parse request body according its content type
  • attributing (as in PSR-7 request attributes) - each operation may have its own set of request attributes calculated from raw request data (like current user information insteadof authentication header, validated DTO insteadof form value array, entity object insteadof query parameter with its id and so on)
  • producing - each operation may have unique algorithm to prepare response body from operation result according media type accepted by client

So you can focus on handling your API operations and spend less time on writing auxiliary code for request processing.

How to install?

Just add "articus/path-handler" to your composer.json and check packages suggested by the library for extra dependencies of optional components you want to use.

How to use?

First of all you need a project with Mezzio application. For example, you can generate one with this installer.

Next you need to declare handlers. Each handler is a set of all operations that can be performed when some path of your API is accessed with distinct HTTP methods. Any class can be a handler, you just need to decorate it with special PHP attributes:

namespace My;

use Articus\PathHandler\PhpAttribute as PHA;
use Articus\PathHandler\Exception;
use Psr\Http\Message\ServerRequestInterface;

#[PHA\Route('/entity')] //This is how you set path for handler operations
class Handler
{
    #[PHA\Post()] //This is how you declare HTTP method of the operation
    #[PHA\Consumer('application/json', 'Json')] //This is how you consume request body
    #[PHA\Attribute('Transfer', ['type'=>'My\DTO','object_attr'=>'dto','error_attr'=>'errors'])] //This is how you attribute request
    #[PHA\Producer('application/json', 'Json')] //This is how you produce response body from returned value
    public function handlePost(ServerRequestInterface $request): \My\DTO
    {
        $errors = $request->getAttribute('errors');
        if (!empty($errors))
        {
            //This is how you can return non-200 responses
            throw new Exception\UnprocessableEntity($errors);
        }
        /* @var \My\DTO $dto */
        $dto = $request->getAttribute('dto');
        return $dto;
    }
}

Finally, you need to configure special factory for router service. Here is a sample configuration for Laminas Service Manager (example is in YAML just for readability):

dependencies:
  factories:
    Mezzio\Router\RouterInterface: Articus\PathHandler\RouteInjectionFactory
    Articus\PathHandler\MetadataProviderInterface: Articus\PathHandler\MetadataProvider\Factory\PhpAttribute
    Articus\PathHandler\Handler\PluginManager: [Articus\PluginManager\Factory\Laminas, Articus\PathHandler\Handler\PluginManager]
    Articus\PathHandler\Consumer\PluginManager: Articus\PathHandler\Consumer\Factory\PluginManager
    Articus\PathHandler\Attribute\PluginManager: Articus\PathHandler\Attribute\Factory\PluginManager
    Articus\PathHandler\Producer\PluginManager: Articus\PathHandler\Producer\Factory\PluginManager

Articus\PathHandler\RouteInjectionFactory:
  paths:
    '':
    # List of your handlers   
    - My\Handler
# Configuration for handler plugin manager - sub-container dedicated for handlers
Articus\PathHandler\Handler\PluginManager:
  factories:
    My\Handler: My\HandlerFactory

For more details check documentation.

Enjoy!

I hope this library will be useful for someone except me. It is used for production purposes, but it lacks lots of refinement, especially in terms of tests and documentation.

If you have any suggestions, advices, questions or fixes feel free to submit issue or pull request.

pathhandler's People

Contributors

articus avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

moln

pathhandler's Issues

Extend super class in Handlers and DTOs in junction with openapi-generator/php-ze-ph

Hi Articus,

I know that might be not correct place for that question, however since you promote PathHandler in junction with OpenAPI generator, I woul like to place it.

Is there any possibility to tell php-ze-ph plugin to generate Hander and DTOs, which extend another super class? For Handler like:

/**
 * @PHA\Route(pattern="/example_item/{byId}")
 */
class ExampleItemById extends AbstractHandler {
   // ...
}

Or for DTOs:

use Articus\DataTransfer\Annotation as DTA;

/**
 */
class ExampleItem extends AbstractDTO
{
  // ...
}

Thanks to #2, I know now, that that I can use Attributing to add something to Request object, but I would like also to use inheritance in this case. Is this possible? An answer would please me a lot!

OAuth2 advice

Hi there,

I really like this library and have used it many times in combination with Swagger.

Now I have to create a public api with authentication for certain endpoints. Normally in Zend Expressive I put a extra Middleware to the specific route but with PathHandler I cannot implement this. Can you give me some advice to implement this with PathHandler?

For example I want to put a Middleware to validate the tokens for a specific endpoints: /products/ .

How to get path parameter inside a Handler

Hello Articus,

I am using PathHandler with OpenAPI generator and have created some Handlers to handle paths with paramaters, but not in query. Example:

/**
 * @PHA\Route(pattern="/country/{byId}")
 */
class CountryById
{
    /**
     * Get country by id
     * @PHA\Get()
     * @PHA\Producer(name=PHProducer\Transfer::class, mediaType="application/json")
     * @param ServerRequestInterface $request
     * @return \App\DTO\Country
     */
    public function getCountry(ServerRequestInterface $request): \App\DTO\Country
    {
       // How to get byId parameter from path herein ?
    }
}

There is very good example from you how to get provided query parameters via an extra class. But how can I get parameter byId from path?

Would be great to have an example. I am a beginner in Zend Expressive.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.