Giter VIP home page Giter VIP logo

route's Introduction

Route

Author Latest Version Software License Build Status Coverage Status Quality Score Total Downloads

This package is compliant with PSR-1, PSR-2, PSR-4, PSR-7, PSR-11 and PSR-15. If you notice compliance oversights, please send a patch via pull request.

Install

Via Composer

$ composer require league/route

Requirements

The following versions of PHP are supported by this version.

  • PHP 7.2
  • PHP 7.3
  • PHP 7.4
  • PHP 8.0

Documentation

Route has full documentation, powered by Jekyll.

Contribute to this documentation in the docs directory.

Testing

$ vendor/bin/phpunit

Contributing

Please see CONTRIBUTING for details.

Credits

License

The MIT License (MIT). Please see License File for more information.

route's People

Contributors

aag avatar abacaphiliac avatar aujicini avatar craig-davis avatar delboy1978uk avatar exagone313 avatar frankgiesecke avatar grahamcampbell avatar hannesvdvreken avatar jamesdb avatar jasoneleventeen avatar josevieirame avatar jrushlow avatar kamalkhan avatar localheinz avatar mattfawcett avatar mclotos avatar merlindiavova avatar mike42 avatar pgk avatar philipobenito avatar philsturgeon avatar pine3ree avatar pwaring avatar shadowhand avatar shrink avatar sjokkateer avatar tomasvotruba avatar tpavlek avatar willemwollebrants avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

route's Issues

Misleading Exception Message v2

When registering a controller action and supplying an invalid method an exception is thrown as follows:

Catchable fatal error: Argument 1 passed to League\Route\Strategy\JsonStrategy::dispatch() must be callable, array given, called in <snip>/src/Route.php on line 79 and defined in <snip>vendor/league/route/src/Strategy/JsonStrategy.php on line 16

This occurs regardless of Strategy used.

A more descriptive exception needs to be thrown which more accurately describes that the method is invalid.

Question/Poll: Should we bump to v3 for per route and per group middleware?

So, I've been looking at bringing in a PSR-7 middleware implementation, the front runner is Relay at the moment. With version two though I feel I've made a glaring mistake with the JsonStrategy in not passing the response object off to the controller.

What I'd like to do is bump to version 3 and implement in a way that I'd be happy with, allowing per route and per group middleware on any strategy. As things stand, because of the issue with the JsonStrategy I would probably have to provide a new middleware specific strategy to keep BC.

I suppose one of the benefits of bumping to v3 now is that the install base for v2 is still quite small so support would only have to be provided for a small amount of time rather than waiting and having to support it for much longer, and it would be a relatively simply upgrade guide.

Thoughts? @hannesvdvreken @localheinz @kayladnls

Default route arguments?

Given I have a route /play/{someusername} and I want the someusername to be optional, is there a supported way of doing this - I'm currently using the Request Response strategy, and the route is just left unmatched when I make a request against /play without any arguments.

Setting a custom Dispatcher

As we can set custom strategies. It might be a good implementation in setting a custom dispatcher or try to interface it. So it will possible to do what in this issue #25 has stated. I'm working on adapters in which I can replace route components with ease without rewriting code every time.

Composer install issue:

When I run composer require league/route I get the following:

  Problem 1
    - Conclusion: don't install league/route 1.1.0
    - don't install league/route 1.0.x-dev|install league/route dev-master
    - Conclusion: don't install league/route dev-master
    - Conclusion: don't install league/route 1.0.1
    - Installation request for league/route ~1.0@dev -> satisfiable by league/route[1.0.0, 1.0.1, 1.1.0, 1.0.x-dev].
    - Conclusion: remove nikic/fast-route v0.2.0
    - league/route 1.0.0 requires nikic/fast-route ~0.3 -> satisfiable by nikic/fast-route[v0.3.0, v0.4.0].
    - Can only install one of: nikic/fast-route[v0.3.0, v0.2.0].
    - Can only install one of: nikic/fast-route[v0.4.0, v0.2.0].
    - Installation request for nikic/fast-route == 0.2.0.0 -> satisfiable by nikic/fast-route[v0.2.0].

Thoughts?

Nested Routes in 2.0

Have you considered adding this feature? If it's something that you'd like to see added I could start working on a PR. I know it would be helpful for the work we're doing.

