Моделювання N-вимірного каталогу

15.04.2011

N-мірний каталог продукції, то між каталог з підкатегоріями необмеженої вкладеності, задум така, що у товару може бути мінім одна, а максиум N (Ну, для початку, N не менше 5-ти, але задум зробити НЕ обмеженим) і якщо в чистої категорії (pid=0) можна створити товар або підкатегорію. Якщо створюємо підкатегорію, то цієї новоствореної підкатегорії в полі pid записується id батьківської категорії (рід, кат,), і в рід, кат, відтепер можна створювати тільки підкатегорії (товари вже НЕЛЬЗЯ), доки з неї не будуть видалені всі підкатегорії. А якщо ми в рід, кат, створюємо товар, то в таблиці товарів полю link_id створеного товару присвоюється id рід, кат, і в ній ми тепер можемо створювати тільки товари, поки не будуть з таблиці видалені всі товари.

Поки що стандартна схема 3-х рівневого каталогу, але фішка в тому, що поле pid таблиці категорій не INT, а VARCHAR, і коли ми в категорії 2-го рівня (К2) створюємо К3, то в pid записуються через кому id рід, кат , Починаючи з самої верхньої, Томеж якщо в К1 з id=1 pid=0, створили К2 у якої id=2 і pid=1, і в ній створили К3 у якої id=3, то pid у неї буде дорівнює pid=' 1,2' і т.д,

Ось спрощена структура таблиці із тестовим дампом:


  1. CREATE TABLE `test`
  2. (
  3. `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  4. `pid` VARCHAR(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
  5. `title` VARCHAR(128) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT ''
  6. )
  7. ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_general_ci;


  1. INSERT INTO `test`
  2. (`id`, `pid`, `title`)
  3. VALUES
  4. (1, '0', 'Кат 1'),
  5. (2, '0', 'Кат 2'),
  6. (3, '0', 'Кат 3'),
  7. (4, '1', 'Кат 1.1'),
  8. (5, '1', 'Кат 1.2'),
  9. (6, '1', 'Кат 1.3'),
  10. (7,'1,4','Кат 1.1.1'),
  11. (8, '1,4', 'Кат 1.1.2'),
  12. (9, '1,4', 'Кат 1.1.3'),
  13. (10,'1,5','Кат 1.2.1'),
  14. (11, '1,5', 'Кат 1.2.2'),
  15. (12, '1,5', 'Кат 1.2.3'),
  16. (13, '1,6', 'Кат 1.3.1'),
  17. (14, '1,6', 'Кат 1.3.2'),
  18. (15, '1,6', 'Кат 1.3.3'),
  19. (16, '2', 'Кат 2.1'),
  20. (17, '2', 'Кат 2.2'),
  21. (18, '2', 'Кат 2.3'),
  22. (19, '0', 'Кат 4');

Для того, щоб дізнатися яка категорія остання (що не має дітей, отже чи має товари чи порожня), а яка батьківська (яка має дітей, отже має підкатегорії) Нам потрібно відокремити групу "Останніх id" (3,7,8,9, 10,11,12,13,14,15,16,17,18,19) які або порожні або містять товари, та групу "Проміжних id" (1,2,4,5,6)

Для цього створюємо запит, який підраховував би кількість дочірніх категорій, і таким чином можна легко відокремити Проміжні підкатегорії від кінцевих.

Для адмінської частини:


  1. function list_cat($pid)
  2. {
  3. if ((int)$pid <= 0) $pid = 0;
  4. $query = 'SELECT t1.*,COUNT(t2.pid)col FROM '.$this->table.'_cat t1 LEFT JOIN '.$this->table.'_cat t2 ON FIND_IN_SET(t1.id,t2. pid) WHERE t1.pid=\''.addslashes($pid).'\' GROUP BY t1.id ORDER BY t1.order';
  5. $res = $this->db->assoc($query);
  6. return (is_array($res) && count($res) > 0) ?$res :false;
  7. }

Де розділення на "Кінцеві" та "Проміжні" категорії відбувається шляхом підрахунку дочірніх підкатегорій.

Для кат 1 pid='0' (саме '0', а чи не NULL) А всім дочірніх наступних відповідному pid-у

І клієнтської частини:


  1. function list_cat($id)
  2. {
  3. $query = 'SELECT t1.*,COUNT(t2.pid)col FROM '.$this->table.'_cat t1 LEFT JOIN '.$this->table.'_cat t2 ON FIND_IN_SET(t1.id,t2. pid) WHERE (t1.pid=\''.(int)$id.'\' OR t1.pid LIKE \'%,'.(int)$id.'\') AND t1.status>0 GROUP BY t1.id ORDER BY t1.order';
  4. $res = $this->db->assoc($query);
  5. return (is_array($res) && count($res) > 0) ?$res :false;
  6. }

Де, на відміну від адмінської частини, виконується тільки перегляд, а отже нам не потрібно знати повністю pid батька і можна схитрувати з оператором LIKE, щоб робити вибірку не по всьому pid, а тільки по його числовому кінцівці, що дає можливість застосувати ЧПК до посиланням (коли ми робимо вибірку не по 1-му id а по зв'язці id через кому, нам неможливо замінити його через .htaccess)

Останнє в нашому блозі

Інтернет маркетинг
04.11.2019