All Projects → krzysztof-magosa → saffron-php

krzysztof-magosa / saffron-php

Licence: Apache-2.0 License
High performance PHP router

Programming Languages

PHP
23972 projects - #3 most used programming language

Labels

Projects that are alternatives of or similar to saffron-php

TutoAsus
Tutorial on how to setup a nginx reverse proxy on Asus router with Merlin firmware, and get Let's Encrypt certificate with acme.sh.
Stars: ✭ 35 (-5.41%)
Mutual labels:  router
backbone.base-router
A better starting point for building a new Backbone Router.
Stars: ✭ 49 (+32.43%)
Mutual labels:  router
http-connection-lifecycle
Complete and detailed explanation of HTTP connection lifecycle
Stars: ✭ 43 (+16.22%)
Mutual labels:  router
dodgr
Distances on Directed Graphs in R
Stars: ✭ 106 (+186.49%)
Mutual labels:  router
ROS Scripts
Scripts for RouterOS (MikroTik devices)
Stars: ✭ 81 (+118.92%)
Mutual labels:  router
routedux
A router that maps urls to redux actions and vice-versa
Stars: ✭ 19 (-48.65%)
Mutual labels:  router
whip
Simple fast http server for nim based on httpbeast and nest for high performance routing
Stars: ✭ 55 (+48.65%)
Mutual labels:  router
networking-icons
Repo containing various networking icons including routers, switches, servers, firewalls, load balancers and more. Icons are provided in png and svg formats.
Stars: ✭ 61 (+64.86%)
Mutual labels:  router
TG799VAC-XTREME-17.2-MINT
My personal unique wiki for hacking the router firmware used by (Telia)TG799vac Xtream v17.2-MINT delivered from Technicolor
Stars: ✭ 71 (+91.89%)
Mutual labels:  router
pi-ap
Raspberry Pi Access Point: This repo automates the configuration of hostapd, dnsmasq, dhcpcd & wpa_supplicant to transform a Pi into a wireless AP. Requirements: a Pi, an Ethernet cable and a DHCP-enabled port on a router with a 'net connection or a switch connected to this router.
Stars: ✭ 69 (+86.49%)
Mutual labels:  router
VueStudy
Vue.js学习系列示例代码及教程
Stars: ✭ 80 (+116.22%)
Mutual labels:  router
gatsby-plugin-dynamic-routes
Creating dynamic routes based on your environment and/or renaming existing routes
Stars: ✭ 14 (-62.16%)
Mutual labels:  router
crizmas-mvc
raulsebastianmihaila.github.io/crizmas-mvc-docs/
Stars: ✭ 12 (-67.57%)
Mutual labels:  router
froute
Type safe and flexible router for React
Stars: ✭ 31 (-16.22%)
Mutual labels:  router
browser
Routing and Navigation for browser apps
Stars: ✭ 31 (-16.22%)
Mutual labels:  router
nuxt-interpolation
Nuxt.js module as directive for binding every link to catch the click event, and if it's a relative link router will push.
Stars: ✭ 38 (+2.7%)
Mutual labels:  router
oas2
OpenAPI 2.0 (aka Swagger) utils for Golang.
Stars: ✭ 19 (-48.65%)
Mutual labels:  router
egg-router
router for eggjs, fork from koa-router with some additional features
Stars: ✭ 50 (+35.14%)
Mutual labels:  router
router
Router is a request matcher and URL generator
Stars: ✭ 38 (+2.7%)
Mutual labels:  router
NoCRouter
RTL Network-on-Chip Router Design in SystemVerilog by Andrea Galimberti, Filippo Testa and Alberto Zeni
Stars: ✭ 39 (+5.41%)
Mutual labels:  router

Saffron PHP Router

Build Status Scrutinizer Code Quality Coverage Status

What is Saffron?

Saffron is very fast and flexible PHP router for your application.

Version

I no longer develop software in PHP so I do not actively support this project. Recently due to contribution project has been updated to be sure it works with PHP 7.x. The newest tag supporting older PHP versions (and also HHVM) is 5.3. If you still use this project - contributions are welcome.

Features

  • No external dependencies
  • High performance
  • Method condition support
  • Domain condition support
  • Https/non-https condition support
  • Routes with optional parameters
  • Requirements for parameters
  • Reverse routing
  • Well tested, 100% of test coverage

Installation

You can easily install Saffron by adding below requirement to your composer.json

{
    "require": {
        "krzysztof-magosa/saffron": "5.*"
    }
}

How to use

You need to use RouterFactory to create instance of Router. Constructor of RouterFactory accepts one parameter, Closure which configures routes. Closure gets RoutesCollection in the first parameter. Closure is fired only once, then everything is stored in compiled file.

use KM\Saffron\RouterFactory;

$factory = new RouterFactory(
    function ($collection) {
        // configuration of routes goes here...
        $collection->route('home')
            ->setUri('/')
            ->setTarget('HomeController');
    }
);

By default Saffron stores cache in system temporary directory. To avoid collisions between projects you are encouraged to set separate cache directories in each project hosted on the same server. If you really need to use one directory for more projects you can set class suffix.

$factory
    ->setCacheDir(__DIR__ . '/cache')
    ->setClassSuffix('MyProject')
    ->build();

When you have configured RouterFactory, you can build Router instance by calling build() method.

$router = $factory->build();

Configuring routes

use KM\Saffron\RouterFactory;

$factory = new RouterFactory(
    function ($collection) {
        $collection->route('home')
            ->setUri('/')
            ->setTarget('HomeController');
            
        $collection->route('contact')
            ->setUri('/contact')
            //...
            ->setTarget('ContactController');
            
        //...
    }
);

To add Route you need to call method route() on $collection, giving route name as the first parameter. Method returns Route instance and then you can set parameters on it. You can create as many routes as you want, but each one needs to have unique name.

Setting target

To execute controller after matching particular route you need to use setTarget() method. First parameter is class name of controller, second is method name. If you omit second parameter it will default to 'indexAction'.

$collection->route('home')
    ->setTarget('HomeController');

$collection->route('team')
    ->setTarget('TeamController', 'actionName');

Setting uri

To match request against uri you need to call method setUri() on Route instance. It takes only one parameter, expected uri.

$collection->route('contact')
    ->setUri('/contact');

Setting domain

To match request against domain you need to call method setDomain() on Route instance. It takes only one parameter, expected domain.

$collection->route('contact')
    ->setDomain('www.example.com');

Setting method

To match request against method you need to call method setMethod() on Route instance. You can pass one method as a string, or more using array.

$collection->route('api1')
    ->setMethod('GET');

$collection->route('api2')
    ->setMethod(['GET', 'POST']);

Setting https

You may want to allow access to some resources only via encrypted or unencrypted connection. It can be done using setHttps() method. Pass true to this method if you want only encrypted traffic, false if unecrypted. Null means that it doesn't matter (it's the default setting).

$collection->route('secret')
    ->setHttps(true);
    
$collection->route('public')
    ->setHttps(false);

Using placeholders

If your uri or domain contains variable parts, you can catch them using placeholders. Placeholders are defined using curly braces.

$collection->route('contact')
    ->setUri('/contact/{name}')
    ->setDomain('{lang}.example.com');

This example allows you to use links like:

Sometimes you want to allow user to omit some placeholders in the link. You can use setDefaults() method to achieve this.

$collection->route('contact')
    ->setUri('/contact/{name}')
    ->setDomain('{lang}.example.com')
    ->setDefaults(
        [
            'name' => 'webmaster',
            'lang' => 'english',
        ]
    );

Now user can go into link http://example.com/contact, and lang will be 'english', and name will be 'webmaster'.

You can also set requirements for placeholders, to allow user only to use some values there. Requirements are build using regular expressions, the same which you use in the preg_match().

$collection->route('contact')
    ->setUri('/contact/{name}')
    ->setDomain('{lang}.example.com')
    ->setDefaults(
        [
            'name' => 'webmaster',
            'lang' => 'english',
        ]
    )
    ->setRequirements(
        [
            'name' => '\w+',
            'lang' => 'english|spanish|french',
        ]
    );

Matching requests

Saffron accepts Request object. In typical configurations you can use createFromGlobals() static method. It was tested on Apache server with mod_php.

use KM\Saffron\Request;
$request = Request::createFromGlobals();

If your configuration isn't typical, you can create this object manually.

use KM\Saffron\Request;
$request = new Request();
$request
    ->setUri($uri)
    ->setDomain($domain)
    ->setMethod($method)
    ->setHttps($https);

Now you can pass this object to Router match() method which returns RoutingResult object.

$result = $router->match($request);

You can check whether matching was successful using isSuccessful() method. To check why matching was not successful you need to use two methods: isResourceNotFound() and isMethodNotAllowed(). When isResourceNotFound() returns true you should display error 404 to user, when isMethodNotAllowed() returns true you should display error 405. RFC 2616 requires to set Allow header containing allowed methods in case of displaying 405 error. You can get this list by calling getAllowedMethods(). Remembet that Saffron is not framework, but just router, so it's up to you to do that.

Building links

Saffron is two-directional router, so in addition to matching requests you can also build links. Router has method assemble() for building links.

// Building uri
$uri = $router->assemble('routeName', ['parameter1' => 'value1']);

// Building entire link (scheme + domain + uri)
$link = $router->assemble('routeName', ['parameter1' => 'value1'], true);

Executing controllers

After successful matching of request you can fire controller specified in the route using Executor.

use KM\Saffron\Executor;
$executor = new Executor($result);
$executor->fire();

In some cases there is need to do something with controller just before or/and just after executing action. It can be done by using setPreDispatch() and setPostDispatch().

use KM\Saffron\Executor;
$executor = new Executor($result);
$executor
    ->setPreDispatch(
        function ($controller, $method, $parameters) {
            // do something before calling action
        }
    )
    ->setPostDispatch(
        function ($controller, $method, $parameters) {
            // do something after calling action
        }
    );

$executor->fire();

In some cases (for example firing error controller) you may want to fire controller which doesn't come from matched route. Executor also supports such situation.

$executor = new Executor();
$executor
    ->setController('YourController')
    ->setMethod('methodName')
    ->setParameters(['param1' => 'value1'])
    ->fire();

Getting parameters

If your uri or domain containts placeholders they will be passed to your controller in arguments to method. You just need to ensure that controller method has arguments with the same names as your placeholders. You don't have to catch all placeholders.

class Controller
{
    public function method($lang, $name)
    {
    }
}
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].