2016-11-17 5 views
1

В этом DataObject есть поле, предоставленное пользователем Заголовок, который должен быть преобразован в уникальный URL-адрес.Уникальный URL-адрес SilverStripe (debug)

Желаемый результат: Дублирующийся URL должен получить суффикс к его значению. Таким образом, сохранение 2 записей с заголовком Foo должно привести к одной записи с foo в качестве ее значения для столбца URL, а вторая запись должна иметь значение foo-2 для того же столбца.

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 в два раза приведет к foo и foo-2.

При сохранении двух записей с тем же названием Foo результатов в двух полях URL с foo

+0

В чем ваш вопрос, нужен ли первый случай «foo» и «foo-2» и второй случай? или 'foo-1' и' foo-2' в обоих случаях? – Timmetje

+0

'foo' для первого и' foo-2' для второго – Faloude

ответ

2

Почему у вас есть два foo URLs?

Если вы проверили свою БД перед вставкой всех записей, это означает, что проверка не будет работать в вашей партии записей.

Не использовать цикл для подсчета уникальных URL

Вам не нужно в цикле и проверять каждый раз, и увеличивать количество ($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 

Solutions

Чтобы сделать это onBeforeWrite() единственная возможность состоит в том, чтобы опрашивать данные и проверить свои записи, прежде чем они будут сохранены.

Или простое решение с теми же результатами, что вы можете изменить URL-адрес в 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 
} 
+0

Работает как шарм. Оператор 'else' необходим, иначе' $ this-> URL' будет NULL, когда он будет уникальным. – Faloude

+0

Ах, я пропустил, что ты абсолютно прав, я изменил ответ на правильность. И теперь это выглядит лучше;) – Timmetje