Container

This package could not use the most current version of the league container?

tks

Best way for authentication

Hi,

What would be the best way to implement authentication to specified pages?

Currently I handle the authentication in the Controllers, but it would be nice if I could give a authentication 'flag' to a route (I think this is possible with middleware in Symfony routing?).

Is there already a build in way to do this? And if not, is this possible to do this with custom strategies? Or is there a better way to accomplish this?

Thanks in advance!

Can't access the container in Controllers

I was playing with this package and I found imposible to do it ... Is that intentional? if so ... why? I can't understand the disadvantage of having access to the service container inside a Controller.

I end up doing it overriding AbstractStrategy::invokeController as in here but IMHO it should be accesible.

Thanks in advance and great package!!!

Can't dispatch more than once on same RouteCollection

This is regarding the develop branch

When I try to dispatch more than once on the same RouteCollection instance, I get the following exception:

FastRoute\BadRouteException: Cannot register two routes matching "/" for method "GET" in /home/ubuntu/workspace/vendor/nikic/fast-route/src/DataGenerator/RegexBasedAbstract.php on line 55

If it's not intended to do so, this behaviour should probably be documented.

I can probably work around this with a factory of some sorts, but it would be neat if it was supported.

Minimal testcase:

use League\Route\RouteCollection;
use Zend\Diactoros\Response;
use Zend\Diactoros\ServerRequest;
use Zend\Diactoros\Uri;

$routes = new RouteCollection();
$routes->get('/', function() { return 'foo'; });

$routes->dispatch((new ServerRequest())->withUri(new Uri('/')), new Response());

$routes->dispatch((new ServerRequest())->withUri(new Uri('/')), new Response());

Handling trailing slashes by default

By default, trailing slashes are not handled - can this be IN by default please?

Example:
/page and /page/ should both be OK if only /page was added in RouteCollection

Catch all route

Is there a way to add a catch all route that deals with every request that doesn't match one of the other specified routes.

Something like this:

$router->addRoute(
    'GET', '/foo',
    function(Request $request, Response $response)
    {
        // handles GET /foo
    }
);

$router->addCatchAllRoute(function(Request $request, Response $response)
{
    // handles everything else, e.g. POST /foo
});

Better implementation of route parameters for RequestResponseStrategy

The Request object from Symfony has a built-in property (attributes) for parameters from the route:
http://api.symfony.com/2.6/Symfony/Component/HttpFoundation/Request.html#createFromGlobals%28%29

The RequestResponseStrategy would have to be modified like this:

    $request = $this->getContainer()->get('Symfony\Component\HttpFoundation\Request');
    $request->attributes->add($vars);
    $response = $this->invokeController($controller, [
            $request,
            $this->getContainer()->get('Symfony\Component\HttpFoundation\Response')
      ]);

What are your thoughts on this? I can do a pull request later for this if you want.

league/pipeline integration

I'd like to see some integration with pipeline for modifying Response objects to assist with the purposes of (but not limited to)

  • Perhaps using Intervention for on-the-fly WebP encoding
  • Auto-adding headers (HSTS, X-Frame-Options, CORS etc.)
  • Handling PSR-7 Response objects
  • Using hooking into external or PHP-based compilers for less/sass/es6 etc.

Not suggesting that those be baked in, but if league/pipeline were to be integrated, those are the examples I'd like to see (except maybe that last one, I've yet to find a PHP-based less compiler that's fully feature matching).

Cached Routes?

FastRoute already have it inbuilt, so why not league/route as well :)

Build request object within dispatcher if not already defined in container

In RequestResponseStrategy.php, when Symfony\Component\HttpFoundation\Request is fetched from the League Container, if it is not already set in the container then it will initiate a largely useless Request object that contains none of the globals that HttpFoundation Request is normally initiated with.

I am not extremely familiar with Dependency Injection so I don't know what the ideal fix for this is in this package. When using Route in a project you can make a Service Provider for HttpFoundation or set it with $container->add('Symfony\Component\HttpFoundation\Request', Request::createFromGlobals());, but it was quite unexpected to have to do so.

[League/Route] - Request Object inside Controller (using Class Methods) is empty?

