Building Codeigniter URLs with variable segments - php

I have searched for the solution to my problem in CI user guide and on Stackoverflow as well but couldn't find. So, here is my problem.
I need to build SEO friendly URLs. I have a controller called "Outlets" and the view that I need to generate will have a URL structure like http://www.mysite.com/[city]/[area]/[outlet-name].
The segments city and area are fields in their respective tables and outlet_name is a field in the table "Outlets".
I am able to generate a URL like http://www.mysite.com/outlets/123 but how do I add the city and area name to the URL.

If all of your page use the same controller, in config/routes.php add this...
$route['(:any)/(:any)/(:any)'] = "outlets/$1/$2/$3";
$route['(:any)/(:any)/(:any)/(:any)'] = "outlets/$1/$2/$3/$4"; // fixed typo
In the controller you will want to remap the function calls because Codeigniter will be looking for functions with the names of the city and they will not exist.
http://codeigniter.com/user_guide/general/controllers.html#remapping
public function _remap($city, $area, $outlet, $options = '')
{
$this->some_function_below($city, $area, $outlet, $options);
}

Another alternative solution.
You can use URI segments. For an url like http://www.mysite.com/[city]/[area]/[outlet-name]
<?php
$this->uri->segment(3); // city
$this->uri->segment(4); // area
$this->uri->segment(5); // outlet-name
?>
and so on... See http://codeigniter.com/user_guide/libraries/uri.html for more details.

Related

Hide URL Segments But Want To Access These Segments In Controller Method In PHP Codeigniter

I Want To Hide URL Last Two Segments But Want To Access These Hidden Segments In controller Method In PHP Codeigniter.
This Is What I Currently Have
somewebsite/somemethod/dragonhunter2009720pblurayx264ytsag-greek/2/11
and accessing as
$this->uri->segment('3');
$this->uri->segment('4');
This Is What I Want To Have
somewebsite/somemethod/dragonhunter2009720pblurayx264ytsag-greek
But I Want To Access These Two Hidden Segment Values In Controller Method
as
$this->uri->segment('3');
$this->uri->segment('4');
How Can I Do This...
URLs do not provide any functionality to send "hidden" data. Therefore you cant hide the values in your url.
However you could use a middle class controller which redirects the user one extra time:
1. User makes request for /subtitles/xy/1/2 Request is answered by the following function:
public function middleware(){
$this->load->library('session');
//Local variables just for easier understanding
$seg2 = $this->uri->segment('2');
$seg3 = $this->uri->segment('3');
$seg4 = $this->uri->segment('4');
//Store the data in a session
$this->session->set_userdata('seg3', $seg3);
$this->session->set_userdata('seg4', $seg4);
redirect('subtitles/'.$seg2);
}
2. Codeigniter sets the session variables and redirects the user to another function which retrieves the values
public function handleSubtitles(){
$this->load->library('session');
//Retrieve the values from the session library
$seg3 = $this->session->userdata('seg3');
$seg4 = $this->session->userdata('seg4');
//Unset the values
$this->session->unset_userdata('seg3');
$this->session->unset_userdata('seg4');}
}
In order for this to work, you need to adjust your routing configuration too: application/config/routes.php
$route['subtitles/(:any)'] = "subtitles/handleSubtitles";
$route['subtitles/(:any)/(:any)/(:any)'] = "subtitles/middleware";
However I would just leave the to values in the URL... It'll make your work easier in the long run.
I suggest you to do dynamic routing for each subtitle in your CI's routing. For doing this, open your routes.php (application/config/routes.php) and write below code:-
require_once( BASEPATH .'database/DB.php' );
$db =& DB();
$query = $db->get('subtitles'); // select the table which have the data and url slug
$result = $query->result();
foreach($result as $r) {
$route['subtitles/'.$r->url_slug] = "subtitles_controller/{$r->url_slug}/{$r->id1}/{$r->id2}";
}
// Hint for above code : -
1. $r->url_slug :- use your table name for the slug .
2. $r->id1 and $r->id2 :- use your table name for both the ids .
3. subtitles_controller :- use the correct controller name from your application to where you want to route .
You can also rout even without any controller name in the beginning (without "subtitles"). For doing this, you can remove the subtitles from the beginning of routing.
eg: $route[$r->url_slug] = "subtitles/{$r->url_slug}/{$r->id1}/{$r->id2}";
now on your controller subtitles
function subtitles_controller($slug,$id1,$id2)
// here you can access the variables
}

