【问题标题】:CodeIgniter: Where should a particular functionality go?CodeIgniter:一个特定的功能应该去哪里?
【发布时间】:2010-04-16 10:12:41
【问题描述】:

以下是大多数应用程序中控制器功能的快速概览:

  • 控制器加载特定模型,从中获取数据,格式化数据并将格式化后的数据传递给视图。

现在有一个搜索页面,需要对整个数据库(所有模型)进行搜索查询。它需要以列表的形式在单个页面上以特定格式输出显示每种类型的数据。

问题:

搜索控制器可以进行搜索,为每种记录类型动态加载模型,并从模型中获取数据。当需要格式化数据时,问题就来了。我正在尝试从搜索控制器加载特定控制器,这会导致问题。

怎么办?

PS:我尝试使用“Wick”库,但当控制器的格式函数尝试使用其自己的模型和会话对象时,它会失败,从而在调用非对象上的成员时出错。

【问题讨论】:

    标签: php codeigniter formatting uiviewcontroller dynamic-data


    【解决方案1】:

    经过多次重构和反复试验,似乎实现上述目标的最佳方法是这样:

    1. 将格式函数保留在派生所有其他控制器的基本控制器中。格式选项与数据对象一起作为参数传递给函数。

    2. 在每个派生控制器中创建一个静态函数,该函数返回数据的格式化选项。

    3. 在搜索控制器(它本身是从基本控制器派生的)内部,对于每个数据对象,调用其特定控制器的静态函数,该函数返回数据格式化选项,然后使用该函数为对象格式化查看。

    我想我可以说我会坚持只将模型用于与数据库的交互,而让其他一切都由控制器完成。如果有人还有更好的解决方案,我会全力以赴。

    【讨论】:

      【解决方案2】:

      听起来你想使用Factory design pattern

      把它变成一个图书馆:

      class MyModelFactory {
        static public function Factory($data) {
          $type = key($data);
          return new $type($data);
        }
      }
      

      现在,在您的控制器中,您可以执行以下操作:

      $model = MyModelFactory::Factory(array($_REQUEST['model'] => $_REQUEST));
      

      现在您有了 $_REQUEST['model'] 中指定的任何模型的对象。请务必为您的应用采取任何可能需要的安全预防措施,以确保用户有权使用他们请求的模型

      现在,由于您想使用通用方法和东西,您的模型可能应该基于抽象类/接口.. 所以而不是

      class MyModelOne extends Model {
        // stuff
      }
      

      您可能想要这样的东西,以确保您所需的方法始终可用:

      abstract class MyAbstractModel extends Model {
      
        protected $search_params;
      
        public function __construct($data = array()) {
           $search_params = $data['search_params'];
        }
      
        protected function GetSearchParameters() {
          return $this->search_params;
        }
        abstract public function GetData();
        abstract public function GetColumns();
        abstract public function DefineViewOptions();
      }
      
      class MyModelOne extends MyAbstractModel {
      
      
        public function GetData() {
          $params = array();
          $params[] = $this->db->escape_str($this->GetSearchParameters());
          // return whatever data you want, given the search parameter(s)
        }
        public function GetColumns() {
          // return some columns
        }
        public function DefineViewOptions() {
          // return some configuration options
        }
      }
      

      【讨论】:

      • 在我看来,模型通过返回视图选项直接影响视图的输出。这打破了 MVC 模式,对吧?
      【解决方案3】:

      一般来说,你不能在 CodeIgniter 的控制器中加载另一个控制器(尽管有一些模组可以让你做这样的事情)。

      我会尝试创建一个用于格式化数据的类并将其添加到应用程序/库文件夹中。然后在你的各种控制器中加载、使用和重用这个类。

      这是 CodeIgniter 文档Creating Your Own Libraries 中的一个页面,其中解释了详细信息和约定。

      另外,如果一个类是多余的,创建辅助函数是一种更轻松的方法。

      CodeIgniter 中库和助手的区别在于库是类,助手只是一组 php 函数。

      一旦你格式化了你的数据,你就可以从任何控制器加载任何视图,所以你应该仍然拥有你需要的所有可重用性,以便你 DRY(不要重复自己)

      【讨论】:

      • 如果,我试图从第二个控制器调用的函数使用它的属性和模型来完成它的工作。我是否将所有这些功能移动/复制到帮助程序/库中???
      • 如果需要的话,是的。可能是您试图在控制器类中做太多事情。我不知道您的代码的所有细节,但听起来您的控制器中有这些元素.. 1. 检索您的数据(模型) 2. 格式化您的数据 3. 将数据传递给视图进行显示..控制器应该将这些操作联系在一起。 1 和 3 由框架提供,但在 2 中,您可以从控制器中取出与格式化有关的所有内容,并为其创建一个可重用的库。同样,我不知道您的代码的详细信息,但这就是我的处理方式。
      【解决方案4】:

      有一些简单的方法基于什么是更简单(相对于什么是完全干燥)的原则。这是我在 CodeIgniter 中使用的另一种方法:

      1. 不要尝试加载多个控制器,而是重用搜索控制器中的视图片段(或搜索路径,具体取决于您使用的)。这需要为您的数据元素使用相同的命名约定,以便视图可以互换,但无论如何您都应该这样做。
      2. 不要使用多个模型进行搜索,而是添加一个知道可以搜索的内容的搜索模型。如果您想防止重复 SQL,请在模型之间重用 SQL(这可以使用常量或从磁盘加载 SQL)。

      控制器不适合从您自己的 PHP 代码中重用:它们将操作和对资源的请求路由到事物本身。它们旨在通过 HTTP 调用,使用您提出的 URI 接口。从代码中调用它们是您要避免的耦合。也就是说,从 JavaScript(或通过 cURL)重用控制器是在任何 Web 框架中重用事物的一种很好的解耦方式。

      【讨论】:

      • 嗨布鲁斯,视图在控制器中很常见。这是导致问题的控制器内部的格式化功能。如果您不清楚,请再次阅读我的问题。至于您建议的搜索模型,这将意味着一个模型知道整个数据库的每个表结构和字段,我认为这不是很有用。
      猜你喜欢
      • 2012-05-11
      • 1970-01-01
      • 1970-01-01
      • 2010-12-06
      • 1970-01-01
      • 2012-12-20
      • 1970-01-01
      • 1970-01-01
      • 2012-06-04
      相关资源
      最近更新 更多