简体   繁体   中英

Load url from routes for a controller

As CodeIgniter comes out of the box, it supportes one controller for each unique url. So, let's say i have the following urls in my routes.php file:

$route['default_controller']  = "homepage";
$route['404_override']        = "homepage/not_found";

$route['^products$']          = "product/list";
$route['^product/(:any)$']    = "product/details";

My urls will look like this:

  1. product list => http://www.mywebsite.com/products
  2. product details => http://www.mywebsite.com/product/my-custom-product

In the controller where I build the products list, I create the url for each product like this:

$this->db->from('products');
$products_result = $this->db->get();

$data['products'] = array();
foreach ($products_result->result() as $row)
{
    $data['products'][] = array(
        'title' => $row->title,
        'image' => $row->image,
        'url'   => site_url('product/' . $row->url)
    );
}

$this->load->view('products/list_view', $data);

But there is too much redundancy for each url. I have to write the url every time I want to echo it somewhere. If I want to change the url, I have to open each php file and replace them all.

Question: Isn't there a "method" I can use to call the controller name and its method and that "method" returns the url for that one? Something like this:

build_site_url('product/details', array('my-product-url'));

where the first argument is the controller and its method (since only one controller exists for a url pattern), and the second argument is the array of url parts.

What you're looking for is a feature called reverse routing . There is no such feature built into CodeIgniter at this time, and any library I could find was done in like 2010, so probably not the most up-to-date.

However, there are articles and pull requests out there relating to reverse routing, so if you are experienced enough, you should be able to put something together for your application.

Otherwise, your best bet may be to create helpers for your most common URLs (like your products). So you could do something like echo product_url('my-product-name'); , and you would only need to adjust the URL in the helper function.

I am not sure what exactly that you desired, but you can override controller behaviour using _remap() function;

look: http://ellislab.com/codeigniter/user-guide/general/controllers.html#remapping

eg

public function _remap($method){
   if ($method == 'product/details') {
     ///do what you want to do
   }

You could either use a default lookup function in the product controller (described in the CI Routing docs ; look at the examples).

$route['product/(:any)'] = "catalog/product_lookup";

A URL with "product" as the first segment, and anything in the second will be remapped to the "catalog" class and the "product_lookup" method.

Or you could use database driven routes.
Add the table product_slugs to your MySQL database:

CREATE TABLE IF NOT EXISTS `product_slugs` (
  `id` bigint(20) NOT NULL auto_increment,
  `slug` varchar(192) collate utf8_unicode_ci NOT NULL
  PRIMARY KEY  (`id`),
  KEY `slug` (`slug`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1;

Replace the code in application/config/routes.php with the one below:

$route[ 'default_controller' ]  = 'main';
$route[ '404_override' ]        = 'error404';

require_once( BASEPATH .'database/DB'. EXT );
$db =& DB();
$query = $db->get( 'product_slugs' );
$result = $query->result();
foreach( $result as $row )
{
    $route[ $row->slug ] = 'product/detail/$1;
}

All you would have to do then is to create a record when you create a product entry and you're done:

INSERT INTO `product_slugs` (`slug`) VALUES ('name-of-the-product');

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM