【问题标题】:How to route identical Codeigniter Controllers如何路由相同的 Codeigniter 控制器
【发布时间】:2012-09-21 01:41:44
【问题描述】:

我的 Codeigniter 项目有一长串相同的类别,每个类别都有许多相同的方法。

为了使其动态和简洁,我使用 _remap 函数在控制器中加载相同的方法。现在我正在尝试复制控制器

例如我的控制器 Antelope.php Bat.php Cuckoo.php Dog.php Elephant.php... Zebra.php 下面都有这个格式(我用_remap把所有类似的方法都浓缩成一个)。

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Antelope extends CI_Controller {

    function __construct() {
        parent::__construct();
    }

    private function _remap($method, $params=array()){
       $this->animal = ucwords($this->router->fetch_class());
       $allowed_methods = array("Tame", "Buy", "Sell", "Gift");
       if (in_array($method, $allowed_methods)):
           // Model zoo has been autoloaded      
           data["foobar"] = $this->zoo->get_data($this->animal, $method);
           // Stuff goes here
       else:
          $this->index();
       endif;
    }

    public function index(){
       // Stuff goes here
    }
}

/** End of file Antelope.php **/

重新映射对 Antelope 及其所有重新映射的方法都有效,但是我有没有办法将相同的方法应用于所有其他文件 所以我可以只使用一个 Animal.php 控制器文件来代替强>?

我想我可能会使用routes.php,但是控制器列表太长了;如果我明确列出每个“动物”路由,我将在路由文件中有数百行。

有什么办法吗?

编辑:“动物类型”列在数据库中,并且会随着时间的推移不断增加。我不想继续重新访问该项目以创建新控制器或为数据库中的新元素添加新类!这就是我想使用动态路由方法的原因。此外,该项目是重新设计的网站,因此 http://www.website.com/antelope/buy/3 等 URL 需要保持不变。

【问题讨论】:

  • 为每种动物类型配备一个控制器似乎有点矫枉过正。你确定你不能用一个控制器来做吗(在我看来你可以)。
  • 实际上,我不能。这是对我想要实现的目标的过度简化的描述。谢谢!
  • 糟糕。我的意思是,是的,我想使用单个控制器。但不,我不认为这个问题是微不足道的。

标签: php codeigniter routing controller remap


【解决方案1】:

您可以尝试以下几个选项:

  1. 拥有一个 Animals.php 基类并从该基类继承所有其他类别

Animal.php

class Animal extends CI_Controller {
    //Your _remap() and other methods
}

Antelope.php Bat.php Cuckoo.php Dog.php Elephant.php... Zebra.php

require_once 'animal.php';

class Antelope extends Animal {
    //Antelope inherits its methods from Animal, so this is blank 
} 

此方法需要您拥有 100 个几乎空白的控制器文件(每个动物/类别一个),因此动态性不是很大,但允许您在 Animal 基类中实现 __init() 方法并在子类,允许您设置类别中的任何偏差(即腿数等)


  1. 为所有动物使用一条路线

routes.php

//default index route http://www.sample.com/animal/type
$route['animal/(:any)']  = 'animal/reroute/$1/index';

//method route http://www.sample.com/animal/type/method
$route['animal/(:any)/(:any)']  = 'animal/reroute/$1/$2';

动物.php

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Animal extends CI_Controller {

    function __construct() {
        parent::__construct();
    }


    public function index(){
       // Stuff goes here
    }

    public function reroute($animal, $method) {
       //Check the $animal is valid
       //Check the $method is valid
       //Do stuff   
    }


}

/** End of file animal.php **/

这有点动态,因为您可以从数据库中加载有效动物的列表,但 URL 不会像 http://www.sample.com/bat/sellhttp://www.sample.com/animal/bat/sell 那样干净

