Custom lithium routing scenario - php

I've been tasked with rewriting an existing website with large pre-existing link catalog. For argument's sake, let's assume we can't do anything that would change the link catalog. Here's a few examples of the link structure we're working with:
An item page would be:
www.domain.com/widgets/some-totally-awesome-large-purple-widget
A category sub page page would be:
www.domain.com/widgets/purple-widgets
A category parent page page would be:
www.domain.com/widgets/
A custom page may be:
www.domain.com/some-random-page
The various page types are too numerous to write individual Routers for.
Using Router::connect I can easily account for the first and second scenarios using something like:
Router::connect('/{:pageroot}/{:pagekey}', 'Pages::index');
In turn, the Pages::index method looks for entries in our database with the "key" of '/widgets/purple-widgets'.
However, the framework defaults to the '/{:controller}/{:action}/{:args}' route for pages like the third and fourth. I know that this is the correct behavior for the framework. Also, best practice would state that I should write the site to match this behavior. But, that isn't an option here.
What I need is a Router that would allow the third and fourth examples to function the same as the first. All examples should be sent to the Pages::index controller, which in turn queries a database using the URL path as a key.

If you don't have any convention in the URL for what is what, between page, item and category. I'd go with a very generic router.
Router::connect('/{:category}/{:page}/{:item}', 'Pages::any');
Router::connect('/{:category}/{:page}', array('Pages::any', 'item' => null));
Router::connect('/{:category}', array('Pages::any', 'page' => null, 'item' => null));
And in Pages::any() to search for the correct stuff. Is that category a page after all (example 4)? Is that page an item (example 1)?
or
You store the URL somewhere (e.g. a mapping table in the database) and use the pattern version of a lithium Route.
Router::connect(new Route(array(
'pattern' => '#^/(?<path>.+)$#',
'params' => array('controller' => 'pages', 'action' => 'any'),
'keys' => array('path' => 'path'),
// extra stuff, if the path is `tata`, it skips this route and uses
// any of the following ones that matches.
'handler' => function($request) {
if ($request->params['path'] == 'tata') {
return false;
} else {
return $request;
}
}
)));
From that point, you'll get the full URL.

You probably should write a smart Router Helper which is maybe able to process your request based on your db defined routes.
Take a look into: net/http/Router.php
especially connect(), parse() and match()
I would start to write some kind of anonymous function and progress it to a testable Class which is located in /extension.. ?

Related

How to set custom Route with alias as controller

The CMS i'm developing using Cakephp 2.0 has two main Controllers:
Pages
Categories
I'm trying to set the route.php to have the following behavior:
If the user request a Page, the URL should be something like:
http://www.something.com/pages-alias/article-name/id/whatever
If the user address a Category, the URL should be something like:
http://www.something.com/categories-alias/category-name/id/whatever
Please notice that following categories and pages i've used "alias".
To clarify with an example, the URLs for a website of a local restaurant will be:
http://www.something.com/course/wild-boar/68/2013-07-18
Where "course" will substitute "page". And
http://www.something.com/menu/valentine-day/8/2014-01-30
Where "menu" will substitute "category".
The View should not be explicited in the URL nor the Routing rules.
Both the cases will have the view automatically choosen by the controller after some internal check (having subcategory, having only one page or more pages, and so on) so that will be overridden by the controller.
I've got some clues about the use of sort-of "alias" to build the routing rules but unfortunately the documentation was not clear enough to me about how to manage the object to create my own custom route.
So, can someone try to explain it with some example different from the ones available in the CakePhP 2.x documentation?
Thanks in advance to anyone that can be helpful.
For reference i'll paste here the links i've already read:
Routing - Cakephp 2.0 Documentation
Bakery Article from Frank (i suppose this is for the v1.3)
That is what you want probably:
Router::connect(
'/:category_alias/:category_name/:id/:whatever',
array('controller' => 'Article', 'action' => 'view'),
array('pass' => array('category_alias','category_name','id','whatever'),
'id' => '[0-9]+')
);
ofc you can delete this validator for id.. or add more validators :)
Then you can use function in ArticleController.php
public function view($category_alias, $category_name, $id, $whatever) {}

How can I have more than 2 directories deep with a controller in Kohana

