8 ms·
Toro - a php micro-router with great examples
- citricsquid 14y agoRelated: A similar project (a simple php router) called Klein exists (https://github.com/chriso/klein.php https://github.com/chriso/klein.php) which is really great. Does anyone have experience with both and can explain which is better?
- ChiperSoft 14y agoI love Klein, but this looks WAY easier to work with and much more specific. Klein includes a bunch of stuff for request and response handling, output buffers and views and stuff. Toro appears to completely leave all that to the implementer, which is very nice if you've already got code to handle those things.
- tlack 14y agoThanks for posting this. I hadn't seen Klein before and the simplicity and minimalism of the API really appeals to me. I'm using Slim so far and it has some serious drawbacks (no namespaced routes, no response()->write(json), overly complicated view system)
- jasonmoo 14y agoThe toro mascot on the main site is pretty cool. http://toroweb.org/ http://toroweb.org/
- gtevelde 14y agoi love it
- brito 14y agoSimple, elegant solution to a typical problem where everybody else ends up building a broken wheel.
- gee_totes 14y agoAgreed. This may have replaced Sinatra for my go-to for building quickie Rest APIs
- christensen_emc 14y agohave you tried SlimPHP? I've been using it for APIs lately and its been great. Very easy to get up and going very quickly.
- slurgfest 14y agoLooks clean. Way to ship!
- jaequery 14y agoi wish zend framework's router was this easy
- sjs382 14y agoSimilar to GluePHP: http://gluephp.com/documentation.html http://gluephp.com/documentation.html
- solox3 14y agoReminds me of many things; as usual, the weakest part of this PHP router is the .htaccess file.
- andypants 14y agoI don't think you can do this kind of url routing in php without modifying the .htaccess file.
- Karunamon 14y agoAnd so it's permanently married to Apache. Too bad.. is there anything like this that'll run on nginx/lighttpd?
- ChiperSoft 14y agoIt's just a matter of altering your nginx configuration to rewrite requests. https://gist.github.com/3441804 https://gist.github.com/3441804
- jasonmoo 14y agoI think it's pretty trivial to change the htaccess rewrite rule into an nginx/lighttpd rule.
- memnips 14y agoIn lighttpd, enable mod rewrite and: url.rewrite-once = ( "^/(.*)$" => "index.php/$1" )
- tlack 14y agoAll of these routers work under Nginx or Lighttpd, they just need a different config file. Here's one that is often used under Nginx: location { root /usr/share/nginx/html; index index.php index.html index.htm; try_files $uri $uri/ /index.php?$request_uri; }
- memnips 14y agoI've used Toro for about six months. It's excellent.
- jasonmoo 14y agoYeah me too. It's been a great tool for me as well.
- rickmb 14y agoThis illustrates exactly why PHP projects often become such an unmaintainable mess and security hole. This looks like an example collection of PHP worst practices. I mean, what could possibly go wrong with untestable code and unfiltered input...?
- jasonmoo 14y agoNot sure how adding some input filtering and tests would make this an unmaintainable mess..? The code is actually pretty tight and is optimized for empowering a developer rather than inflating the bumpers of your bowling lane.
- andypants 14y agoUntestable code? How is it untestable? Unfiltered input? You realise that this is a router, right? The only 'input' is the URL path. I really wish you could be more specific about these 'worst practices' that make this 91-line library an 'unmaintainable mess and security hole'.
- skrebbel 14y agoThat's not the problem this solves. This is 91 lines of code that solve one problem, routing, and that problem only. You filter input right afterwards. And how is this untestable, exactly? It's really easy to fake http requests in php-cli from a unit test, for instance. And is there any other way you'd want to test a router than by faking php requests? I somewhat wonder whether the fact that this happens to be PHP biased your judgment.
- jakejake 14y agoIf anything I find that a router makes your code easier to test. If you're 100% consistent about using the router to obtain user input, then your code is easy to unit test with a mock router. Routers themselves can be easy to test as well. It's a clean separation of concerns - the router is the only thing that knows about the URL implementation. The rest of the code relies on the router to do that. That's a good practice to me. What would you would consider "best practice" in place of a router?
- mootothemax 14y agoIs this a parody of how not to do things? I was prepared to take it on face value of being rather misguided, but thinking about it... It's a glorified mess of goto statements and objects being misused. I confess that I stopped digging further after I saw files being included in methods, absolutely one of the biggest sins in PHP: https://github.com/anandkunal/ToroPHP/blob/master/examples/blog/handlers/article_handler.php https://github.com/anandkunal/ToroPHP/blob/master/examples/b... https://github.com/anandkunal/ToroPHP/blob/master/examples/blog/handlers/articles_handler.php https://github.com/anandkunal/ToroPHP/blob/master/examples/b...
- jasonmoo 14y agoMost frameworks hide including views by way of extract() and output buffering. There's no real benefit to doing that on a small app. And no benefit on an api.
- mootothemax 14y agoMost frameworks hide including views by way of extract() and output buffering. There's no real benefit to doing that on a small app. And no benefit on an api. There's always a benefit to not copying and pasting code, which is what writing an include in each of your handlers boils down to.
- lux 14y agoNot that I've looked at it in much depth, but those just look like simplistic examples to show how the routing works. If it's just a router, then how you render views is beyond the scope of the library, and cutting corners in examples for the sake of expediency doesn't seem so bad.
- mootothemax 14y agoNot that I've looked at it in much depth, but those just look like simplistic examples to show how the routing works. If it's just a router, then how you render views is beyond the scope of the library, and cutting corners in examples for the sake of expediency doesn't seem so bad. I'm fine with the idea of a router simply being a router; I really take exception to yet more PHP examples illustrating bad coding habits being on the web though.
- flyosity 14y agoLooks similar to Fat Free Framework for PHP, which I've been using for a few months. http://bcosca.github.com/fatfree/ http://bcosca.github.com/fatfree/
- mmcnickle 14y agoWell done! This has a really clean interface, I wish I'd come across it when looking for a simple router a few weeks ago. A lot of the other ones lean heavily towards a style associated with their related framework, or are too esoteric/basic. There are a few things I would have to add before I would use it however, and I hope they make it in some day: 1) You should add a whitelist for the HTTP request method names, i.e only allow calls to get(), post(), not some_suspicious_call_from_bad_user(). People will often put non HTTP methods in their views (view as in django sense) and you don't want them to be able to be called by a malicious user. 2) You should make it easy for the developer to configure their own xhr headers. 3) Nitpick: You should probably use 405 (Method Not Allowed) instead of 404 for when a method handler isn't found. Maybe I'll use it in this project, in which case you may have a few pull requests headed your way!
- jasonmoo 14y agoWow fantastic code review! I'm a minor contributor on this project and those changes sound great.
- mcfunley 14y agoHow is this not just a slower .htaccess implementation with OOP boilerplate? The instructions even mention editing .htaccess, so it's not like this is necessarily intended for people who don't have control of it. RewriteRule ^foo/([0-9]+)/bar /foo/bar.php?x=$1 [L,NC,QSA] Done. These things come across as monkey-see-monkey-do. Other frameworks in other languages have routers, therefore they must also make sense in PHP.
- jasonmoo 14y agoThere are benefits to keeping your routing in your app. Using different route sets based on environment variables, specifically migrating from one version of an api to another is not possible or easy with a purely htaccess router. But I agree that in some cases the fastest you can do is an htaccess route.
- benatkin 14y ago> There are benefits to keeping your routing in your app. Using different route sets based on environment variables, specifically migrating from one version of an api to another is not possible or easy with a purely htaccess router. I'm not excited to correct you, because the way it it doesn't quite hold true involves dragons, but I thought I would in case people doubt the power of apache configuration (nginx is much the same way). It is possible, with included modules like the one below. There is also the ability to use custom modules, which are programmatic in nature and have access to Apache at a low level. Since it wasn't specified whether a shared host is being used, I think it's within the scope of the discussion. http://httpd.apache.org/docs/2.2/env.html http://httpd.apache.org/docs/2.2/env.html
- chc 14y agoAnd then somebody tries to run your app in nginx. Tying your app to a particular server is a design choice. Some people like it, some people don't.
- laacz 14y agoIf someone tries to run app on nginx or lighttpd, he (or she) already knows how to mimic .htaccess rules in their webserver of choice.
- iguana 14y agoIt's an interesting approach. I use SlimPHP, which approaches the RESTful API problem as a DSL, much like Sinatra. Slim has a few nice features, and my new preferred PHP stack is Slim Framework + Zend Framework as a library.
- desfrenes 14y agoLike everybody else, I wrote my own router which somehow began to grow and became a so-called microframework: http://azuki.desfrenes.com/ http://azuki.desfrenes.com/ This is probably what I would use for PHP, but obviously other languages have better solutions like ruby/sinatra, python/flask etc.
- devgutt 14y agoHow can I bypass images or specific files using ToroPhp? I usually add this lines at my .htaccess: RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d
- sjs382 14y agoYou do just that. When setting your .htaccess to route all URLs through Toro, use a snippet like: RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php
- jmtucu 14y agoI used Moor for several projects and works like charms and it's very easy to use ( https://github.com/jeffturcotte/moor https://github.com/jeffturcotte/moor )