SilverStripe唯一网址(调试)

时间:2016-11-17 17:36:38

标签: php silverstripe

在此 DataObject 中,有一个用户提供的字段标题,必须将其转换为唯一的网址标记。

所需结果:重复的网址应获得其值的后缀。因此,使用标题Foo保存2条记录应该会产生一条记录foo作为列URL的值,第二条记录的值应为foo-2。< / p>

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

    // Sanitize Title field to use for URL
    $filter = URLSegmentFilter::create();
    $this->URL = $filter->filter($this->Title);

    // If URL is not unique, add suffix
    $i = 1;
    while($this->uniqueURL($this->URL)) {
        $i++;
        $this->URL = $this->URL . "-" . $i;
    }   
}

方法:uniqueURL (在同一个班级内)

public function uniqueURL($URL) {

    // Check if there is a record with the same URL
    $existingURL = DataObject::get('NewsArticle', "URL = '$URL'");
    if ($existingURL) {
        // this is a duplicate URL
        return false;
    } else {
        // this is a unique url
        return true;
    }
}

两次保存Foo会产生foofoo-2

保存具有相同标题Foo的两个记录时会产生两个带有foo

的网址字段

1 个答案:

答案 0 :(得分:3)

为什么你有两个foo网址?

如果在插入所有记录之前检查数据库,则表示该检查对您的记录批次不起作用。

请勿使用循环来计算唯一网址

您不需要每次循环检查并增加计数($i)。性能方面,您最好在查询中执行COUNT(),并将该值用于下一次插入。

// The following does exactly the same with just 1 query. No loop needed.
$count = DB::query("SELECT COUNT(*) FROM Table WHERE Title LIKE '{$filteredTitle}'")->value();
if ($count > 1) {
    $filteredTitle .= "-" .  $count;
}
$this->URL = $filteredTitle

<强>解决方案

要做到onBeforeWrite(),唯一的可能是查询您的数据并在保存之前检查您的记录。

或者一个结果相同的简单解决方案是您可以更改onAfterWrite()中的网址,并检查使用相同标题的数量作为数字。

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

    // Sanitize Title field to use for URL
    $filter = URLSegmentFilter::create();
    $filteredTitle= $filter->filter($this->Title);

    $count = DB::query("SELECT COUNT(*) FROM Table WHERE Title LIKE '{$filteredTitle}'")->value();
    if ($count > 1) {
        $filteredTitle .= "-" .  $count;
    }
    $this->URL = $filteredTitle
}