2010-04-16 76 views
5

这里是控制器的功能的快速概览在大多数的应用程序:CodeIgniter:特定功能应该去哪里?

  • 控制器加载特定的模式,从它得到的数据,格式化数据和格式化的数据传递到视图。

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

问题:

搜索控制器可以做搜索,动态加载模型为每个记录类型,并从模型中获取的数据。数据需要格式化时出现问题。我试图从搜索控制器加载特定的控制器,这是造成问题的原因。

怎么办? PS:我试过使用'Wick'库,但是当控制器的格式函数尝试使用它自己的模型和会话对象时失败,从而给调用非对象成员造成错误。

回答

2

多重构和试验/错误之后,看来,最好的方式来实现上述是这样:

  1. 保持格式函数从所有其他控制器来源的基本控制器。格式选项与数据对象一起作为参数传递给函数。

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

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

我想我可以说我会坚持使用模型只用于与数据库交互,并让其他一切都由控制器完成。如果任何人仍然有更好的解决方案,我是全部耳朵。

0

这听起来像你想使用的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 
    } 
} 
+0

正如我所看到的,该模型通过返回视图选项直接影响视图的输出。这打破了MVC模式? – Samnan 2010-04-17 05:59:42

0

一般来说,你不能加载另一个控制器从内部控制在CodeIgniter中使用oller(虽然有mods可以让你做这样的事情)。

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

下面是CodeIgniter文档Creating Your Own Libraries中的一个页面,它解释了细节和约定。另外,如果一个类是矫枉过正的,那么创建辅助函数是更轻量级的方法。

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

一旦你格式化你的数据,你可以加载任何控制器的任何观点,所以你还是应该有所有的可重用性,你需要这样你DRY(不要重复自己)

+0

如果我试图从第二个控制器调用的函数使用它的属性和模型来完成它的工作,该怎么办?我是否将所有功能移动/复制到助手/库? – Samnan 2010-04-17 05:40:57

+0

如果这是需要的,是的。这可能是因为你试图在控制器类中做太多事情。我不知道你的代码的所有细节,但它听起来像你有你的控制器中的这些元素.. 1.检索您的数据(型号) 2.格式化您的数据 3.将数据传递到视图用于显示.. 控制器应该将这些操作绑定在一起。 1和3是由框架提供的,但在2中,您可以将涉及格式的所有控制器都拿出来,并为其创建可重用的库。 同样,我不知道你的代码的细节,但这是我将如何处理它。 – JohnWright 2010-04-20 18:04:28

0

有几个简单的方法基于什么更简单的原则(而非完美DRY)。下面是我使用CodeIgniter的一种替代方法:

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

控制器不是您自己的PHP代码重用的好选择:它们将操作和资源请求路由到事物本身。它们的目的是通过HTTP调用,使用你提出的URI接口。从代码调用它们是您想要避免的耦合。也就是说,从JavaScript(或通过cURL)重新使用控制器是一种伟大的,分离的方式来重用任何Web框架中的东西。

+0

嗨布鲁斯,这种观点在控制器中很常见。这是控制器内部导致问题的格式化功能。如果不清楚,请再次阅读我的问题。至于你所建议的搜索模型,它将意味着一个模型,它知道整个数据库的每个表结构和字段,我认为这并不是真的有用。 – Samnan 2010-04-20 10:30:16