views:

42

answers:

2

I'm trying to figure out what the best way to go about rewriting urls to accommodate not only a directory structure, but appended actions for a menu for a site I'm building in PHP.

I have one page that dynamically loads content based on whatever "page" is being loaded. Includes are pulled based on what the page is. Right now that's tied to directories in my includes folder. So folder/page will include includes/folder/page.php.

If I have a structure like "root/page/action/param" that works fine as long as I say "whatever is in this place in the url is this." But I ran into trouble when I started adding folders that hold different levels of pages. If I explode page out to "folder/subfolder/page" then using placement to determine what is what goes out the window. I was thinking about using something like a hyphen as a delimiter to go "root/folder-subfolder1-subfolder2-page/action/param" so I can identify the page easily but I don't really like that option.

I also don't really like tying my includes directory structure to my urls but the only other way I would think to go about avoiding that would be to have an in-memory object to handle what exactly goes where. But I want to avoid that as I want the menu to be dynamic, based on an XML file that gets parsed and urls generated accordingly. I don't want the overhead of parsing the xml and not only generating URLs but also dynamically generating an in-memory object that has seemingly arbitrary rules.

Any suggestions?

A: 

Use Absolute Paths instead of relative in your menu html & scripts and you shouldn't have problems as it will always point to correct source.

Absolute Path Example (notice the /):

<a href="/">Home</a>
<a href="/services">Services</a>
<a href="/mypage">My Page</a>
<a href="/mypage2">My Page 2</a>
Codex73
kappasims
A: 

PHPonTrax uses an implementation that I think would allow for this type of routing that you want, and it's open source so you could look at the code for some inspiration. (Note: I am not making any judgement as to the framework, I just have seen the code and think it might work for you).

Basically, you store your routes in an array and you provide some placeholder's as well so that you can have multiple possible controllers/actions/ids after a given path.

So if $routes[] is our array to hold everything, we could add:

$routes[0]['path'] = "foo/bar/:controller/:action";
$routes[0]['params'] = null;
$routes[1]['path'] = "baz/:action";
$routes[1]['params'] = array("controller"=>"blah");
$routes[2]['path'] = "catalog/:id";
$routes[2]['params'] = array("controller"=>"products", "action"=>"view");
$routes[3]['path'] = ":controller/:action/:id";
$routes[3]['params'] = null;

":controller", ":action", and ":id" are unique tokens that indicate what you are allowing a token to represent in the path. So "/baz/edit", "/baz/delete", "/baz/create", "/baz/funkify", etc are all valid provided controller "blah" has edit, delete, create, and funkify methods. If the path is "/catalog/1234", then '1234' is the id and it's a valid path if and only if you can find a product with id=1234. If your request is to "/products/dothis/12345", routes 0-2 don't match, but route 3 does, so you can then look for a controller file named "products", and provided it has a method named "dothis", then you can call "dothis(12345)". Obviously, if there's no "dothis" method, or '12345' can't be found, it's an invalid path and you can raise an exception. Note you need to provide a default route, and in this case it's $routes[3].

In your file structure, you can have:

/app
  /controllers
  /views
  /etc, etc

Possible drawback is that in your rewrite, you send every request to one php script.

If this interests you: PHPonTrax. You will want to look at the router class and action_controller class (see the process_route() and recognize_route() methods).

CLM