Welcome Guest, Not a member yet? Register   Sign In
Create great-looking URLs, depending on which city you selected
#1

[eluser]KevinSjoberg[/eluser]
Hello guys,

I have a site where I allow the user to select the city before continuing. What I want to accomplish is to whichever city they choose will create the following URL structure:

Code:
City / controller / method

At the moment the user get to a splash screen and may choose a city they want. The selection is saved in a cookie that I use later. I hard code my URLs as follows:

Code:
anchor ($this->uri->segment(1) . '/ controller / method');

just wanted to hear if there is an easier way to do this, and if so, how can I validate such URL as well.

Sincerely, Kevin Sjoberg
#2

[eluser]treeface[/eluser]
Hi Kevin,

I'm not entirely sure what you're asking for. Do you have a route set up for this in your routes.php config? If not, you should take a look at CodeIgniter's URI Routing class.
#3

[eluser]KevinSjoberg[/eluser]
Hi Treeface,

At the moment I've set up routes as follows:
Code:
$route['(:any)/specific_controller_name_here/(:any)' = 'specific_controller_name_here/$2';

But I'm not sure if that's a good way of accomplish what I want.

I also would like some hints about validating the city in the URL, to check if it exsist and so fourth.
#4

[eluser]treeface[/eluser]
Let's see...

So you want a URI like "montreal/maps/display" to route to this: "maps/display/montreal"? If so, this would be the way to do that:

Code:
$route['(:any)/specific_controller_name_here/(:any)' = 'specific_controller_name_here/$2/$1';

//and this might also be necessary...

$route['(:any)/specific_controller_name_here' = 'specific_controller_name_here/$1';

With a $1 at the end which represents the city name being passed either to your "maps" index function or to the specific function that is specified in your link. Then in your "maps" controller, your "display" function would look something like this:

Code:
function display($city) {
    //call your model to see if the city exists in your DB...if it does, load the view, if it doesn't, load a 404 page or something...
}

Let me know if this isn't what you were asking for.
#5

[eluser]KevinSjoberg[/eluser]
It was not exactly what I meant.

The site that the user visits will show other contact information, pictures and so on, depending on which city you've selected. I have chosen to build the URL structure as follows:

Code:
www.example.com/chosen_city/controller/method

I want to build up my routes so I always have the above structure and some hints of how to validate that the city actually exists.
#6

[eluser]treeface[/eluser]
Ah so you want a way to <i>create</i> this url structure given a city? If that's the case (and if you don't feel comfortable putting it right into your views), you can make a library to help you construct them. See the user_guide about how to create libraries.

As I said above, the way to validate if a city actually exists is to pass the value to your controller and compare it to your 'cities' table in your database. Maybe you have a model function in your "cities" model that looks like this:

Code:
function checkCity($city) {
    $qStr = "SELECT * FROM cities WHERE city=?";
    $q = $this->db->query($qStr, array($city));

    return ($q->num_rows() > 0);
}

Then in your "specific_controller_name" controller you have your "specific_method" that looks like this:

Code:
function specific_method($city) {
    $this->load->model('cities');
    if ($this->cities->checkCity($city)) {
        //load the view you want to load
    } else {
        //load the 404 page or a page saying the city doesn't exist
    }
}
#7

[eluser]KevinSjoberg[/eluser]
Thanks treeface,

But then I would have to pass the city as an argument to every method in my entire projects, and the URL structure wouldn't be the same aswell, or am I wrong?

Instead of
Code:
city/controller/method
I would have
Code:
controller/method/city

Right?

And how would that work for let's say four different controllers?
#8

[eluser]treeface[/eluser]
You wouldn't pass city to every method, only for the URIs structured like this: (:any)/mycontroller/mymethod.

Ok so let's get down into the specifics a bit more to try to get at the root of the problem.

Let's say you have three controllers where city is an important parameter: maps, directories, and videos. In maps and directories, you need the city argument for all methods, including index(). To handle that, you'd do this:

Code:
//maps
$route['(:any)/maps/(:any)' = 'maps/$2/$1';
$route['(:any)/maps' = 'specific_controller_name_here/$1';

//directories
$route['(:any)/directories/(:any)' = 'directories/$2/$1';
$route['(:any)/directories' = 'directories/$1';

Now let's say you don't want the city param to pass to all of your videos controller methods. Then you'd do something like this:

Code:
$route['(:any)/videos/cityvideos' = 'videos/cityvideos/$1';

Now if you want to cut off the "cityvideos" entirely so that your link looks like: example.com/montreal/videos, it's going to require a little bit of trickery either way and both ways would require various assumptions. You can do it the way you're doing by using the uri string componenets, or you can set up a route like this:

Code:
$route['(:any)/videos'] = 'videos/$1';

At this point you'll be getting $city as a parameter in your index function in the videos controller. Here you can run $this->cities->checkCities($city) to see if it's a valid city or not. However, this approach comes with the implicit assumption that you will have no other places in your code where you use /videos and the second uri segment. If I were designing this, I'd set it up a little more like this:

Code:
example.com/cities/montreal/videos

And a router like this:

Code:
$route['cities/(:any)/(:any)'] = 'cities/$2/$1';

This allows for maximum flexibility with minimal code and allows people to see specifically that "montreal" is a city and that they are being linked to the videos for that city.




Theme © iAndrew 2016 - Forum software by © MyBB