2010-01-12 58 views
0

我正在開發一個Symfony項目(我的第一個),我必須從我的Widget類中檢索一組屬於Page的小部件。但是,在返回結果之前,我需要驗證 - 對於外部服務 - 用戶有權查看每個小部件。如果沒有,當然,我需要從結果集中刪除小部件。Symfony模型回調等效

使用CakePHP或Rails,我會使用回調,但我沒有發現任何類似的Symfony。我看到事件,但如果我正確地閱讀東西(這總是需要討論),那些與控制器/動作看起來更相關。我的回退解決方案是覆蓋WidgetPeer類中的各種檢索方法,並通過自定義方法轉移它們,該方法執行授權並適當修改結果集。不過,這感覺像是大規模的矯枉過正,因爲我必須每選擇方法覆蓋以確保授權在未來的開發人員不必考慮的情況下完成。

看起來行爲可能對此很有用(尤其是因爲它可能是,我可能需要在未來授權其他類實例),但我找不到任何體面的文檔來進行合格評估。

我錯過了什麼嗎?似乎必須有更好的方式,但我還沒有找到。

回答

0

雖然至少在理論上,我仍然認爲一種行爲是正確的方法,但我無法在Symfony 1.4.x中找到足夠的關於它們的實現的文檔來給我一個溫暖和模糊的文檔,如果有的話,沒有很多的胃灼熱。即使在Propel自己的行爲文檔中,我也沒有看到任何觸發我需要採取的行動的檢索前或檢索後鉤子。

因此,我採取了我的備用路徑。但是經過一些源代碼篩選之後,我意識到這並不像我第一次想到的那樣辛苦。每一個檢索方法穿過BasePeer模型doSelect()方法,所以我只是推翻了一個在定製Peer型號:

static public function doSelect(Criteria $criteria, PropelPDO $con = null) { 
    $all_widgets = parent::doSelect($criteria, $con); 
    $widgets  = array(); 

    foreach ($widgets as $i => $widget) { 
    #if(authorized) { 
    # array_push($widgets, $widget); 
    #} 
    } 

    return $widgets; 
} 

我沒有連接好服務調用的授權呢,但是這似乎按預期方式工作用於修改結果集。何時以及如果我必須爲其他模型實例提供授權,我將不得不重新訪問行爲以保持DRY,但在此之前,它看起來會很好。

0

以下是關於Symfony 1.2 Propel行爲的一些文檔:http://www.symfony-project.org/cookbook/1_2/en/behaviors

爲什麼不在你的頁面對象上有一個'getAllowedWidgets'方法來執行你正在查找的檢查?喜歡的東西:

public function getAllowedWidgets($criteria = null, PropelPDO $con = null) { 
    $widgets = $this->getWidgets($criteria, $con); 
    $allowed = array(); 

    // get access rights from remote service 

    foreach($widgets as $widget) { 
    // widget allowed? 
    $allowed[] = $widget; 
    } 

    return $allowed; 
} 

不過,如果你總是選擇頁面的窗口小部件,然後當要進行這種檢查行走的行爲是你最好的選擇。

+0

這是_always_部分,它比單個高級方法中的操作更尖叫。我在Symfony行爲中看到了令人沮喪的少量文檔,並且它似乎都是以1.2爲中心的。我正在使用1.4.1。行爲機制自1.2以來發生了變化嗎?謝謝你的幫助。 – 2010-01-12 20:19:59

+0

行爲實際上可能不是您的解決方案,您是否想要對更多對象執行此「可查看」檢查而不僅僅是您的Page Widgets?如果沒有,那麼在你的模型中的直接覆蓋將會很好,不用擔心創建整個行爲。 Rails/Cake鉤子的工作方式與行爲和方法覆蓋的方式完全相同,唯一真正的區別是您使用pre *和post *方法構建的乾淨的代碼分離。然而,Symfony確實可以讓你完全覆蓋所有的東西。 希望有所幫助。 – nortron 2010-01-12 21:58:54

+0

這確實有幫助。我喜歡回調的封裝,但嘗試過和真正的面向對象覆蓋可以完成這項工作。正如我在上面的回答中所提到的那樣,當我想要/需要授權更多隻是'Widget'模型時,我會擔心創建行爲。再次感謝。 – 2010-01-13 12:10:01

1

首先,我認爲基於行爲的方法是錯誤的,因爲它會增加模型層耦合程度。

sfEventDispatcher::filter()方法,它允許您分別過濾傳遞給它的參數。

因此,守則草案將看起來像:

<somewhere>/actions.class.php

public function executeBlabla(sfWebRequest $request) 
{ 
    //...skip... 
    $widgets = WidgetPeer::getWidgetsYouNeedTo(); 
    $widgets = $this->getEventDispatcher()->filter(new sfEvent($this, 'widgets.filter'), $widgets)); 
    //...skip... 
} 

apps/<appname>/config/<appname>Configuration.class.php

//...skip... 
    public function configure() 
    { 
    $this->registerHandlers(); 
    } 
    public function registerHandlers() 
    { 
    $this->getEventDispatcher()->connect('widgets.filter', array('WidgetFilter', 'filter')); 
    } 
//...skip 

lib/utility/WidgetFilter.class.php

class WidgetFilter 
{ 
    public static function filter(sfEvent $evt, $value) 
    { 
    $result = array(); 
    foreach ($value as $v) 
    { 
     if (!Something::isWrong($v)) 
     { 
     $result[] = $v; 
     } 
    } 
    } 
} 

希望你有一個主意。

+0

我想我明白了,但我認爲模型是我想要的,而不是控制器。不管爲什麼要求一個小部件,我需要確保當前用戶有權查看該小部件。目前,只有頁面纔有理由請求小部件,但這可能會發生變化。如果授權數據保存在數據庫中,我會在'WHERE'子句中進行篩選。 – 2010-01-13 17:43:32

+0

好吧,從模型或你想要的任何地方調用'sfContext :: getInstance() - > getEventDispatcher() - > filter()'。 – develop7 2010-01-13 21:43:49