Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
W
webbasics
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Taddeüs Kroes
webbasics
Commits
8c329e4c
Commit
8c329e4c
authored
Oct 06, 2012
by
Taddeus Kroes
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added RouteHandler functionaity to Router class
parent
1677e70b
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
116 additions
and
12 deletions
+116
-12
router.php
router.php
+67
-8
tests/test_router.php
tests/test_router.php
+49
-4
No files found.
router.php
View file @
8c329e4c
...
...
@@ -12,7 +12,7 @@ namespace webbasics;
require_once
'base.php'
;
/**
* A Router is used to call a handler
function
with corresponding to an URL.
* A Router is used to call a handler with corresponding to an URL.
*
* Simple example: a website with the pages 'home' and 'contact'.
* <code>
...
...
@@ -33,9 +33,10 @@ require_once 'base.php';
* </code>
*
* You can use regular expression patterns to specify an URL. Any matches are
* passed to the handler function
as parameters
:
* passed to the handler function
in a single parameter
:
* <code>
* function page($pagename) {
* function page(array $data) {
* $pagename = $data[0];
* return "This is the $pagename page.";
* }
*
...
...
@@ -46,6 +47,26 @@ require_once 'base.php';
* $response = $router->callHandler('/contact'); // 'This is the contact page.'
* </code>
*
* Instead of functions, you can implement the RouteHandler interface in a
* handler class. The router will create an instance of the handler class and call *handleRequest*
* <code>
* class MyHandler implements RouteHandler {
* function handleRequest(array $data) {
* $pagename = $data[0];
* return "This is the $pagename page.";
* }
* }
*
* $router = new Router(array(
* '/(home|contact)' => 'MyHandler'
* ));
* $response = $router->callHandler('/home'); // 'This is the home page.'
* $response = $router->callHandler('/contact'); // 'This is the contact page.'
* </code>
*
* The WebBasics library provides a set of base handler classes implementing
* the RouteHandler interface. These are sufficient for most usage cases.
*
* @package WebBasics
*/
class
Router
extends
Base
{
...
...
@@ -84,12 +105,25 @@ class Router extends Base {
* parentheses), the matches for these are passed to the handler function.
*
* @param string $pattern A regex pattern to mach URL's against.
* @param
mixed
$handler The handler function to call when $pattern is matched.
* @param
RouteHandler|callable
$handler The handler function to call when $pattern is matched.
* @throws \InvalidArgumentException If $handler is not callable.
*/
function
addRoute
(
$pattern
,
$handler
)
{
if
(
!
is_callable
(
$handler
))
throw
new
\InvalidArgumentException
(
sprintf
(
'Handler for patterns "%s" is not callable.'
,
$pattern
));
if
(
is_callable
(
$handler
))
{
$handler
=
array
(
'callable'
,
$handler
);
}
else
if
(
!
is_string
(
$handler
))
{
throw
new
\InvalidArgumentException
(
'Handler should be callable or class name.'
);
}
else
if
(
!
class_exists
(
$handler
))
{
throw
new
\InvalidArgumentException
(
sprintf
(
'Handler class "%s" does not exist.'
,
$handler
));
}
else
if
(
!
in_array
(
__NAMESPACE__
.
'\RouteHandler'
,
class_implements
(
$handler
)))
{
throw
new
\InvalidArgumentException
(
sprintf
(
'Handler class "%s" should implement the RouteHandler interface.'
,
$handler
));
}
else
{
$handler
=
array
(
'class'
,
$handler
);
}
$this
->
routes
[
self
::
DELIMITER
.
'^'
.
$pattern
.
'$'
.
self
::
DELIMITER
]
=
$handler
;
}
...
...
@@ -108,10 +142,19 @@ class Router extends Base {
* corresponding handler function otherwise.
*/
function
callHandler
(
$url
)
{
foreach
(
$this
->
routes
as
$pattern
=>
$
handler
)
{
foreach
(
$this
->
routes
as
$pattern
=>
$
tuple
)
{
if
(
preg_match
(
$pattern
,
$url
,
$matches
))
{
list
(
$type
,
$handler
)
=
$tuple
;
array_shift
(
$matches
);
$result
=
call_user_func_array
(
$handler
,
$matches
);
switch
(
$type
)
{
case
'callable'
:
$result
=
count
(
$matches
)
?
$handler
(
$matches
)
:
$handler
();
break
;
case
'class'
:
$instance
=
new
$handler
;
$result
=
$instance
->
handleRequest
(
$matches
);
}
if
(
$result
!==
false
)
return
$result
;
...
...
@@ -122,4 +165,20 @@ class Router extends Base {
}
}
/**
* Interface for handler classes which can be bound to a router pattern.
*
* @package WebBasics
*/
interface
RouteHandler
{
/**
* Handle an HTTP request.
*
* @param string[] $data A list of matched pattern groups, without the zero-group.
* @return mixed FALSE if the handler function was not able to handle the
* request, else the result of the reqeust.
*/
function
handleRequest
(
array
$data
);
}
?>
\ No newline at end of file
tests/test_router.php
View file @
8c329e4c
...
...
@@ -2,19 +2,31 @@
require_once
'router.php'
;
use
webbasics\Router
;
use
webbasics\RouteHandler
;
function
test_handler_no_args
()
{
return
true
;
}
function
test_handler_arg
(
$arg
)
{
return
$arg
;
function
test_handler_arg
(
array
$args
)
{
return
$arg
s
[
0
]
;
}
function
test_handler_args
(
$arg0
,
$arg1
)
{
function
test_handler_args
(
array
$args
)
{
list
(
$arg0
,
$arg1
)
=
$args
;
return
$arg1
.
$arg0
;
}
class
TestHandler
implements
RouteHandler
{
function
handleRequest
(
array
$data
)
{
return
$data
[
0
];
}
}
class
InterfacelessHandler
{
function
handleRequest
(
array
$data
)
{}
}
class
RouterTest
extends
PHPUnit_Framework_TestCase
{
function
setUp
()
{
$this
->
router
=
new
Router
(
array
(
...
...
@@ -44,10 +56,43 @@ class RouterTest extends PHPUnit_Framework_TestCase {
$this
->
assertEquals
(
'bar'
,
$foo
);
}
function
testAddRoute
()
{
function
testAddRoute
CallableSuccess
()
{
$this
->
router
->
addRoute
(
'(foobar)'
,
'test_handler_arg'
);
$this
->
assertEquals
(
'foobar'
,
$this
->
router
->
callHandler
(
'foobar'
));
}
/**
* @expectedException \InvalidArgumentException
*/
function
testAddRouteCallableFailure
()
{
$this
->
router
->
addRoute
(
'(foobar)'
,
'non_existing_function'
);
}
function
testAddRouteHandlerSuccess
()
{
$this
->
router
->
addRoute
(
'(foobar)'
,
'TestHandler'
);
$this
->
assertEquals
(
'foobar'
,
$this
->
router
->
callHandler
(
'foobar'
));
}
/**
* @expectedException \InvalidArgumentException
*/
function
testAddRouteHandlerNoString
()
{
$this
->
router
->
addRoute
(
'(foobar)'
,
new
TestHandler
);
}
/**
* @expectedException \InvalidArgumentException
*/
function
testAddRouteHandlerNonExisting
()
{
$this
->
router
->
addRoute
(
'(foobar)'
,
'NonExistingHandler'
);
}
/**
* @expectedException \InvalidArgumentException
*/
function
testAddRouteHandlerWithoutInterface
()
{
$this
->
router
->
addRoute
(
'(foobar)'
,
'InterfacelessHandler'
);
}
}
?>
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment