Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

callable utils #1

Open
schnittstabil opened this issue Jan 17, 2017 · 6 comments
Open

callable utils #1

schnittstabil opened this issue Jan 17, 2017 · 6 comments

Comments

@schnittstabil
Copy link
Member

schnittstabil commented Jan 17, 2017

I'm planning to create 4 middleware related projects, allowing clients to additional deal with callable middlewares:

  1. middleware/is-delegate
  2. middleware/is-middleware
  3. middleware/to-delegate, casting/adapting DelegateInterface instances and callable delegates to DelegateInterface instances.
  4. middleware/to-middleware, casting/adapting MiddlewareInterface instances and callable delegates to MiddlewareInterface instances.

I'm always shilly shally about project names. For example:

  • is-delegatable sounds better, but
  • is-middlewarable may sounds weird, or doesn't it?

@middlewares/contributors Thoughts are welcome.

@oscarotero
Copy link
Member

I'm not sure if this is a good idea because I see the use of callable as a feature implementation.
For example, I have this middleware dispatcher with some features like support of callables, container-interop, nested middlewares, etc... IMHO, the support of callables is another feature, not special or more important than others, due the ability to instantiate anonimous classes in php7, opening a new way to do the same, but safety (and better). I just use closures when I'm too lazy to respect the psr-15 interface signature :D

@schnittstabil
Copy link
Member Author

schnittstabil commented Jan 17, 2017

I see the use of callable as a feature implementation.

That is exactly its purpose. It allows middleware dispatchers to easily implement a callable feature, thus they do not need to reinvent the wheel. In addition, consumers of middleware dispatchers which do not provide a callable feature, can easily reuse their already existing closures.

And more importantly, they do not have to test that feature…

@oscarotero
Copy link
Member

Yes but I mean that you're using a 1:1 convert. This callable works:

$callable = function (ServerRequestInterface $request, DelegateInterface $delegate) {
    return $delegate->process($request);
}

but a more lazy typed callable doesn't:

$callable = function ($request, $delegate) {
    return $delegate->process($request);
}

And for me, it's more confortable use callables to create lazy middlewares, for testing purposes or for minor operations, because if I need strong typing, I can do this:

$middleware = new class () implements MiddlewareInterface
{
    public function (ServerRequestInterface $request, DelegateInterface $delegate) {
        return $delegate->process($request);
    }
}

That it's faster than callables (because there's no need to create wrappers or use Reflections). Of course, this only works in php7, but I think is the primary focus.

@schnittstabil
Copy link
Member Author

I understand your point of view. But, for example the is_middleware may look like that:

function is_middleware($var, bool $strict)
{
    /* short circuit for interface implementers */
    if ($var instanceof MiddlewareInterface) {
        return true;
    }

    if (! is_callable($var)) {
        return false;
    }

    if (! $strict) {
        return true;
    }

    // use reflection
    …
}

If we think about middleware frameworks, then I can imagine a usage like this:

class App
{
    public function get(string $route, $middleware)
    {
        $middleware = to_middleware($middleware, $this->debug); // throw an exception in case of non-middleware
        …
    }
    …
}

This means we can type-check early:

$app = new \App([
   'debug' => true,
]);

// this uses reflection:
$app->get('/hello/{name}', function (ServerRequestInterface $request, DelegateInterface $delegate) {
    …
});

// this doesn't uses reflection:
$app->get('/hello/{name}', new ContactMiddleware());

$app->run();

Well, that all depends on the features a concrete framework wants to provide. If you feel that this does not fit to http://github.com/middlewares, then I will create it at http://github.com/schnittstabil – that wouldn't be a tragedy 😉

@oscarotero
Copy link
Member

I think this organization should focus mostly in creating psr-15 middleware packages that everybody can consume, instead packages for frameworks or other implementations. For this kind of utilities, we have a middlewares/utils package, so if you like, you can add this feature as a static class. For example:

use Middlewares\Utils\CallableValidator;

$valid = CallableValidator::isMiddleware($callable);

As you can see, there's a CallableMiddleware, a Dispatcher and a Delegate, so you can reuse this classes to create the toDelegate and toMiddleware functions.

@schnittstabil
Copy link
Member Author

👍 middlewares/utils seems the right place to provide such features.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants