Intereting Posts
Использование pdo в php с хранимой процедурой Использование функции заголовка в PHP Получение того, что кажется ошибкой PHP4 на моем сервере PHP5 Как прочитать второй лист файла xlsx с PHPExcel? Получить скрытое входное значение из базы данных после выбора формы Создание динамического выпадающего меню при возврате набора результатов mySQL XAMPP / MySQL: не удалось открыть файл таблицы таблиц с одной таблицей. \ Mysql \ innodb_index_stats.ibd после перезагрузки MySQL CodeIgniter: Страница не найдена при передаче параметров контроллеру? Сценарий вычисления Javascript для вычисления входного значения формы затем сохраните как скрытый ввод для page2.php Как я могу увидеть фактический XML, созданный PHP SOAP Client Class? Свойства PHP Readonly? Как шифровать / расшифровывать данные в php? невозможно сравнивать данные из базы данных с массивом строк Поиск подстроки при игнорировании тегов HTML PHP – SQLite vs SQLite3

создание уникальных slug-заголовков страниц php

У меня есть функция для создания уникального слитка для названия страницы. Он проверяет, доступен ли slug в таблице страниц, а затем создает уникальный слизню, добавив соответственно «-int». Функция работает отлично для первых трех записей, например, для «тестовой пули», введенной три раза, создаст «test-slug-1», «test-slug-2» и «test-slug-3». Затем после этого я получаю сообщение об ошибке «Неустранимая ошибка: максимальное время выполнения 30 секунд превышено» для четвертой записи. Должна быть какая-то проблема с логикой, может ли кто-нибудь помочь мне найти ее, пожалуйста. Ниже приведен код:

function createSlug($title, $table_name, $field_name) { global $db_connect; $slug = preg_replace("/-$/","",preg_replace('/[^a-z0-9]+/i', "-", strtolower($title))); $counter = 1; do{ $query = "SELECT * FROM $table_name WHERE $field_name = '".$slug."'"; $result = mysqli_query($db_connect, $query) or die(mysqli_error($db_connect)); if(mysqli_num_rows($result) > 0){ $count = strrchr($slug , "-"); $count = str_replace("-", "", $count); if($count > 0){ $length = count($count) + 1; $newSlug = str_replace(strrchr($slug , "-"), '',$slug); $slug = $newSlug.'-'.$length; $count++; }else{ $slug = $slug.'-'.$counter; } } $counter++; $row = mysqli_fetch_assoc($result); }while(mysqli_num_rows($result) > 0); return $slug; 

}

Solutions Collecting From Web of "создание уникальных slug-заголовков страниц php"

Просто используйте один запрос, чтобы сделать весь тяжелый подъем для вас …

 $slug = preg_replace("/-$/","",preg_replace('/[^a-z0-9]+/i', "-", strtolower($title))); $query = "SELECT COUNT(*) AS NumHits FROM $table_name WHERE $field_name LIKE '$slug%'"; $result = mysqli_query($db_connect, $query) or die(mysqli_error($db_connect)); $row = $result->fetch_assoc(); $numHits = $row['NumHits']; return ($numHits > 0) ? ($slug . '-' . $numHits) : $slug; 

Просто нажмите базу данных один раз, захватите все сразу, скорее всего, это самое узкое место.

 $query = "SELECT * FROM $table_name WHERE $field_name LIKE '".$slug."%'"; 

Затем поместите свои результаты в массив (допустим, $slugs )

 //we only bother doing this if there is a conflicting slug already if(mysqli_num_rows($result) !== 0 && in_array($slug, $slugs)){ $max = 0; //keep incrementing $max until a space is found while(in_array( ($slug . '-' . ++$max ), $slugs) ); //update $slug with the appendage $slug .= '-' . $max; } 

Мы используем проверки in_array() как если бы slug был my-slug LIKE также возвращал строки, такие как

 my-slug-is-awesome my-slug-is-awesome-1 my-slug-rules 

и т. д., что вызовет проблемы, проверки in_array() гарантируют, что мы проверяем только точный введённый пул.

Почему бы нам просто не подсчитать результаты и +1?

Это связано с тем, что если вы получили несколько результатов и удалили несколько, ваш следующий слизень вполне может конфликтовать.

Например

 my-slug my-slug-2 my-slug-3 my-slug-4 my-slug-5 

Удалить -3 и -5 оставляет нас

 my-slug my-slug-2 my-slug-4 

Итак, это дает нам 3 результата, следующая вставка будет my-slug-4 которая уже существует.

Почему бы нам просто не использовать ORDER BY и LIMIT 1 ?

Мы не можем просто выполнить order by в запросе, потому что отсутствие естественной сортировки сделает my-slug-10 ранг ниже, чем my-slug-4 поскольку он сравнивает символ по символу, а 4 – выше 1

Например

 m = m y = y - = - s = s l = l u = u g = g - = - 4 > 1 !!! < 0 (But the previous number was higher, so from here onwards is not compared) 

Вы можете просто выбрать slug с наибольшим числом и увеличить его с помощью 1:

 $query = "SELECT $field_name FROM $table_name WHERE $field_name LIKE '".$slug."-[0-9]*' ORDER BY $field_name DESC LIMIT 1"; 