How to apply codeigniter's URL_TITLE value to the URL

I'm completely new to ci,
I have a url something like this:
http://localhost/mvc/post/prod_id/1
And I want it to be:
http://localhost/mvc/post/my-best-product
So far I'm able to manage to route all that to home/post/ and learned the segment function also.
But my question is how do I really get the url_title out to the actual url.
I couldn't find any information on this particular subject. All I could find is how to use the url_title and how to route in ci. But they don't explain how we can actually change the base url name.
Please guide me to the right direction.
solution Example:
public function my_method($product_slug)
{
$product1 = "training-for-recruitment";
$product2 = "training-for-od";
if($product_slug==$product1)
{
$this->load->view('prod1');
}else if($product_slug==$product2)
{
$this->load->view('prod2');
}else{
show_404();
}
}
This is not what exactly I'm going to do. It is just for others to understand the workaround of Slugs.
Generate a unique slug for each of your product. Add a field for it on product table and every time, while selecting a product from table, use that slug instead of getting the product from primary id.
So, your function becomes like:
function product($product_slug)
{
//get product by slug from database
//load view page
}
Now, in config/routes.php
$route['your_controller_name/(:any)'] = "your_controller_name/product/$1";
You need to do this:
Set up some logic that translates "my-best-product" to "1"
Set up routing in CI that calls your 'prod_id' controller and passes the URI vars

CodeIgniter routing with app ID's and entry ID's

