Welcome Guest, Not a member yet? Register   Sign In
Help with full "fake" directory structure URL
#1

[eluser]alphane[/eluser]
Hi all,

I've been developing with CI intermittently for about a year. I'm by no means a novice, but not coming from a PHP background before using CI has left some major gaps in my knowledge.

My current issue is that I want to create a site using a full "virtual directory" structure. So where I understand I could easily create a controller to handle requests such as

Code:
www.site.com/controller/friendly-page-name

what if I wanted to show the pages relationship to other pages through the URL? How could I, for example, achieve something like this:

Code:
www.site.com/parent-page/child-page/even-deeper-page

I could route all requests to a master controller, but wouldn't that leave me with the situation of having to then manually re-route all exceptions to their true controllers?

It seems to me that there should be a really elegant solution that is just eluding me. I don't really know what to call this "technique" either, which is also hindering me searching the web for known solutions.

Can anyone help or point me in the right direction on this?

Regards,

Andy
#2

[eluser]guillermo, out of repose[/eluser]
Not all that sure I have a full grasp on what you're asking but I think the _remap() method can be put to use here. Read more about it in the user guide. If I get what you're saying, you could, in theory, have a few "parent" controllers and use the _remap() method to handle all requests that go to those parents. So:

[pre]www.site.com/parent-page/child-page/even-deeper-page[/pre] could get handled by the parent-page controller, and you could do something like this:

[pre]
function _remap($method)
{
switch($method) {
case "some-awesome-child":
// do some stuff using uri segments
case "some-other-awesome-child":
// do some more stuff
}
}
[/pre]

You could even ignore the $method parameter and just do whatever you want to based on the uri segments. Essentially, again, just implement the _remap() method to handle all of your requests.
#3

[eluser]jedd[/eluser]
You could also do some pretty rude things with __call(), too.

I think the problem is that you're only describing one half of what you want. Viz.

[quote author="alphane" date="1253757238"]
what if I wanted to show the pages relationship to other pages through the URL? How could I, for example, achieve something like this:

Code:
www.site.com/parent-page/child-page/even-deeper-page
[/quote]

That URL works just fine if you have a controller called parent-page, which contains a method called child-page, and child-page() knows what to do when its first parameter is a string such as 'even-deeper-page'.

Perhaps if you describe the structure you want to have in your code, and the visible effect you want to have in the URL, and how you want the two to map against each other. Avoiding the word page might help, too, as it can mean all kinds of different things.
#4

[eluser]alphane[/eluser]
Okay, I think I can see where I've gotten you all confused.

(I've tried to explain without using the word page, but I'm at a loss how to!)

Basically, I want a CMS-like dynamic ability to create many web-pages within a hierarchical structure. So for example a web page called "About us" may have child-pages called "Our Mission" and "The Team".

To access these pages I desire a URL structure that reflects these pages relationship, so accessing www.site.com/about-us would give the about us page. From this page, if I was to browse to "Our Mission" I would want the URL to read www.site.com/about-us/our-mission. Reading the URL, it then becomes obvious where I am in the sites page structure, almost like a breadcrumb trail.

I understand I could simply have an "about-us" controller, but this wouldn't be dynamic as I want all "pages" to route through one master "page" controller, be they "about us" or "contact us" or otherwise, as displaying one web-pages content should be handled by one controller.

Where this is confusing me is that I can't use a standard method as I will have an unknown amount of URI segments being passed to a given function, so I need to manually grab the URI segments and try to find a match in the database and work my way back through valid pages.

Using another example, I would also want www.site.com/about-us/not-a-real-page to detect that while "not-a-real-page" doesn't exist, "about-us" does and redirect them to the existing page.

Whilst I'm writing this, I guess I'm probably over-thinking this somewhat. I could set the standard master controller as the default controller so all web-pages get routed through there first of all. All I would really need to do is prevent the user from creating "pages" with reserved real controller names? So where I might have a controller accessed like: www.site.com/user/3, I would need to prevent the users from creating a page called "user" so there is no ambiguity when trying to decide whether this is a controller or a page to be called from the default master "page" controller.

