2012-07-23 26 views
2

我目前正在开发一个Zend Framework项目,其中用户遍历应用程序的最终结果为他们提供了一个包含其结果的大表。该表格可以包含不同数量的行,其中大部分是作为计算结果生成的。到现在为止还挺好。以面向对象的方式构建复杂条件表PHP

第一个;尽管很小的障碍,但是桌子需要水平放置。也就是说,标题在第1列中,每个附加列代表一个数据实体项目。例如:

 
Forename | James | Richard 
Surname | Jones | Mayfair 

同样,这不是问题。当我来整理桌子时,问题就出现了。使用构建器模式,我有三个类:表,组和行。它们可以像这样使用:

$table = new Table($attribs); 
$group = new Group(); // Nothing special about groups, they're just there for helping with presentation 

$row = new Row(); 
$row->setTitle('Forename') 
    ->setData(array('item1' => 'James', 'item2' => 'Richard')) 

$row2 = new Row(); 
$row2->setTitle('Surname') 
    ->setData(array('item1' => 'Jones', 'item2' => 'Mayfair')) 

$group->addRow($row) 
     ->addRow($row2); 

$table->addGroup($group); 

上面的代码片段出现在控制器的动作中。然后将表格对象传递给视图,并且我有一个视图帮助器,根据我自己的规范输出到表格。

然而,我所面临的挑战是,我已经结束了一个非常混乱的'结果'模型。例如,我有很多的:

$group->addRow($this->_resultsModel->getSurnameRow()); 

的“_resultsModel”属性是它包含了很多的做方法的对象:

public function getSurnameRow() 
{ 
    $row = new Row(); 
    $row->setTitle('Surname'); 
    $row->setData($this->_getAssociateArrayOfSurnames()); 
    return $row; 
} 

此外,结果对象延伸的结果摘要该类包含原始数据的访问器,设置器和计算方法。这些“计算”方法中的每一个都会返回一个可以分配给行对象的关联数据数组。结果对象和抽象类都是很长的,而且看起来很不一致。

所以总结......我已经结束了一个大型的结果模型,它完成所有的计算并返回所有的行对象。虽然它确实有效,但我确信有更好的做事方式。我应该在控制器中建立行吗?我是否应该只从模型中调用计算?有没有人有任何抽象这样的东西的经验?

我很抱歉这是一个不好的解释。如果有人有任何问题可以发布,请告诉我。

回答

0

首先,控制器内部不应该有太多逻辑 - 控制器可以处理模型的输入并将结果转发到输出(视图),而不是计算内容。

第二:你的结果有很多其他的事情要做,为什么它必须处理表格表示?另外,为什么它必须有很多单独的函数,这些函数仅在字符串中有所不同?

我想我会用声明数组一起做一些事情:那就是,我收集了声明数组是这样的:

$table_description = [ 
    'group1' => ['surname', 'firstname', 'whatever'], 
    'group2' => ['other', 'rows', 'as', 'needed'] 
]; 

,并建立一些东西,解析这个描述与实际数据填充起来(如果需要使用反射)

主要问题是:形式遵循函数,算法遵循数据结构。

如果你有一个数据结构,它被分成表,组和行,那么你很可能有一个相同的算法。

第二个问题是:这种变化可能发生在哪里?如果表格方案可以很容易地改变,把它们放到一个“配置”(一个描述符)中。如果行的格式可以很容易地更改,请确保它们是自我格式化的(或者有人知道如何请求格式化程序,但不知道该行实际包含的内容)

一个好主意是能够回退为默认值:即,如果大多数行以默认方式构造,然后确保你能够使用默认的方法,如:

class Row { 
    public $formatter; 
    private $data_assoc; 
    private $title; 
    public function __construct($title, $data, RowFormatter $formatter=NULL){ 
     if ($formatter == NULL){ 
      $this->formatter = DefaultFormatter::getInstance(); 
     } 
     /*set title, data_assoc...*/ 
    } 
    public function setFormatter(RowFormatter $formatter){/*obvious*/} 
    public function format(){ 
     return $this->formatter->format($this->data_assoc); 
    } 
} 

现在看来,你resultsModel有太多许多责任,你有这些前缀名称(getSurnameRow) - 为什么应该resultsModel知道行?此外,关联数组(地图)是相当好的构造,特别是在PHP中。为什么getData('姓氏')不够?为什么Row不能从标题和关联数据构建自己?

如果你想做同样的事情,但具有不同的属性,请使用枚举或字符串。如果您有时需要插入某些东西,请使用工厂,该工厂根据属性名称查找索引表,如果不是例外情况,则会返回到默认实现。象,的getX,的getY - 只要它的两个属性,简单正交这样

$row = RowFactory::getRow('Surname'); 
$row->setData($this->data['Surname']); 

代码重复的罚款。但有了无限的属性,我想这只是重复。