I'm new to CodeIgniter and going to be using it for building a sort of reusable application with multiple instances of an application. For example, each instance of the application will have an id "12345", and inside that instance, there will be entry IDs of 1,2,3,4,5,6,7,8, etc.
to do this, I think I will want to be able to using Routing to set up something like:
http://example.com/12345/Entry/Details/1
Where this URI will go to the Details page of the Entry of ID=1, inside application ID 12345. This would be a different group of entries from a url of, say, /12346/Entry/Details/1. Is this a routing rule that needs to be set up, and if so, can someone please provide an example of how this could be configured, and then how I would be able to use 12345, and 1, inside of the function. Thanks so much for your help, in advance.
My suggestion would be that you route your urls like this:
$route['(:any)/{controller_name}/(:any)/(:any)'] = '{controller_name}/$2/$3/$1';
so that the last parameter for the function is always the id of the app (12345/12346). Doing this means that your Entry controller functions will look like this:
class Entry extends CI_Controller
{
function Details(var1, var2, ..., varn, app_id){}
function Someother_Function (var 1, app_id){}
}
you will also need to add a route for functions that don't have anything but the app_id:
$route['(:any)/{controller_name}/(:any)'] = '{controller_name}/$2/$1'; //This may work for everything.
I hope this is what you we're asking...
Edit:
If you are only going to be using numbers you could use (:num) instead of (:any)
You can achieve a routing like that by adding this rule to the application/config/routes.php file:
$route['default_controller'] = "yourdefaultcontroller";
$route['404_ovverride'] = "";
// custom route down here:
$route['(:num)/entry/details/(:num)'] = "entry/details/$1/$2",
of course assuming your URI to be like the example.
In your controller "Entry" you'll have a method "details" which takes 2 parameters, $contestID and $photoID, where $contestID is the unique instance you're assigning, while $photoID is the other (assumed) variable of your url (last segment).
class Entry extends CI_Controller(
{
function details {$contestID, $photoID)
{ //do your codeZ here }
}
See URI routing for more info on that. You might also want to consider the __remap() overriding function, in case.

codeigniter routing

I am currently working on CMS for a client, and I am going to be using Codeigniter to build on top of, it is only a quick project so I am not looking for a robust solution.
To create pages, I am getting to save the page details and the pull the correct page, based on the slug matching the slug in the mysql table.
My question is however, for this to work, I have to pass this slug from the URL the controller then to the model, this means that I also have too have the controller in the URL which I do not want is it possible to remove the controller from the URL with routes?
so
/page/our-story
becomes
/our-story
Is this possible
I would recommend to do it this way.
Let's say that you have : controller "page" / Method "show"
$route['page/show/:any'] = "$1";
or method is index which I don't recommend, and if you have something like news, add the following.
$route['news/show/:any'] = "news/$1";
That's it.
Yes, certainly. I just recently built a Codeigniter driven CMS myself. The whole purpose of routes is to change how your urls look and function. It helps you break away from the controller/function/argument/argument paradigm and lets you choose how you want your url's to look like.
Create a pages controller in your controllers directory
Place a _remap function inside of it to catch all requests to the controller
If you are using the latest version of CI 2.0 from Bitbucket, then in your routes.php file you can put this at the bottom of the file: $routes['404_override'] = "pages"; and then all calls to controllers that don't exist will be sent to your controller and you then can check for the presence of URL chunks. You should also make pages your default controller value as well.
See my answer for a similar question here from a few months back for example code and working code that I use in my Codeigniter CMS.
Here's the code I used in a recent project to achieve this. I borrowed it from somewhere; can't remember where.
function _remap($method)
{
$param_offset = 2;
// Default to index
if ( ! method_exists($this, $method))
{
// We need one more param
$param_offset = 1;
$method = 'index';
}
// Since all we get is $method, load up everything else in the URI
$params = array_slice($this->uri->rsegment_array(), $param_offset);
// Call the determined method with all params
call_user_func_array(array($this, $method), $params);
}
Then, my index function is where you would put your page function.

CodeIgniter Routing

I am developing an ecommerce website with CI that has product categories and products. I want to route the URL so that it will go to the products controller, then run the getCategoryByName function for the first segment, then run the getProductByName for the second segment. Here is what I have:
URL:
products/docupen/rc805
routes.php:
$route['products/([a-z]+)'] = "products/getCategoryByName/$1";
$route['products/([a-z]+)/([a-z0-9]+)'] = "products/$1/getProductByName/$2";
But its not working. "docupen" is the category, and "rc805" is the product.
Thanks in advance.
Thank you all for your help. This is what I ended up with for what I needed.
$route['products/:any/:num'] = "products/getProductByID";
$route['products/:any/:any'] = "products/getProductByName";
$route['products/:any'] = "products/getCategoryByName";
My answer builds a bit on Colin's answer.
When I played around with the routes in CodeIgniter I came to the conclusion that the order of the routes was important. When it finds the first valid route it won't do the other routes in the list. If it doesn't find any valid routes then it will handle the default route.
My routes that I played around with for my particular project worked as follows:
$route['default_controller'] = "main";
$route['main/:any'] = "main";
$route['events/:any'] = "main/events";
$route['search/:any'] = "main/search";
$route['events'] = "main/events";
$route['search'] = "main/search";
$route[':any'] = "main";
If I entered "http://localhost/index.php/search/1234/4321" It would be routed to main/search and I can then use $this->uri->segment(2); to retrieve the 1234.
In your scenario I would try (order is very important):
$route['products/:any/:any'] = "products/getProductByName";
$route['products/:any'] = "products/getCategoryByName";
I don't know enough to route the way you wanted (products/$1/getProductByName/$2), but I'm not sure how you would create a controller to handle this particular form of URI. Using the $this->uri->segment(n); statements as mentioned by Colin in your controller, you should be able to do what you want.
You should use the URI class to retrieve the "docupen" and "rc805" segments from your url. You can then use those values in whatever functions you need.
For example, if your url is www.yoursite.com/products/docupen/rc805, you would use the following in your products controller to retrieve the segments and assign them to variables:
$category = $this->uri->segment(2); //docupen
$product = $this->uri->segment(3); //rc805
Then you can use $category and $product however you need to.
CodeIgniter routes don't work well with regex. They are supported, not I can never get them to work. It would be much easier to catch them like this
$route['products/(:any)'] = "products/getCategoryByName/$1";
$route['products/(:any)/(:any)'] = "products/$1/getProductByName/$2";

Categories