Symfony模型回调等价

时间:2010-01-12 16:04:36

标签: php symfony1

我正在开发一个Symfony项目(我的第一个),我必须从我的Widget类中检索一组属于Page的小部件。但是,在返回结果之前,我需要验证 - 对于外部服务 - 用户有权查看每个小部件。如果没有,当然,我需要从结果集中删除小部件。

使用CakePHP或Rails,我会使用回调,但我没有找到类似Symfony的东西。我看到事件,但如果我正确地阅读事物(这总是需要讨论),那些似乎与控制器/操作更相关。我的后备解决方案是覆盖WidgetPeer类中的各种检索方法,转移它们通过执行授权的自定义方法并适当地修改结果集。但是,这感觉就像是大规模的过度杀伤,因为我必须覆盖每个选择方法,以确保授权完成,而未来的开发人员不必考虑它。

看起来行为对此有用(特别是因为它可能是可想象的,我将来可能需要授权其他类实例),但我找不到任何关于它们的正确文档做出合格的评估。

我错过了什么吗?似乎必须有更好的方法,但我还没有找到它。

3 个答案:

答案 0 :(得分: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;
      }
    }
  }
}

希望你有个主意。

答案 1 :(得分:0)

以下是有关Symfony 1.2 Propel行为的一些文档:http://www.symfony-project.org/cookbook/1_2/en/behaviors

为什么不在您的Page对象上设置'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;
}

但是,如果始终希望在选择Page的Widgets时执行此检查,那么Propel的行为是您最好的选择。

答案 2 :(得分: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,但看起来这样就足够了。