Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Алгоритм проверки наличия категории

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Описание: Категория магазина. Есть она или нет?
Wooorker
Отправлено: 10 Ноября, 2014 - 20:35:15
Post Id



Гость


Покинул форум
Сообщений всего: 99
Дата рег-ции: Нояб. 2011  


Помог: 0 раз(а)




В магазинах, как то VM, JShopping и других используется похожий способ хранения категорий

CREATE TABLE IF NOT EXISTS `categories` (
`category_id` int(11) NOT NULL AUTO_INCREMENT,
`category_parent_id` int(11) NOT NULL)

В файле загрузки имеем категорию "КАТЕГОРИЯ 1 УРОВНЯ\КАТЕГОРИЯ 2 УРОВНЯ\категория 3 уровня". В данном случае 3 уровня. А может быть 4, 5. Теоретически их может быть 10, 11 и т. д.
Нужно проверить наличие данных категорий в таблице `categories`. Ума не приложу как это можно сделать. Предполагаю что с помощью рекурсивной функции. Но как?

Скажем разбил я строку explode
PHP:
скопировать код в буфер обмена
  1.  
  2. $categories = explode("\\", $row['category']);
  3. $x = 0;
  4. foreach ($categories as $category) {
  5.  $x++;
  6. }
  7.  

ну и что это даёт?
Если перебирать с условиями, что это категория имеет paren_id =0, то переходим к следующей категории.
Если не имеет совпадений, то создаём новую с parent_id=0. В какой-то переменной запоминаем (хотя в данном случае можно и мудрить с двухмерным массивом) значение id категории первого уровня.
Далее смотрим номер цикла:
если это $x=1, то проверяем существование категории с таким уровнем; если она не существует, то создаём с parent_id =запомненному ранее значению; если она существует, то проверяем совпадает ли parent_id с запомненным ранее, если нет, то опять же создаём её, если да, то запоминаем и переходим к следующему циклу.
Т. е. это надо прописывать все if для каждого цикла. Условия умножаются в геометрической прогрессии. Очевидно это неправильный путь решения, т. к.
1) это некрасиво
2) количество категорий будет ограничено прописанными условиями и до десятого цикла код разрастётся так, что невозможно будет его переварить.

Как реализовать всё это какой нибудь красивой рекурсивной функцией (функцией класса, выделяю это потому, что классы только начал изучать и как в классе применить рекурсивную функцию - не представляю)?
 
 Top
Bio man
Отправлено: 10 Ноября, 2014 - 21:25:24
Post Id


Постоянный участник


Покинул форум
Сообщений всего: 2751
Дата рег-ции: Июль 2010  
Откуда: Даугавпилс, Латвия


Помог: 52 раз(а)




CODE (SQL):
скопировать код в буфер обмена
  1. CREATE TABLE IF NOT EXISTS `categories` (
  2. `category_id` int(11) NOT NULL AUTO_INCREMENT,
  3. `category_parent_id` int(11) NOT NULL,
  4. `category_name` varchar(255) NOT NULL
  5. )


PHP:
скопировать код в буфер обмена
  1. $categories = explode("\\", $row['category']);
  2.  
  3. if(!empty($categories)) {
  4.   // выбираем всё что есть по данным категориям
  5.   $condition = "'" . join("', '", $categories) . "'";
  6.   $sql = "SELECT * FROM `categories` WHERE `category_name` IN($condition)";
  7.  
  8.   $res = $mysqli->query($sql);
  9.  
  10.   $data = [];
  11.  
  12.   while($row = $res->fetch_assoc()) {
  13.     $data[$row['category_name']] = $row;
  14.   }
  15.  
  16.   foreach($categories as $cat) {
  17.     if(!isset($data[$cat])) {
  18.       // передвигаем итератор назад
  19.       $parent = prev($categories);
  20.  
  21.       $parentId = 0;      
  22.  
  23.       if(isset($data[$parent])) {
  24.         $parentId = $data[$parent]['category_id'];
  25.       }
  26.      
  27.  
  28.       // вставляем данные в БД и получаем ID
  29.       $sql = "INSERT INTO `categories`, SET `category_name` = '$cat', `category_parent_id` = $parentId";
  30.       $mysqli->query($sql);
  31.  
  32.       $categoryId = $mysqli->insert_id;
  33.  
  34.       // пишем новые данные в массив для следующей итерации
  35.       $data[$cat] = [
  36.         'category_id' = $categoryId,
  37.         'category_name' = $cat,
  38.         'category_parent_id' = $parent_id
  39.       ];
  40.  
  41.       // возвращаем итератор на прежнюю позицию
  42.       next($categories);
  43.     }
  44.   }
  45. }
  46.  


набросал на коленке. не уверен в работоспособности, не проверял.
и ещё не уверен насчёт next и prev в цикле, я не знаю как себя ведут эти функции внутри цикла, но по логике должны работать корректно.
в любом случае будет пища для размышлений
 
 Top
Wooorker
Отправлено: 12 Ноября, 2014 - 12:37:51
Post Id



Гость


Покинул форум
Сообщений всего: 99
Дата рег-ции: Нояб. 2011  


Помог: 0 раз(а)




Bio man пишет:
набросал на коленке. не уверен в работоспособности, не проверял.
и ещё не уверен насчёт next и prev в цикле, я не знаю как себя ведут эти функции внутри цикла, но по логике должны работать корректно.
в любом случае будет пища для размышлений


Вопрос я писал на ночь глядя. Утром после прочтения вашего ответа никак не мог сообразить как же ваш пример должен работать.

Вы итоге по поводу "пищи для размышлений" вы оказались правы. И только в этом.

Сам пример абсолютно не рабочий. Проблем в том, что разбор категорий не с конца надо вести, а именно с начала.
А вообще всё просто оказалось:
PHP:
скопировать код в буфер обмена
  1.                
  2. $sql="SELECT `category_id` FROM $cat_tables WHERE `category_name` = :category AND `category_parent_id` = :parentId LIMIT 1";
  3. $stmt_r = $this->db->prepare($sql);
  4. $sql="INSERT INTO $cat_tables (`category_parent_id`, `category_name`)
  5. VALUES (:parentId, :category_name)";
  6. $stm_i = $this->db->prepare($sql);
  7.  
  8. $categories = explode('\\', $row['category_name']);
  9. $parentId = 0;
  10. foreach ($categories as $category) {
  11. $stmt_r->bindParam(":category", $category, PDO::PARAM_STR);
  12. $stmt_r->bindParam(":parentId", $parentId, PDO::PARAM_INT);
  13. $stmt_r->execute();
  14. if ($cat_res = $stmt_r->fetchColumn()){
  15. //if exist category
  16. $stmt_r->closeCursor();
  17. $parentId = $cat_res[0];
  18. }else{
  19. //if not exist category
  20. $stm_i->bindParam(":category_name", $category, PDO::PARAM_STR);
  21. $stm_i->bindParam(":parentId", $parentId, PDO::PARAM_INT);
  22. $stm_i->execute();
  23. $parentId = $this->db->lastInsertId();
  24. $stm_i->closeCursor();
  25. }
  26. }
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Вопросы новичков »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB