【问题标题】:Load url from routes for a controller从控制器的路由加载 url
【发布时间】:2013-05-14 22:41:59
【问题描述】:

由于 CodeIgniter 开箱即用,它支持每个唯一网址使用一个控制器。 所以,假设我的 routes.php 文件中有以下网址:

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

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

我的网址将如下所示:

  1. 产品列表 => http://www.mywebsite.com/products
  2. 产品详情 => http://www.mywebsite.com/product/my-custom-product

在我构建产品列表的控制器中,我为每个产品创建 url,如下所示:

$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);

但是每个 url 都有太多的冗余。每次我想在某处回显时,我都必须写下 url。如果我想更改 url,我必须打开每个 php 文件并将它们全部替换。

问题:难道没有我可以用来调用控制器名称及其方法的“方法”,并且“方法”会返回该控制器的 url 吗?像这样的:

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

其中第一个参数是控制器及其方法(因为 url 模式只存在一个控制器),第二个参数是 url 部分的数组。

【问题讨论】:

  • 不要将^...$ 放在你的路由中——Router 类会为你做到这一点。
  • 现在我在_parse_routes() 方法中看到了它。谢谢。我希望我能再次投票给你:)

标签: php codeigniter


【解决方案1】:

您正在寻找的是一种称为反向路由的功能。目前 CodeIgniter 中还没有内置这样的功能,而且我能找到的任何库都是在 2010 年完成的,所以可能不是最新的。

但是,那里有与反向路由相关的文章和拉取请求,因此,如果您有足够的经验,您应该能够为您的应用程序组合一些东西。

否则,您最好的选择可能是为最常用的 URL(例如您的产品)创建帮助程序。所以你可以做echo product_url('my-product-name');这样的事情,你只需要在帮助函数中调整URL。

【讨论】:

  • 在这之后我不知道如何在谷歌上查看。谢谢(你的)信息。并且构建一个助手绝对是反向路由的好方法。这样,我将只有两个文件中的网址。但是如何替换正则表达式 url?正如互联网所暗示的那样,使用正则表达式,我最终会回到我第一次提出问题时所在的位置。
  • 对 SO 的评论有点冗长。本质上,反向路由功能对每个路由/目的地都有一个独特的“id”,因此您可以指定应生成的链接。然后,该 ID 可以接受 X 个参数,例如通配符路由。我知道这有点含糊,但看看一些现有的解决方案(用于 CI 或其他框架),你应该会有一个想法。
  • 我对此有一个想法,我实际上是在一个框架(不是 codeigniter)上构建了一个反向路由,但有一些缺陷。基本上,我假设用户在编写 url 正则表达式(例如在 routes.php 中)时不会出错,我只是得到括号并从数组中替换它们。数组中的第一个键替换第一组括号。它不是正则表达式,它使用的是strposstr_replace。我假设 codeigniter 社区已经有一个库、助手等。
  • 这基本上就是您最终要创建的内容,是的。只需使用一组参数来填充路由中的通配符点。不,CI 中没有任何东西可以帮助这个过程。 strposstr_replace 或类似的方法就可以了。
【解决方案2】:

我不确定您到底想要什么,但您可以使用 _remap() 函数覆盖控制器行为;

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

例如

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

【讨论】:

  • 我想要什么:我不想用实际的 url 调用 site_url 函数,而是想用 function (或助手)调用 controller/method 作为参数,它会返回实际的 url。
【解决方案3】:

您可以在产品控制器中使用默认查找功能(在 CI Routing docs 中描述;查看示例)。

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

一个以“产品”为第一段的网址,第二段为任何内容 将重新映射到“目录”类和“product_lookup” 方法。

或者您可以使用数据库驱动的路线。
将表 product_slugs 添加到您的 MySQL 数据库中:

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;

将 application/config/routes.php 中的代码替换为以下代码:

$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;
}

您所要做的就是在创建产品条目时创建一条记录,然后就完成了:

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

【讨论】:

  • 你误解了我的意思,因为我在解释事情时遇到了问题:)。请阅读@Charlie 的第一个答案。
  • 我希望你没有在网站上这样做。在路由中,每个路由都有一个正则表达式匹配(称为 _parse_routes 的方法)。正则表达式很慢。想象一下,您的商店中有 10000 种产品,而您会要求最后一种...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-04
  • 1970-01-01
相关资源
最近更新 更多