Coder Social home page Coder Social logo

elmer's Introduction

#Elmer Build Status

Weniger, aber besser โ€” Dieter Rams

Elmer is a simple and flexible web routing framework for PHP.

Getting Started

<?php

use Elmer\Environment;
use Elmer\Response;
use Elmer\Routes;

require '../vendor/autoload.php';

$app = new Routes(function($app) {
	$app->get('/', function($env) {
		return new Response(200, 'Hello, world!');
	}
});

$response = $app(Environment::initFromGlobals());
$response->send();

This is all it takes to create an application that says 'Hello, world' when a user navigates their browser to the root of your site.

Methods

We assigned a new route to our application by calling the get method on our application instance. The method refers to the HTTP method and we can respond to any HTTP method by changing the method that we call on our application:

<?php
$app->post();
$app->delete();
$app->brew(); // Custom methods are supported

Route Parameters

URIs may contain parameters. A parameter starts with a semicolon and is followed by the type of parameter:

<?php
$app->get('/users/:int', function($app, $id) {
	return "You are user #$id";
});

This route will match /users followed by any digit, eg. /users/21.

You may use the following parameters:

:any // Anything (alpha, num, underscore, or dash)
:int // Any integer
:alpha // Any alphabetic character
:alphanum // Any alphanumeric character
:year // 4 digits
:month // 1 - 12
:day // 1 - 31

You can add custom parameters by modifying the patterns property of your application instance like so:

<?php
$app->patterns['names'] = '(peter|simon|john)';

You may also write your own custom regex inline. Be sure to wrap it in parenthesis so it is counted as a matched section.

Optional Parameters

Parts of a URI can be marked as optional by appending a question mark:

<?php
$app->get('/articles/:year?', function($app, $year = 2012) { .. });

This route will match the request /articles, as well as /articles/2011.

Don't forget to set a default value for optional parameters!

Responses

TODO

Filters

Filters 'wrap' around routes so that you can add additional functionality to your application, such as logging and authentication.

A filter looks like this:

<?php
$app->filter(function($app, $route)) {
	$response = $route();
	$response['body'] .= 'Bar';
	
	return $response;
}

$app->get('/', function() {
	return 'Foo';
}

The filter above appends 'Bar' to the response so the final result would be FooBar. The route is passed to the filter, which is responsible for continuing the execution of the application by calling the route closure. This allows code to be run before/after, modify the response, or skip calling the route altogether.

Filters can be used for a range of tasks, such as authentication or logging, the limit is your imagination!

Filters are inspired by middleware for Ruby's Rack and Python's WSGI

Multiple filters

You may use as many filters as you like.

Groups

Groups enable you to apply a filter to a limited subset of routes. To define a group all you need to do is wrap several routes in the following:

<?php
$app->group(function($app) {
	
	// Declare filters here
	// Declare routes here
}

Now any filters that are declared within the above group will only be applied to routes declared in that same group.

You may nest groups if you like. Filters apply to sub-groups, but a filter in a sub-group will not be applied to routes in the parent group. For example:

<?php
$app->group(function($app) {
	$app->filter(function($route) { .. }); // Filter A
	$app->get('/foo', function() { .. });
	
	$app->group(function($app) {
		$app->filter($route) { .. }); // Filter B
		$app->get('/bar', function() { .. });
	});
});

In the above code sample Filter A applies for both routes /foo and /bar. Filter B only applies to the route /foo.

Prefixing routes

You can apply a prefix to a group of routes by passing in the URI prefix as the first parameter of the group decleration.

<?php
$app->group('/user', function($app) {
	$app->get('/profile', function() { .. });
}

The above route will match the request GET /user/profile.

elmer's People

Contributors

peterhorne avatar

Stargazers

Philip J Anders avatar Paul Dufour avatar Wing Lian avatar Mohamed E. avatar

Watchers

 avatar

Forkers

conyum

elmer's Issues

Redirect method in Elmer\Response

Something like:

<?php
$response = new Elmer\Response;
$response->redirect('/foo');

Should auto add scheme + host + script as a prefix... need to figure a way to make this information available to the response object. Ideally without having to pass in the request object as a dependency.

Filters wrap in the wrong order

<?php

$app->filter(function($route) {
    echo 'Called first';
    return $route();
});

$app->filter(function($route) {
    echo 'Called second';
    return $route();
});


$app->get('/', function() {
    return 'I am the route';
});

Output should be:

Called first
Called second
I am the route

Actual output is:

Called second
Called first
I am the route

Use _method to add support for HTML forms

HTML forms are typically limited to GET or POST. Use the rails convention of a hidden parameter '_method' with the actual method to be used so that users can overcome the limitations of HTML forms.

Implement Environment

Introducing functionality based on Rack for Ruby will mean that the Request class should be re-factored into an Environment class.

Variety of response classes (Json, Csv, etc.)

If the user sets body to an array instead of a string (via __constructor, or $response['body']) then the array should be converted to a json string and the appropriate headers should be set.

Rename filters to decorators

They are an implementation of the decorator pattern and so it makes sense to reuse a standard term rather than inventing a new one!

Using regexes in parts of URIs

Support for the following would be great:

<?php
$app->get('/data/(:id).json', function() { .. });

Alternatively, adding support for file extensions so the user can write:

<?php
$app->get('/data/:id.json', function() { .. });

Second option looks like the best one at the moment? Also, we could then expose the file extension in the request object?

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.