Hi,
I have this code setup, I'm using symfony http request, but for routing/dispatching I'm using League/Route for a change..
I note something:
in the controller method (example below quoted), the $request object is empty - is this normal? Because I would expect that the initial $request object obtain (Request::createFromGlobals()) should have been reflected to Request in: public function action (Request $request, Response $response)
But this does not seem the case and the parameter being there is not having any use - defeating the purpose.

I am surely missing something here, anyone can help?

use Symfony\Component\HttpFoundation\Request; 
use Symfony\Component\HttpFoundation\Response; 

class MyController 
{ 
    public function action (Request $request, Response $response) 
    { 
        print_r($request); // everything is empty including paramter bag for a POST !!
    } 
}

Route prefixes/prehandlers

Not so much of an issue as a question.

Is it possible to implement the following like laravel:

Route::group(['domain' => $domain, 'prefix' => 'version1'], function() {});

I was thinking strategies might help with this, but i'm not 100% sure how to. Any advice on where to look would be great!

Thanks.

How exactly do I use League\Container\Container w/ this lib?

So I noticed in the docs it says you can set a custom container and pass it to the constructor of the route collection. There's no way to actually access the container from the route collection class though?

So what exactly is the point in passing a new container to the routecollection class? Maybe there's some confusion because the docs are vague on the usage and I can't seem to find anything anywhere questioning it.

Route doesn't allow an array callable (eg.: [$obj, 'method'])

Simple example of this not working:

$test = new Test();
$router = new League\Route\RouteCollection;
$router->addRoute('GET', '/', [$test, 'index']);

$request    = Request::createFromGlobals();
$dispatcher = $router->getDispatcher();

try {
    $response   = $dispatcher->dispatch($request->getMethod(), $request->getPathInfo());
    $response->send();
} catch(Exception $e) {
    echo $e->getMessage();
}

class Test
{
    public function index(Request $req, Response $resp) 
    {
        $resp->setContent("Testing");
        return $resp;
    }
}

Errors:

Warning: Illegal offset type in /var/www/source/vendor/league/route/src/RouteCollection.php on line 84

Warning: Illegal offset type in /var/www/source/vendor/league/route/src/RouteCollection.php on line 84

Warning: Illegal offset type in /var/www/source/vendor/league/route/src/Dispatcher.php on line 69

Warning: Illegal offset type in /var/www/source/vendor/league/route/src/Dispatcher.php on line 70

Catchable fatal error: Argument 2 passed to League\Route\Dispatcher::handleFound() must implement interface League\Route\Strategy\StrategyInterface, null given, called in /var/www/source/vendor/league/route/src/Dispatcher.php on line 73 and defined in /var/www/source/vendor/league/route/src/Dispatcher.php on line 85

Doing the following works as expected though:

$router->addRoute('GET', '/', 'test::index');

Both ways are valid callables, so this not working is weird.

league/container 2.x dependency version conflict

I added league/container:^2.0 as a dependency to my project on its own, then attempted to add league/route as well (simply via composer require league/route), and I receive a conflict due to Route requiring league/container:~1.0.

I can eliminate the Container requirement so it will fall back to 1.0 resolution, but that's not ideal as I'd like to use the latest version of these packages. I know that Route 2.0 is around the corner sometime (and my project is slow moving, so I don't really care about fixing this immediately). Just figured I'd give you a heads up.

As someone who is starting to put individual components together to try and build an ideal "framework" for my projects, I'm happy to put some of these components through their paces and provide feedback and use where necessary, if I can be of any help.

Cheers ๐Ÿ˜Ž

.htaccess guide

I am having a problem setting this up as there is no documentation of the location of the .htaccess in a project and data that should be in the .htaccess file

Request alias is not identified in the container with RestfulStrategy

I am using league/container in my project and have this code to set up my container:

$container->add('Router', function () use ($container) {
    $router = new RouteCollection($container);
    $router->setStrategy(new RestfulStrategy);
    // ... list of routes
    return $router;
});

And then this code to dispatch the request:

$router     = $container->get('Router');
$request    = $container->get('Request');
$dispatcher = $router->getDispatcher();
$response   = $dispatcher->dispatch($request->getMethod(), $request->getPathInfo());

The problem is that when my controllers are called with action($request) the request is a new instance and not the request that was used to dispatch. I would suggest adding a method to RestfulStrategy that would allow the request name to be set:

public function setRequest($request) { ... }
public function getRequest() { ... }

public function dispatch($controller, array $vars)
{
    // ...
    $request = $this->getRequest() ?: $this->getContainer()->get(...);
    // ...
}

This would allow me to do the following, without having to use a FQCN in my container:

$container->set('DispatchStrategy', RestfulStrategy::class)
    ->withMethodCall('setRequest', ['Request']);

Support container-interop

Currently route requires league/container, however, it would be beneficial to support the container-interop project as to not create a hard dependency on the league/container project itself. I for one would prefer to utilize a supporting container-interop project instead in some cases. I believe that is a planned feature for league/container but ideally it would happen with v2 of container and the dependency would be lifted in v2 of route.

Pass a route configuration file

Hi,

I have been using your fastroute extension and am enjoying it very much.

I was wondering if you would be interested in a Pull Request which adds a method to pass a configuration array?

    /**
     * Add a collection of routes from a configuration
     * array
     *
     * @param  array $routes
     * @param  \League\Route\Strategy\StrategyInterface $strategy
     * @throws \League\Route\Exception\EmptyRoutingPassedException
     * @throws \League\Route\Exception\MalformedRouteConfigurationException
     */
    public function addRoutesFromConfig(
        array $routes = [],
        Strategy\StrategyInterface $strategy = null
    ) {
        // Check if the array is empty
        if (true === empty($routes)) {
            throw new EmptyRoutingPassedException;
        }

        // Loop through each modules routing data
        foreach ($routes as $module => $route) {
            foreach($route as $name => $body) {
                // Check configuration is passed correctly
                if (
                    false === isset($body['method'])
                    || false === isset($body['pattern'])
                    || false === isset($body['controller'])
                ) {
                    throw new MalformedRouteConfigurationException(
                        sprintf(
                            'The route [%s] in the [%s] section has not been configured correctly',
                            $name,
                            $module
                        )
                    );
                }

                $this->addRoute($body['method'], $body['pattern'], $body['controller'], $strategy);
            }
        }
    }

and then called like:

$routes = [
    'demo_page' => [
        'pattern'    => '/demo/{name}',
        'controller' => 'Demo\Controller\DemoController::index',
        'method'     => 'GET',
    ],
];


$router = new RouteCollection();
$router->setStrategy(new RequestResponseStrategy);
$router->addRoutesFromConfig($routes);

In terms of the exceptions, not sure if they are the best place for them as they are not Http exceptions but more argument exceptions?

Container dependency

As the code only passes the Container instance down the chain to a Strategy, which itself only uses the get method, it would make sense to not rely on a hard dependency of the League Container, and rather replace this dependency with a dependency on the Interop Container instead.

This would make the code much freer from having to use a container that developers may not be using, and increase uptake of the package.

Personally, I am a fan of Auryn Injector, and could very easily make a very simple bridge for Auryn to the package, if only it relied on the Interop Container instead of the League one.

I understand that a custom Strategy can be made that relieves the reliance, but still, an instance of a Container is still created and passed around that is not always required. Call me weird, but this just doesn't feel right to me.

Documentation v2

Hello!

I just started to use this library after a long search for the perfect router class/framework/library for my project(s). And with the additions in V2 I think this is the perfect class for my needs!

But I only miss the documentation for the second version, I am now developing with help of the code and the unit tests. But I am sure that I miss some nice features this way :)

Has someone already started with early version of the documentation?

Also I would like to help with the documentation if needed, just let me know and I will see if I can help!

Kind regards,

Matthijs

Enable file caching of route data via var_export

I was not a fan of Front Controller pattern in PHP, but I am trying to force myself to follow the movement of open source frameworks. So I think FastRoute\cachedDispatcher could reduce the overhead of dispatching process as much as possible (of course, I know this is a premature optimization). I wonder, does league's route support it? I cannot found any declaration of that class in the source code.

Question about the use of v2

First of all, thank you for sharing your amazing router!

I couldn't find any examples to use the v2, so I wonder if you can give me one.
Furthermore, PSR7 will be use?
What kind of PSR7 module do you recommend, if any?

I am in a hurry to use the next version in one of my project because the next version looks pretty better than the first release and I am searching a powerful router!

Thank you :)

Middleware like filters