【讨论】:

  • 谢谢你,Re0sless。想到了第一个选项,但我放弃了它,因为它确实需要许多几乎为空的控制器文件。我喜欢您提供的第二个解决方案,特别是因为我可以从数据库中加载动物列表,但有两个问题是:(1)URL 需要像site.com/bat/sell 一样干净,因为这是一个网站重新设计,太多了断开的链接会出现。 (2) 网站上存在其他“非动物相关”控制者。附:您认为我可以使用上面的解决方案 2,然后使用 Apache htaccess 清理 URL 吗?这会影响性能吗?
  • 您可以使用 .htaccess 重新路由到动物控制器,但这只会转移问题,因为 htaccess 必须有一个要查找的动物列表,或者一个列表控制不重新路由。我不知道它会对性能产生多大影响,但是您所做的任何事情(包括 codeigniters 路由)都会产生一些负面影响,因为服务器需要执行额外的工作。
【解决方案2】:

只需创建一个类来继承

class Animal extends CI_Controller {
   function __construct() {
        parent::__construct();
    }

    public function _remap($method, $params=array()){
       $this->animal = ucwords($this->router->fetch_class());
       $allowed_methods = array("Tame", "Buy", "Sell", "Gift");
       if (in_array($method, $allowed_methods)):
           // Model zoo has been autoloaded      
           data["foobar"] = $this->zoo->get_data($this->animal, $method);
           // Stuff goes here
       else:
          $this->index();
       endif;
    }
}

class Antelope extends Animal {
    public function index(){
       // Stuff goes here
    }
}

【讨论】:

  • 感谢您的回答,但真正的问题是“动物类型”是从数据库加载的,并且会随着时间的推移而不断增加。我不想继续重新访问该项目来为数据库中的新元素添加新类!
  • ...但是您有每个动物的档案吗?你自己说的??即 bat.php、antelope.php
  • 是的,我使用数据库中的名称手动复制和粘贴 Antelope.php 中的代码以满足我的最后期限。然后我意识到这不是一种可持续的方式。随着项目的发展,我需要不断地重新审视它以创建新的控制器或类!
【解决方案3】:

诀窍是要意识到动物类型是可变的,并且您正在尝试将其映射到静态文件。 不要这样做。只需将动物作为第一个参数传递给索引函数。这就是参数的用途:变量。

class Animal extends CI_Controller{
    function __construct(){
        parent::__construct();
    }

    function index($animal){
        echo "I'm the {$animal}!";
    }
}

并设置单条路线:

$route['animal/(:any)'] = "animal/index/$1";

现在,如果您前往http://localhost/yourapp/animal/antelope

CodeIgniter 会回显“我是羚羊!”

评论后编辑:

CodeIgniter 在你的路由文件中从上到下遍历,并在找到有效的路径时中断。您可以将其放在config/routes.php 文件的底部

$route['(:any)/buy/(:id)'] = "animal/$1/buy/$2";
$route[':any'] = "animal/index/$1";
//etc

您需要重新路由上面的所有其他控制器。

【讨论】:

  • 感谢您的回答。但正如我所说,该项目是一个网站重新设计,所以像 website.com/antelope/buy/3 这样的 URL 需要保持不变,而不是更改为 website.com/animal/antelope/buy/3(这是我上级的限制)。
  • 非常感谢!我会接受这个答案,因为它让我最接近我想要的。但是,它并没有真正解决我的问题。正如我在 Re0sless 的评论中所说,'2) 网站上还有其他“与动物无关的”控制器。您的方法意味着我需要在上述路径文件中列出所有与动物无关的控制器。叹。只是担心可持续性和低维护成本,因为我把它交给了。再次感谢。
  • P.S.我用“动物”来解释问题。该网站上还有许多其他类别,而不仅仅是“动物”。其他类别的结构不同,但 /buy/id URL 也相似。
猜你喜欢
  • 2015-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-24
  • 2016-03-29
  • 1970-01-01
  • 1970-01-01
  • 2012-11-01
相关资源
最近更新 更多