2012-07-23 43 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']); 

代碼重複的罰款。但有了無限的屬性,我想這只是重複。