2

我目前正在开发一个 Zend Framework 项目,用户浏览应用程序的最终结果向他们展示了一个包含他们结果的大表。该表可以包含不同数量的行,其中大部分是作为计算结果生成的。到目前为止,一切都很好。

首先; 尽管障碍很小,但表格需要水平呈现。也就是说,标题在第 1 列中,每个附加列代表一个数据实体项。例如:

姓名 | 詹姆斯 | 理查德
姓氏 | 琼斯 | 梅菲尔

同样,这不是问题。当我来整齐地构建桌子时,问题就出现了。使用构建器模式,我有三个类:Table、Group 和 Row。它们可以这样使用:

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

此外,结果对象扩展了一个结果抽象类,其中包含原始数据的访问器、设置器和计算方法。这些“计算”方法中的每一个都返回可以分配给行对象的关联数据数组。结果对象和抽象类都很长,而且看起来很脱节。

总结一下……我最终得到了一个大型结果模型,它执行所有计算并返回所有行对象。虽然它确实有效,但我相信有更好的做事方式。我应该在控制器中构建行吗?我应该只从模型中调用计算吗?有没有人有任何抽象这样的东西的经验?

我很抱歉,这是一个糟糕的解释。如果有人有任何我可以提出的问题,请告诉我。

4

1 回答 1

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('Surname') 不够?为什么 Row 不能从标题和关联数据构建自己?

如果您想做同样的事情但具有不同的属性,请使用枚举或字符串。如果您有时需要能够插入一些东西,请使用工厂,它根据属性名称查找索引表,并回退到默认实现以防万一它不是异常。

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

像这样的代码重复是可以的,只要它有两个属性和简单的正交性——比如,getX,getY。但是对于无限数量的属性,我想这只是重复。

于 2012-07-23T22:15:33.873 回答