Have I made things any clearer?

I had a quick look through the user guide for any reference to this "__call()" feature, and can't find anything on the subject, can you shed any light on that?

Regards,

Andy
#5

[eluser]jedd[/eluser]
[quote author="alphane" date="1253764145"]
Have I made things any clearer?
[/quote]

Slightly. The problem I had with 'page' is you were using it to describe different things, in the one sentence!

Quote:I had a quick look through the user guide for any reference to this "__call()" feature, and can't find anything on the subject, can you shed any light on that?

I keep a documentation browser open all the time that has the CI UserGuide on one tab, the MySQL doc on the next, PHP on the third, and a git cheatsheet on the fourth.

In this particular case I'd point you at my third tab.

Remember, always, that CI uses PHP - and that means you can too.

For example ...
Quote:Where this is confusing me is that I can’t use a standard method as I will have an unknown amount of URI segments being passed to a given function, so I need to manually grab the URI segments and try to find a match in the database and work my way back through valid pages

You may want to look up the func_get_args() and func_num_args() functions, and see if they might be of assistance in dealing with your unknown number of URI segments. I've not used them before, but they seem fairly straightforward.

I'd encourage you to have a 'wiki' controller, and everything under http://site.name/wiki/ ... used some feature (maybe one of the ones I've mentioned) to give you this virtual mapping of All Things, but still provides for hard coded 'about us' (to pick a bad example) pages. It means you can still have an About_Us page that's owned and managed by your wiki - it'll just be different to the static one that your about_us() controller would offer. As I say, 'about us' is a very poor example, but there will definitely be occasions where you want some semi-static, or at least non-wiki-managed pages.
#6

[eluser]guillermo, out of repose[/eluser]
__call() is a mechanism in PHP used for overloading. Codeigniter's _remap() method, in conjunction with some changes in your routing configuration file, will enable you to do what you want. I've done this same thing before and used it on several large sites. If you read up on the _remap() method, you'll note that it is always called, so you really don't need to use the __call() method.

Your database setup is key, though. We can talk more about that off the forum Wink.
#7

[eluser]jedd[/eluser]
I hasten to add that when I wrote this:

[quote author="jedd" date="1253763171"]
You could also do some pretty rude things with __call(), too.
[/quote]

- it was written in the context of a warning, not as an encouragement.

Rude things, at least when they involve programming languages, should generally be eschewed.
#8

[eluser]BrianDHall[/eluser]
Jedd, you use your mouth prettier than a $20 dollar...err, nevermind. (I love Blazing Saddles, sue me)

As to the op, I do something very similar to this on a site of mine.

My trick? The only thing that matters is the last segment. Last segment not a valid page? Then try the one right before it, etc, until you exhaust them in which case someone is screwing with the url Smile

So I basically use this little fact to build pure vanity strings, primarily for seo purposes. So I might have keyword.mysite.com/keyword_keyword/keyword_keyword/somemore_keywords/theactualpage.html

For this sort of deal you would route everything not in specified controllers to a special controller that would handle the routing to the real page - or, if you prefer, use _remap to handle the "no other controller fits this so what do I do now" function. Or, use something you can look for with a regex in the url, such as mysite.com/fakeurl-keyword/...etc. Then in your routing rule of there is "fakeurl-" then route it specially.

My advantage was I only wanted to do this with one particular controller, but the principal is the same.

To answer your other implied question, there is no super-simple elegant way of handling what you want, because you want something that the basic url structure of CI was not built to handle. This does not mean it can't handle it, but you will basically have to build your own routing rules to construct a different structure. The advantage of CI is it is more than happy to ablige, but it will be a fair bit of core over-riding to make it happen.

You might just find it not really worth it to be quite that picky and instead settle for something not quite exact but still doable. For instance, you might want to have mysite.com/controller/function/parent-page/child-page/grand-child-page. In your function you use the 'last segment' trick, and you just manually build your page navigation/links to have your desired structure.




Theme © iAndrew 2016 - Forum software by © MyBB