I have a stat, in which many can exist for an improvement, which is one model in my about page. I initially built the page as one giant controller having silly actions like "action_editimprovementstat".
So I tried to move things into directories, so rather than everything being in "[...]/controller/about", I moved things into there perspective folders, for example: "[...]/controller/about/improvement/stat"
I changed the regex of the route, so the controller would accept slashes, which judging by the debugger, worked, because now the controller text will show up as "about/improvement/stat", unfortunately it still tells me the requested url can't be found.
So, I ask, what is the simplest way to have a hierarchical controller structure?
Here is an example of controller URLs that I would prefer:
/about
/about/internal
/about/external
/about/improvement
/about/improvement/stat
Those would also have actions, so for example:
/about/improvement/edit/6
/about/improvement/stat/delete/7
I'm willing to compromise if there are issues with ambiguity.
(Btw, I think I could manage a way if I did my own routing through a single controller, but I'm wondering if there is a better way, or if that way is well documented [so I can learn from another's experience].)
You can simply add additional variables or constant values to the route if you live.
The Kohana documentation even shows a concrete example, where an extra directory is added in front of the route, which can have only one of two given values:
Route::set('sections', '<directory>(/<controller>(/<action>(/<id>)))',
array(
'directory' => '(admin|affiliate)'
))
->defaults(array(
'controller' => 'home',
'action' => 'index',
));
Of course you can add values in the back or inbetween as well. The only requirement is that your route will always result in at least a controller and an action. But they don't actually have to exist in the url. You can specify routes that match other values and have a constant value for controller and/or action, like this:
Route::set('search', ':<query>', array('query' => '.*'))
->defaults(array(
'controller' => 'search',
'action' => 'index',
));
The greatest pitfall: It is important to understand that routes are matched in the order they are added, and as soon as a URL matches a route, routing is essentially "stopped" and the remaining routes are never tried. Because the default route matches almost anything, including an empty url, new routes must be place before it.
Maybe that is what's going wrong now?
Anyway, rather than adding trickery to match slashes, I'd rather create a route that accepts a large number of optional variables, so you could read 'urlpart1' to urlpartX' from your generic controller. That is, if you need to. The setup, of course, is to let you create different controllers for different urls, so you don't need a humongous controller with a gigantic method to decide what to do based on the url parts.
Ever since I learned Kohana, my programming experience has been greatly improved because prior to Kohana I never gave a moments thought to how my urls were constructed. In the MVC world using Pretty URLs makes you really think about what you want to do and how to go about it.
In my opinion by looking at what you are wanting to do in the examples above, it seems to me that you are thinking backwards. You said the URLS that you preferred are: /about /about/internal /about/external /about/improvement /about/improvement/stat
It seems to me that "about" is really an action, not a controller. The url "/about/" is pretty confusing because it doesn't tell me what I'm getting information about but we can let that one slide because it's probably about the site in general. "/about/internal" is pretty clear but in a lot of ways you are trying to write your urls so that they read in proper English. In reality I would write them as: /about, /internal/about, /external/about, /improvement/about, /improvement_stat/about
I'm not sure why you are resisting have several controllers unless perhaps you are setting up your controllers as template controllers and maybe you think you have to do that for each one. You dont. In general I create a controller named "page" which is my template controller. Then all other controllers extend the page controller. I can define constants and other variables in the page controller that can be used in all the controllers that extend the page controller.
But if you are really resisiting writing multple controllers, you can always write specific routes that will let you reach any controller and action that you want. For example I used a route for a comparison where I wanted up to 4 id's passed into my route. I wrote that route like this:
Route::set('thing_compare', 'thing/compare/<thing1>/<thing2>(/<thing3>(/<thing4>))')
->defaults(array(
'controller' => 'thing',
'action' => 'compare'
));
Note that thing3 and thing4 are in parens which means they are optional. Then in my controller I can get those values by doing something like:
$thing1 = $this->request->param('thing1');
But going back to the examples you gave, just write the routes something like this (assuming your controller is named "about":
Route::set('about_internal', 'about/internal')
->defaults(array(
'controller' => 'about',
'action' => 'about_internal'
));
Route::set('about_external', 'about/external')
->defaults(array(
'controller' => 'about',
'action' => 'about_external'
))
Personally I would avoid setting routes like this and really reconsider how your urls need to be setup so that it creates a sensible design strategy.

CMS Routing in MVC

I am creating my own MVC framework in php as a means to learn more advanced programming. I've got the framework up and running however I have an issue regarding the current routing method. I want the framework to support a backend cms to compliment the front end website. The issue is that my routing structure works like so - mywebsite.com/controller/method/id
The routing engine sorts the information into an array like this
segments 0 => controller, 1 => method, 2 => id
Right now if I visit mywebsite.com/projects it takes me to what I have set up as an admin page. Not only do I want this to be accessible only from mywebsite.com/admin/projects, I want the mywebsite.com/projects to take me to frontend.
So if I want to visit mywebsite.com/projects I'd like it to render the "front" controller, pushing "projects" into the method. If I visit mywebsite.com/admin/projects I'd like it to load the projects controller.
Here's the current routing class in whole as follows.
<?php
class Request {
//url domain.com/controller/method/other
//holds url segments 0 => controller, 1 => method, 2 => other, etc
public $segments;
function __construct() {
$this->parse_globals();
}
function parse_globals(){
//$uri = preg_replace("|/(.*)|", "\\1", str_replace("\\", "/", $_SERVER['REQUEST_URI']));
$uri = (empty($_GET['rt'])) ? '' : $_GET['rt'];
$this->segments = array_filter(explode('/', $uri));
if (in_array("admin", $this->segments)) {
array_shift($this->segments);
}
print_r($this->segments);
//remove index php
if( reset($this->segments) == 'index.php') {
array_shift ($this->segments);
}
}
function controller(){
return $this->segment(0);
}
function method(){
return $this->segment(1);
}
function param( $str ){
return isset($_REQUEST[$str]) ? $_REQUEST[$str] : false;
}
function segment( $no ){
return isset($this->segments[$no]) ? $this->segments[$no] : false;
}
}
Instead of simply using explode() to separate the segments of URL, you could use a set of regular expression pattern.
For example, this following patter would try to match at firsts action, and, if action exists them check if there is controller set before it:
'/(:?(:?\/(?P<controller>[^\/\.,;?\n]+))?\/(?P<action>[^\/\.,;?\n]+))?/'
Most of PHP frameworks use different ways to generate such patterns, with simplified notations. This way you can set which parts for each pattern are mandatory and which optional. And it is also possible to provide fallback values for the optional parts.
That said ...
Before starting to make something so complicated as cms with framework, you might invest some additional time in researching OOP. I would recommend to at least watch lectures from Miško Hevery and Robert C. Martin. Just because you think, that you know how to write a class, does not mean, that you understands object oriented programming.
Update
I have listed few materials in this answer. You might find them useful,
Additionally here are two more lectures, that were not in answer above:
Clean Code I: Arguments
Clean Code III: Functions
My understanding is that there's three routing cases:
The basic one:
/<controller>/<action>/<parameters>
A special one for the admin panel (where "admin" would be a kind of separate module):
/<module>/<controller>/<action>/<parameters>
And finally a special case for "/projects" which maps to "/front/projects".
In that case, you need to make your routing class more flexible so that it can handle any kind of routing scheme. In a framework like Kohana, this would be done with rules such as:
Route::set('adminModule', 'admin/projects')
->defaults(array(
'controller' => 'projects',
'action' => 'admin',
));
Route::set('projectPage', 'projects')
->defaults(array(
'controller' => 'front',
'action' => 'projects',
));
Route::set('default', '(<controller>(/<id>(/<action>)))')
->defaults(array(
'controller' => 'index',
'action' => 'index',
));
Obviously this is just an example but you get the idea. Basically, you want to provide some sensible default routing (eg. controller/action/id) but you also need to allow users to configure other routes.
I am currently developing a php router which is targeted at extreme high performance. you probably might want to take a look.
https://github.com/c9s/Pux
We also provide a pattern compiler that is doing the same thing as yours. but you can write a simpler path instead of complex patterns.
e.g., you may write something like this:
/product/:id/:name [ id => '\d+', name => '\w+' ]
FYI:
Pux is 48.5x faster than symfony router in static route dispatching, 31x faster in regular expression dispatching. (with pux extension installed)
Pux tries not to consume computation time to build all routes dynamically (like Symfony/Routing). Instead, Pux compiles your routes to plain PHP array for caching, the compiled routes can be loaded from cache very fast.
With Pux PHP Extension support, you may load and dispatch the routes 1.5~2x faster than pure PHP Pux.

cakephp routing for cushycms preview link

I have a set of rather static pages wich I moved to the views/pages folder. The resulting *.ctp files are editable by my customer through CushyCMS (simplistic cms perfect for dummy proof editing). However CushyCMS generated preview links that obviously don't take CakePHP into account. I would like to solve this little problem with custom routing, but can't get my head around the details..
How can I dynamically connect the url http://localhost:8888/cake125/app/views/pages/test.ctp to http://localhost:8888/cake125/pages/test?
I added the following in my routes.php:
Router::connect('/pages/test.ctp', array(
'controller' => 'pages',
'action' => 'display', 'test'));
This works ok for connecting: http://localhost:8888/cake125/pages/test.ctp to http://localhost:8888/cake125/pages/test. Somehow following snibbet doesn't do the trick:
Router::connect('/app/views/pages/test.ctp', array(
'controller' => 'pages',
'action' => 'display', 'test'));
Ideally I'd like to have a single Router::connect statement which connects all /app/views/pages/*.ctp requests to the right place.
Finally I would also like to correctly handle google search results for the old version of the site. Like so:
Router::connect('/test.html', array(
'controller' => 'pages',
'action' => 'display', 'test'));
This works ok but I'd rather have anypage.html connect to /pages/anypage. Can anyone help with this?
Thanks in advance!
First, by virtue of having Cake in a subdirectory (/cake125), I think you may need to connect the /cake125/:controller/:action, rather than how you have it. Not 100%, though; Cake might be robust enough to handle that use case. If you have weird errors, I'd check that.
On with my answer:
I think you are somewhat misunderstanding how the Router class works. You connect URLs, not relative filesystem paths, using Router::connect. By default (which you may have erased, but it's pretty simple to fix), Cake will route requests to /pages/* to the PagesController::display() function, passing it one argument (the action listed in the http request).
So, to have the pages controller map /pages/one to the app/views/pages/one.ctp element, simply make sure that the following (default, i.e. Cake normally has this setup) line is in the routes config (and make sure that lines above it do not match that pattern):
Router::connect( '/pages/:action', array( 'controller' => 'pages', 'action' => 'display', :action);
This should ensure that PagesController::display( $action ) is invoked during the request, which is (I think) what you're after.
If your CMS generates preview links that you want to correctly re-route, I'd suggest adding a new route. E.g., if your CMS generates links like http://somesite.com/cms/preview/newly_edited_file, you can route it like this:
Router::connect( '/cms/preview/:action', array( 'controller' => 'pages', 'action' => 'display', :action );
For your second question: have a default rule in your routes (make it the last rule, and have it match *). It will then be configured to route all not found requests to your controller/action pair as requested. Try this:
Router::connect( '/:action', array( 'controller' => 'pages', 'action' => 'display', :action );
Major caveat this will break your existing routes. You will need to manually add an entry for each of your existing controllers (Router::connect( '/users/:action', ...etc...). If you google around you can find some clever solutions, such as having that list generated at runtime for you. But you will need to address "normal" routing, once you've added that catch-all (and make sure your catch-all is at the end of the routing file).
Also, if you want to parse URLs like /test.html, simply add a call to Router::parseExtensions(...) so that Cake will register .html as an extension for it to parse. Check the manual on that function for more info.
As others have pointed out how CakePHP Router works, I'll leave it at that.
For the second part of your question (handling old links), I'd suggest adding this to the end of your Routes list:
Router::connect( '/:page',
array (
'controller' => 'pages',
'action' => 'display',
),
array (
'pass' => array ('page'), // to pass the page as first arg to action
'page' => '.+\.html$', // to verify that it ends with .html
)
);
You'd unfortunately have to parse out the .html yourself though
How can I dynamically connect the url http://localhost:8888/cake125/app/views/pages/test.ctp to http://localhost:8888/cake125/pages/test?
Well, the thing is, you don't. :-)
What I mean by that is, you do not connect a URL to another URL. What you really do is, you make certain URLs trigger certain Controller functions (or Actions for short) which in turn may (or may not) render certain Views. By default it's all straight forward through naming conventions. The URL /foo/bar triggers the Controller Foo's Action bar and renders the View /views/foo/bar.ctp.
The PagesController is already a special case. The URL /pages/foo triggers the Controller Pages's Action display, passes it the parameter foo, which renders the View /views/pages/foo.ctp. Notice the difference in which Action is triggered.
Since there are a lot of steps inbetween, it's not a given that a certain URL corresponds to a particular file on the hard disk. The URL /foo/bar might trigger Controller Baz' Action doh which renders the View /views/narf/glob.ctp.
This makes translating http://localhost:8888/cake125/app/views/pages/test.ctp to render the file /views/pages/test.ctp somewhere between an uncertainty and a pain in the rear.
Edit:
Having said that, the particular problem in your case is that the base URL is http://localhost:8888/cake125/app/. You can invoke a Cake app from http://localhost:8888/cake125/, http://localhost:8888/cake125/app/ or http://localhost:8888/cake125/app/webroot. All three URLs will be handled by the same file cake125/app/webroot/index.php, if you use one of the shorter URLs the request will be "forwarded" (rewritten) via .htaccess rules.
So the Route you're trying to connect, the Route that Cake sees, is actually /views/pages/test.ctp.
Actually, my mistake, this might not be the problem, but it depends on your .htaccess files and server configuration.
It doesn't seem to make much sense in a CMS though, since every newly created page would need its own rule. So I'd recommend against trying to do so and rather hack Cushy to properly construct URLs using the Cake HtmlHelper or Router::url(). Failing that, connect all URLs with a catch-all rule to some Action, parse the URL there and render the correct View "manually".
Alternatively, use .htaccess files and rewrite rules to actually rewrite the URL into a normal Cake URL, so Cake doesn't have to worry about it. As said above though, this can be very fragile.

PHP Application URL Routing

So I'm writing a framework on which I want to base a few apps that I'm working on (the framework is there so I have an environment to work with, and a system that will let me, for example, use a single sign-on)
I want to make this framework, and the apps it has use a Resource Oriented Architecture.
Now, I want to create a URL routing class that is expandable by APP writers (and possibly also by CMS App users, but that's WAYYYY ahead in the future) and I'm trying to figure out the best way to do it by looking at how other apps do it.
I prefer to use reg ex over making my own format since it is common knowledge. I wrote a small class that I use which allows me to nest these reg ex routing tables. I use to use something similar that was implemented by inheritance but it didn't need inheritance so I rewrote it.
I do a reg ex on a key and map to my own control string. Take the below example. I visit /api/related/joe and my router class creates a new object ApiController and calls it's method relatedDocuments(array('tags' => 'joe'));
// the 12 strips the subdirectory my app is running in
$index = urldecode(substr($_SERVER["REQUEST_URI"], 12));
Route::process($index, array(
"#^api/related/(.*)$#Di" => "ApiController/relatedDocuments/tags",
"#^thread/(.*)/post$#Di" => "ThreadController/post/title",
"#^thread/(.*)/reply$#Di" => "ThreadController/reply/title",
"#^thread/(.*)$#Di" => "ThreadController/thread/title",
"#^ajax/tag/(.*)/(.*)$#Di" => "TagController/add/id/tags",
"#^ajax/reply/(.*)/post$#Di"=> "ThreadController/ajaxPost/id",
"#^ajax/reply/(.*)$#Di" => "ArticleController/newReply/id",
"#^ajax/toggle/(.*)$#Di" => "ApiController/toggle/toggle",
"#^$#Di" => "HomeController",
));
In order to keep errors down and simplicity up you can subdivide your table. This way you can put the routing table into the class that it controls. Taking the above example you can combine the three thread calls into a single one.
Route::process($index, array(
"#^api/related/(.*)$#Di" => "ApiController/relatedDocuments/tags",
"#^thread/(.*)$#Di" => "ThreadController/route/uri",
"#^ajax/tag/(.*)/(.*)$#Di" => "TagController/add/id/tags",
"#^ajax/reply/(.*)/post$#Di"=> "ThreadController/ajaxPost/id",
"#^ajax/reply/(.*)$#Di" => "ArticleController/newReply/id",
"#^ajax/toggle/(.*)$#Di" => "ApiController/toggle/toggle",
"#^$#Di" => "HomeController",
));
Then you define ThreadController::route to be like this.
function route($args) {
Route::process($args['uri'], array(
"#^(.*)/post$#Di" => "ThreadController/post/title",
"#^(.*)/reply$#Di" => "ThreadController/reply/title",
"#^(.*)$#Di" => "ThreadController/thread/title",
));
}
Also you can define whatever defaults you want for your routing string on the right. Just don't forget to document them or you will confuse people. I'm currently calling index if you don't include a function name on the right. Here is my current code. You may want to change it to handle errors how you like and or default actions.
Yet another framework? -- anyway...
The trick is with routing is to pass it all over to your routing controller.
You'd probably want to use something similar to what I've documented here:
http://www.hm2k.com/posts/friendly-urls
The second solution allows you to use URLs similar to Zend Framework.
Use a list of Regexs to match which object I should be using
For example
^/users/[\w-]+/bookmarks/(.+)/$
^/users/[\w-]+/bookmarks/$
^/users/[\w-]+/$
Pros: Nice and simple, lets me define routes directly
Cons: Would have to be ordered, not making it easy to add new things in (very error prone)
This is, afaik, how Django does it
I think a lot of frameworks use a combination of Apache's mod_rewrite and a front controller. With mod_rewrite, you can turn a URL like this: /people/get/3 into this:
index.php?controller=people&method=get&id=3. Index.php would implement your front controller which routes the page request based on the parameters given.
As you might expect, there are a lot of ways to do it.
For example, in Slim Framework , an example of the routing engine may be the folllowing (based on the pattern ${OBJECT}->${REQUEST METHOD}(${PATTERM}, ${CALLBACK}) ):
$app->get("/Home", function() {
print('Welcome to the home page');
}
$app->get('/Profile/:memberName', function($memberName) {
print( 'I\'m viewing ' . $memberName . '\'s profile.' );
}
$app->post('/ContactUs', function() {
print( 'This action will be fired only if a POST request will occure');
}
So, the initialized instance ($app) gets a method per request method (e.g. get, post, put, delete etc.) and gets a route as the first parameter and callback as the second.
The route can get tokens - which is "variable" that will change at runtime based on some data (such as member name, article id, organization location name or whatever - you know, just like in every routing controller).
Personally, I do like this way but I don't think it will be flexible enough for an advanced framework.
Since I'm working currently with ZF and Yii, I do have an example of a router I've created as part of a framework to a company I'm working for:
The route engine is based on regex (similar to #gradbot's one) but got a two-way conversation, so if a client of yours can't run mod_rewrite (in Apache) or add rewrite rules on his or her server, he or she can still use the traditional URLs with query string.
The file contains an array, each of it, each item is similar to this example:
$_FURLTEMPLATES['login'] = array(
'i' => array( // Input - how the router parse an incomming path into query string params
'pattern' => '#Members/Login/?#i',
'matches' => array( 'Application' => 'Members', 'Module' => 'Login' ),
),
'o' => array( // Output - how the router parse a query string into a route
'#Application=Members(&|&)Module=Login/?#' => 'Members/Login/'
)
);
You can also use more complex combinations, such as:
$_FURLTEMPLATES['article'] = array(
'i' => array(
'pattern' => '#CMS/Articles/([\d]+)/?#i',
'matches' => array( 'Application' => "CMS",
'Module' => 'Articles',
'Sector' => 'showArticle',
'ArticleID' => '$1' ),
),
'o' => array(
'#Application=CMS(&|&)Module=Articles(&|&)Sector=showArticle(&|&)ArticleID=([\d]+)#' => 'CMS/Articles/$4'
)
);
The bottom line, as I think, is that the possibilities are endless, it just depend on how complex you wish your framework to be and what you wish to do with it.
If it is, for example, just intended to be a web service or simple website wrapper - just go with Slim framework's style of writing - very easy and good-looking code.
However, if you wish to develop complex sites using it, I think regex is the solution.
Good luck! :)
You should check out Pux https://github.com/c9s/Pux
Here is the synopsis
<?php
require 'vendor/autoload.php'; // use PCRE patterns you need Pux\PatternCompiler class.
use Pux\Executor;
class ProductController {
public function listAction() {
return 'product list';
}
public function itemAction($id) {
return "product $id";
}
}
$mux = new Pux\Mux;
$mux->any('/product', ['ProductController','listAction']);
$mux->get('/product/:id', ['ProductController','itemAction'] , [
'require' => [ 'id' => '\d+', ],
'default' => [ 'id' => '1', ]
]);
$mux->post('/product/:id', ['ProductController','updateAction'] , [
'require' => [ 'id' => '\d+', ],
'default' => [ 'id' => '1', ]
]);
$mux->delete('/product/:id', ['ProductController','deleteAction'] , [
'require' => [ 'id' => '\d+', ],
'default' => [ 'id' => '1', ]
]);
$route = $mux->dispatch('/product/1');
Executor::execute($route);
Zend's MVC framework by default uses a structure like
/router/controller/action/key1/value1/key2/value2
where router is the router file (mapped via mod_rewrite, controller is from a controller action handler which is defined by a class that derives from Zend_Controller_Action and action references a method in the controller, named actionAction. The key/value pairs can go in any order and are available to the action method as an associative array.
I've used something similar in the past in my own code, and so far it's worked fairly well.
Try taking look at MVC pattern.
Zend Framework uses it for example, but also CakePHP, CodeIgniter, ...
Me personally don't like the MVC model, but it's most of the time implemented as "View for web" component.
The decision pretty much depends on preference...

Categories