In addition to strategies I would like to add middleware-like filters. A filter could be added to a filter collection of an route. A filter could be an invokable or callable. Filters are executed on dispatching a route. Filters are aware of request, response, route and passed dispatch vars.

PSR-7 support in 2.0

Is there any way to sneak PSR-7 diactoros default support in the 2.0.0 release? We can suggest the symfony bridge and the symfony/http-foundation to make it simple to support. If so, I'd be happy to do this work.

Named Routes

Hi, I'm not sure if this is implemented yet. Would be cool to have named routes.

[Feature Request] Nested route groups

Hi all,

I am trying v2 for my application. I really like the route groups, but I couldn't figure out a way to build nested route groups.

I tried to just simply nest it

$router = new RouteCollection($container);

$router->group('/admin', function($router) {

    $router->map(...);

    $router->group('/cms', function($router) {
        $router->map(...);
        $router->map(...);
    });

});

But I get the error (for the nested group):

Fatal error: Call to undefined method League\Route\RouteGroup::group()

So I think nested routing is not supported, is this possible to implement?

Separate different args with other characters than "/"

Is there a way to have more than one variable inside of one part of a url?

Something like this doesn't work for me:

$router->addPatternMatcher('wordStartsWithM', '(m|M)[a-zA-Z]+');
$router->addPatternMatcher('wordStartsWithQ', '(m|Q)[a-zA-Z]+');

$router->get('/test/{first:wordStartsWithM},{second:wordStartsWithQ}', function (Request $request, array $args) use ($mysqli) {
        return ["This is just for debug" => "true", "first" => $args['first'], "second" => $args['second']];
});

My code above generates the following result for me:

[[]]

But it 'seems' like the routing is working, partially... Am I doing it wrong?

Error while implementing Custom Strategy

First of all, thanks for this fantastic package.

I was trying to implement a login and sort of a middleware to filter unauthenticate route requests.

So I use the Custom Strategy mentioned in the documentation.

I am not sure what code to put in the dispatch method. But, when I copy the code of RequestResponseStrategy's dispatch method, it did not show any errors.

But, in one Post request route - this error showed up - "Warning: array_map(): An error occurred while invoking the map callback in vendor\league\container\src\Container.php on line 495"

I am in the dark what to do next in this case.

Can you help me out to replicate the functionality if there is no Strategy used at all for the RouteCollection - so that I can have the same code in CustomStrategy's dispatch method ?

Upgrade to latest version of Container

I don't believe withMethodCall is part of Container v1.0 (which is currently required for this component). A solution to this would be upgrading to the latest version of Container.

addRoute with array of methods

Hello

I would like to pass the method as array like this:

$router->addRoute(array('GET', 'POST'), '/', function (Request $request, Response $response) {
    // ...
});

Well this code is working but the documentation (and scrutinizer-ci) of the function addRoute
says that the datatype must be a string.

 * @param  string $method

But the internal call to the FastRoute addRoute function also accepts an array for $method.

* @param string|string[] $httpMethod

https://github.com/nikic/FastRoute/blob/master/src/RouteCollector.php

Would it be possible to fix the DocBlock for the parameter $method to this?

* @param string|string[] $method

Problem with original request

I am using @alexbilbie's Proton which uses this package for routing internally. My problem is that the original request object is not passed to the controller. When the dispatcher is called (with data originating from an already existing Request object), it creates a new Request which does not contain anything (not query params, etc).

I opened this issue here because I think it is rather an issue with routing than an issue with Proton itself. However, this still might occur because of improper use of router, so if this is a bug in Proton, I need some help to fix it.

Callable type hints

May I suggest the removal of the callable type hints in the development branch?

When I provide [ SomeClass::class, 'methodName' ] as a handler (implying that SomeClass be resolved from the DI container), multiple warnings are raised saying that methodName should not be invoked as a static method (because it isn't static). I can work around the warnings by prepending the @ to the map statement, but I don't think that's a decent solution.

Worse even, when I provide 'SomeClass::methodName' as handler (which should be legal), a fatal error is raised.

Stop requiring a container

There's no particular reason that league/container is a hard dependency, as it is only required when using the "Class Method" type of dispatching. Instead of being a required dependency, it should be suggested. This would make it possible to avoid using league/container completely for those of us that prefer a different DI implementation.

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.