Welcome Guest, Not a member yet? Register   Sign In
Passing rooted url-segments to controller variables
#1

[eluser]taig[/eluser]
Hi (:

On my website I want the user to be able to access a page like this:

http://www.example.com/music/newcomer/ or
http://www.example.com/music/newcomer/sort_by/title/z-a or
http://www.example.com/music/newcomer/page/4 or
http://www.example.com/music/newcomer/pa.../title/z-a

So, obviously the information stored in the segments can be on several positions what makes it harder to call them via segment(n)-function.

Therefore I added a route-entry:
Code:
$route['(:any)/(:any)/sort_by/(:any)/(:any)'] = "$1/$2/page/1/sort_by/$3/$4";
While my controller looks like that:
Code:
function newcomer($page = null, $page_number = 1, $sort_by = null, $category = 'release', $sorting = 'asc') { ... }

Seems to be working fine - if I call http://www.example.com/music/newcomer/sort_by/title/z-a now everything is working as it should. But somehow (I guess it's some rooting issue) the controller is now passing wrong variables. If I echo all variables from the controller they've now got these values:
Code:
$page: 'page'
$page_number: '3'
$sort_by: 'page'
$category: '1'
$sorting: 'sort_by'
And the links generated to the next page look like this http://example.com/music/newcomer/page/2/page/1/sort_by.

Somehow the problem doesn't occur if I use this root:
Code:
$route['music/newcomer/sort_by/(:any)/(:any)'] = "music/newcomer/page/1/sort_by/$1/$2";

I hope someone got a clue for me (: Maybe I'm using wrong functionalities for my intention? I know I could use rsegment(n) after rooting to get the correct values but I really prefer the style of passing them to the controller. Furthermore if I'd use rsegment(n) calling http://example.com/music/newcomer/page/2 the links to new pages are automatically like http://example.com/music/newcomer/page/4...elease/asc instead of leaving it to http://example.com/music/newcomer/page/4 and sorting with preset settings. I don't want them to blow up that unnecessary!

Smile
#2

[eluser]WanWizard[/eluser]
Make sure that your segments always contain a param/value pair, then it can be as simple as
Code:
// fetch the URI parameters into an assoc-array
$segments = $this->uri->uri_to_assoc();

foreach ($segment as $param => $value)
{
   switch ($param)
   {
        case "sort_by":
            // do something with $value
            break;
    }
}

This allows you to be completely free in the sequence in which the parameters appear.
#3

[eluser]taig[/eluser]
Thank you WanWizard,

your suggestion seems to make sense. As long as there are no other suggestions I'll do it that way (:

However, it still rankles me that the parameters aren't submitted correctly to the controller.. (;
#4

[eluser]WanWizard[/eluser]
What do you mean by "the parameters aren’t submitted correctly to the controller.."?
#5

[eluser]taig[/eluser]
Well, if I open the page
Code:
http://www.example.com/music/newcomer/page/3/sort_by/title/z-a
the Controller
Code:
function newcomer($page = null, $page_number = 1, $sort_by = null, $category = 'release', $sorting = 'asc') { ... }
has the values
Code:
$page: 'page'
$page_number: '3'
$sort_by: 'page'
$category: '1'
$sorting: 'sort_by'
What's obviously totally wrong. And as mentioned before the problem does not occour if the rooting is
Code:
$route['music/newcomer/sort_by/(:any)/(:any)'] = "music/newcomer/page/1/sort_by/$1/$2";
instead of
Code:
$route['(:any)/(:any)/sort_by/(:any)/(:any)'] = "$1/$2/page/1/sort_by/$3/$4";
#6

[eluser]WanWizard[/eluser]
Offcourse it doesn't happen with your first route, as that route is ignored because it doesn't match.

You're caught in regex hell here. Your second rule basically says: I have some characters, the literal /, some more characters, the literal /sort_by/, some more characters, the literal /, and some more characters.

With your example URL, the first (:any) matches 'music/newcomer/page', the second one '3', the third one 'title' and the last one 'z-a'. So your routed URI becomes 'music/newcomer/page/3/page/1/sort_by/title/z-a'.

The router library replaces '(:any)' with '.+', which is greedy, meaning it will grab as much as it possible can, given the source string. So it doesn't stop at the first slash in the URL, it grabs as much as possible, till it finds a slash, followed by some characters, followed by '/sort_by/'.
#7

[eluser]taig[/eluser]
Thanks a lot for your detailed explanation! Guess its safer to write own RegEx then.

At least
Code:
$route['(music|literature|movies|videogames)/(newcomer|recently_published|last_added)/sort_by/(title|creator|release)/from/(a-z|z-a)'] = "$1/$2/page/1/sort_by/$3/from/$4";
is doing quite a good job now! Well, it looks kinda ugly..

Would you agree with that solution or do you think it's not clever to handle the problem like that?

Thanks anyway, you did quite a good job! (:
#8

[eluser]WanWizard[/eluser]
I would dump all rules, dump the static parameters from the method, and use either the solution I posted earlier, or grab the method arguments by using func_get_args().

If you have a pretty standard usage of URI parameters, you can also create a library (or model). Add methods like get_sort_by(), that return the validated sort_by value, no matter where it occurs in the URI, or a default value if not defined:
Code:
function controller_method()
{
    // load the library
    $this->load->library('splituri');

    // check the sort order
    if ( $this->splituri->get_sort_by()  == 'title' )
    {
        $this->db->order_by('my_title');
    }
}




Theme © iAndrew 2016 - Forum software by © MyBB