[0-9]* в запросе означает любое количество чисел.

Этот запрос будет выбирать строку с $slug при запуске и наибольшее число.

После этого вы можете проанализировать результат, получить номер и увеличить его.

В этом случае у вас будет только один запрос и много неиспользуемой производительности.

ОБНОВИТЬ

Это не сработает, потому что slug-8 будет «больше», чем slug-11 . Но не знаю, как это исправить. возможно ORDER BY id DESC ?

ОБНОВЛЕНИЕ 2

Запрос можно заказать по длине, и он будет работать правильно. Благодаря Джеку:

 $query = "SELECT $field_name FROM $table_name WHERE $field_name LIKE '".$slug."-[0-9]*' ORDER BY LENGTH($field_name), $field_name DESC LIMIT 1"; 

ОБНОВЛЕНИЕ 3

Также добавлена ​​проверка оригинального слизняка. Благодаря Хейлвуду.

 $query = "SELECT $field_name FROM $table_name WHERE $field_name = '".$slug."' OR $field_name LIKE '".$slug."-[0-9]*' ORDER BY LENGTH($field_name), $field_name DESC LIMIT 1"; 

Для одной части я создал бы объект, который имеет дело с частью, создающей slug и обрабатывающей число:

 // generate new slug: $slug = new NumberedSlug('Creating Unique Page Title Slugs in PHP'); echo $slug, "\n", $slug->increase(), "\n"; // read existing slug: $slug = new NumberedSlug('creating-unique-page-title-slugs-in-php-44'); echo $slug->getNumber(), "\n"; 

Вывод:

 creating-unique-page-title-slugs-in-php creating-unique-page-title-slugs-in-php-1 44 

Для другой части базы данных это уже значительно упрощает ваш код (пожалуйста, дважды проверьте, я сделал это быстро). Также посмотрите, как вы можете воспользоваться объектом Mysqli, который у вас есть (но не использовать как есть):

 function createSlug($title, $table_name, $field_name, Mysqli $mysqli = NULL) { $mysqli || $mysqli = $GLOBALS['db_connect']; $slug = new NumberedSlug($title); do { $query = "SELECT 1 FROM $table_name WHERE $field_name = '" . $slug . "'"; if (!$result = $mysqli->query($query)) { throw new RuntimeException(var_export($mysqli->error_list, true)); } if ($result->num_rows) { $slug->increase(); } } while ($result->num_rows); return $slug; } 

Но, как уже писали другие, вы должны сначала получить все слитки, которые нумеруются сразу из базы данных, а затем при необходимости выбрать уникальный. Это уменьшит количество вызовов базы данных. Также код намного компактнее:

 function createSlug2($title, $table_name, $field_name, Mysqli $mysqli = NULL) { $mysqli || $mysqli = $GLOBALS['db_connect']; $slug = new NumberedSlug($title); $query = "SELECT $field_name FROM $table_name WHERE $field_name LIKE '$slug-_%'"; if (!$result = $mysqli->query($query)) { throw new RuntimeException(var_export($mysqli->error_list, true)); } $existing = array_flip(call_user_func_array('array_merge', $result->fetch_all())); $slug->increase(); while (isset($existing[$slug])) { $slug->increase(); } return $slug; } 

Смотрите в действии.

 $query = "SELECT * FROM $table_name WHERE $field_name LIKE '".$slug."%'"; $result = mysqli_query($db_connect, $query) or die(mysqli_error($db_connect)); //EDITED BASED ON COMMENT SUGGESTIONS //create array of all matching slug names currently in database $slugs = array(); while($row = $result->fetch_row()) { $slugs[] = $row['field_name']; } //test if slug is in database, append - '1,2,..n' until available slug is found if(in_array($slug, $slugs)){ $count = 1; do{ $testSlug = $slug . '-' . $count; $count++; } while(in_array($testSlug, $slugs)); $slug = $testSlug; } //insert slug 

Вы должны иметь возможность сделать это в одном вызове базы данных с ключевым словом LIKE, что сократит время выполнения.

Почему бы вам просто не создать пул и оставить остальную часть задания, которая включает индексирование в MySQL. Вот функция slugify (это слегка модифицированная версия, используемая в рамках платформы Symfony).

 function slugify( $text ) { $text = preg_replace('~[^\\pL\d]+~u', '-', $text); $text = trim($text, '-'); $text = iconv('utf-8', 'ASCII//IGNORE//TRANSLIT', $text); $text = strtolower(trim($text)); $text = preg_replace('~[^-\w]+~', '', $text); return empty($text) ? substr( md5( time() ), 0, 8 ) : $text; } 

А часть MySQL может быть решена с помощью триггера (изменить имена таблиц и столбцов).

 BEGIN declare original_slug varchar(255); declare slug_counter int; set original_slug = new.slug; set slug_counter = 1; while exists (select true from post where slug = new.slug) do set new.slug = concat(original_slug, '-', slug_counter); set slug_counter = slug_counter + 1; end while; END 

MySQL Вставить строку, дублировать: добавить суффикс и повторно вставить

Вы можете использовать Fbeen / UniqueSlugBundle . Этот комплект легкий и делает то, что ему нужно.