Silverstripe 如何使用ORM而不是原始SQL查询更新值?

Silverstripe 如何使用ORM而不是原始SQL查询更新值?,silverstripe,Silverstripe,当用户想要将图像设置为特色时,我们希望将所有其他图像重置为非特色图像。我使用以下原始SQLquery实现了这一点 使用ORM有没有更干净的方法来实现这一点,或者对于这种类型的东西,保持原样是否更干净 <?php class Banner extends DataObject { private static $db = array( 'FeaturedImage' => 'Boolean' ); private static $has_on

当用户想要将图像设置为特色时,我们希望将所有其他图像重置为非特色图像。我使用以下原始
SQL
query实现了这一点

使用
ORM
有没有更干净的方法来实现这一点,或者对于这种类型的东西,保持原样是否更干净

<?php

class Banner extends DataObject {
    private static $db = array(
        'FeaturedImage' => 'Boolean'
    );

    private static $has_one = array(
        'Image' => 'Image'
    );

    private static $summary_fields = array(
        'Image.CMSThumbnail' => 'Image',
        'FeaturedImage.Nice' => 'Featured?'
    );

    public function onBeforeWrite()
    {
        parent::onBeforeWrite();

        // When user sets an image to be featured, reset all other images not to be featured
        if ($this->FeaturedImage) {
            $query = 'UPDATE Banner SET FeaturedImage = 0 WHERE Banner.ID !=' . $this->ID;
            DB::query($query);
        }
    }
}
类似这样的东西:

$banners = Banner::get()->exclude('ID', $this->ID);
foreach($banners as $banner) {
   $banner->FeaturedImage = 0;
   $banner->write();
}
您是否已尝试此操作(抱歉,无法将其添加为注释)


该条件应防止递归调用write。

否,获取错误:
致命错误:已达到最大函数嵌套级别“256”,正在中止!在第0行的Unknown中
是否在onAfterWrite()中尝试过?onBeforeWrite和onAfterWrite在这里不起作用,因为它们在每次处理图像对象时都会运行。所以当你有
$banner->FeaturedImage=0$banner->write()
这将在
$banner
的写前和写后重新运行。它陷入了一个无休止的循环。好的,唯一的方法是使用原始查询,这是您当前正在执行的操作。您刚刚尝试在
onAfterWrite()
中使用此代码。我有3个横幅,它只适用于最后一个,如果我试图使第一个或第二个横幅的特色之一,它不会改变它。。看起来原始SQL可能是最终的最佳方式..正如greg所说,最好是在onAfterWrite中。。。不过,还是最好对此进行某种更改,而不是将其“破解”到保存中。@ifusion cleaner,嗯。。。但有一个选项是从同一个对象(每个下拉列表或ListBoxField将横幅保存到其中一个横幅对象)中选择一个。
public function onAfterWrite()
{
    parent::onAfterWrite();

    if ($this->FeaturedImage) {
        $banners = Banner::get()->exclude('ID', $this->ID);
        foreach($banners as $banner) {
           $banner->FeaturedImage = false;
           $banner->write();
        }
    }
}