Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Bagaimana cara memilih subkategori dari kategori yang dipilih menggunakan fungsi bersarang di PHP?

Ada beberapa solusi. Pertama-tama, saya akan menggunakan data berikut (categories tabel) sebagai contoh.

+----+--------------------------+-----------+
| id | name                     | parent_id |
+----+--------------------------+-----------+
|  1 | Electronics              |      NULL |
|  2 | Apparel & Clothing       |      NULL |
|  3 | Phones & Accessories     |         1 |
|  4 | Computer & Office        |         1 |
|  5 | Men's Clothing           |         2 |
|  6 | Women's Clothing         |         2 |
|  7 | Cell Phones              |         3 |
|  8 | Cell Phone Accessories   |         3 |
|  9 | Phone Parts              |         3 |
| 10 | Computers & Accessories  |         4 |
| 11 | Tablets & Accessories    |         4 |
| 12 | Computer Peripherals     |         4 |
| 13 | Computer Components      |         4 |
| 14 | Office Electronics       |         4 |
+----+--------------------------+-----------+

Solusi 1 (Daftar Ketetanggaan ):

Anda dapat dengan mudah mengambil semua kategori atau subkategori dari suatu kategori dalam satu kueri menggunakan DENGAN (Ekspresi Tabel Umum) klausa (memerlukan MySQL 8.0):

// Database connection

$options = [
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES => false,
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
];

$pdo = new PDO('mysql:host=localhost;dbname=<DATABASE_NAME>', '<USERNAME>', '<PASSWORD>', $options);
function getCategories(PDO $db, $parentId = null)
{
    $sql = $parentId ? 'WITH RECURSIVE cte (id, name, parent_id) AS (SELECT id, name, parent_id FROM categories WHERE parent_id = ? UNION ALL SELECT c.id, c.name, c.parent_id FROM categories c INNER JOIN cte ON c.parent_id = cte.id) SELECT * FROM cte' : 'SELECT * FROM categories';
    $stmt = $db->prepare($sql);
    $stmt->execute($parentId ? [$parentId] : null);
    return $stmt->fetchAll();
}

Jika Anda menggunakan MySQL 5.7, ubah fungsinya seperti ini:

function getCategories(PDO $db, $parentId = null)
{
    $sql = $parentId ? 'SELECT id, name, parent_id FROM (SELECT * FROM categories ORDER BY parent_id, id) c, (select @pv := ?) initialisation WHERE find_in_set(parent_id, @pv) AND LENGTH(@pv := concat(@pv, ",", id))' : 'SELECT * FROM categories';
    $stmt = $db->prepare($sql);
    $stmt->execute($parentId ? [$parentId] : null);
    return $stmt->fetchAll();
}

Untuk mendapatkan semua kategori di database Anda:

$allCategories = getCategories($pdo);

Keluaran:

+----+--------------------------+-----------+
| id | name                     | parent_id |
+----+--------------------------+-----------+
|  1 | Electronics              |      NULL |
|  2 | Apparel & Clothing       |      NULL |
|  3 | Phones & Accessories     |         1 |
|  4 | Computer & Office        |         1 |
|  5 | Men's Clothing           |         2 |
|  6 | Women's Clothing         |         2 |
|  7 | Cell Phones              |         3 |
|  8 | Cell Phone Accessories   |         3 |
|  9 | Phone Parts              |         3 |
| 10 | Computers & Accessories  |         4 |
| 11 | Tablets & Accessories    |         4 |
| 12 | Computer Peripherals     |         4 |
| 13 | Computer Components      |         4 |
| 14 | Office Electronics       |         4 |
+----+--------------------------+-----------+

Untuk mendapatkan subkategori dari suatu kategori:

$subCategories = getCategories($pdo, 1); // 1 is parent_id

Keluaran:

+----+--------------------------+-----------+
| id | name                     | parent_id |
+----+--------------------------+-----------+
|  3 | Phones & Accessories     |         1 |
|  4 | Computer & Office        |         1 |
|  7 | Cell Phones              |         3 |
|  8 | Cell Phone Accessories   |         3 |
|  9 | Phone Parts              |         3 |
| 10 | Computers & Accessories  |         4 |
| 11 | Tablets & Accessories    |         4 |
| 12 | Computer Peripherals     |         4 |
| 13 | Computer Components      |         4 |
| 14 | Office Electronics       |         4 |
+----+--------------------------+-----------+

Jika Anda menginginkan keluaran HTML, Anda dapat mengulang $allCategories / $subCategories (berdasarkan contoh Anda):

function prepareCategories(array $categories)
{
    $result = [
        'all_categories' => [],
        'parent_categories' => []
    ];
    foreach ($categories as $category) {
        $result['all_categories'][$category['id']] = $category;
        $result['parent_categories'][$category['parent_id']][] = $category['id'];
    }
    return $result;
}

function buildCategories($categories, $parentId = null)
{
    if (!isset($categories['parent_categories'][$parentId])) {
        return '';
    }

    $html = '<ul>';
    foreach ($categories['parent_categories'][$parentId] as $cat_id) {
        if (isset($categories['parent_categories'][$cat_id])) {
            $html .= "<li><a href='#'>{$categories['all_categories'][$cat_id]['name']}</a>";
            $html .= buildCategories($categories, $cat_id);
            $html .= '</li>';
        } else {
            $html .= "<li><a href='#'>{$categories['all_categories'][$cat_id]['name']}</a></li>";
        }
    }
    $html .= '</ul>';

    return $html;
}
echo buildCategories(prepareCategories($allCategories));

Keluaran:

echo buildCategories(prepareCategories($subCategories), 1);

Keluaran:

Solusi 2 (Set Bertingkat ):

Kami akan menambahkan kolom tambahan left dan right ke meja kami dan masukkan nomor di dalamnya yang akan mengidentifikasi kelompok milik orang tua. (Perhatikan bahwa kami tidak akan menggunakan parent_id kolom.)

+----+--------------------------+--------------------------+
| id | name                     | parent_id | left | right |
+----+--------------------------+--------------------------+
|  1 | Electronics              |      NULL |    1 |    22 |
|  2 | Apparel & Clothing       |      NULL |   23 |    28 |
|  3 | Phones & Accessories     |         1 |    2 |     9 |
|  4 | Computer & Office        |         1 |   10 |    21 |
|  5 | Men's Clothing           |         2 |   24 |    25 |
|  6 | Women's Clothing         |         2 |   26 |    27 |
|  7 | Cell Phones              |         3 |    3 |     4 |
|  8 | Cell Phone Accessories   |         3 |    5 |     6 |
|  9 | Phone Parts              |         3 |    7 |     8 |
| 10 | Computers & Accessories  |         4 |   11 |    12 |
| 11 | Tablets & Accessories    |         4 |   13 |    14 |
| 12 | Computer Peripherals     |         4 |   15 |    16 |
| 13 | Computer Components      |         4 |   17 |    18 |
| 14 | Office Electronics       |         4 |   19 |    20 |
+----+--------------------------+--------------------------+

Sekarang, kita perlu mengubah fungsi kita:

function getCategories(PDO $db, $parentId = null)
{
    $sql = $parentId ? 'SELECT children.* FROM categories parent INNER JOIN categories children ON parent.left < children.left AND parent.right > children.left WHERE parent.id = ?' : 'SELECT * FROM categories';
    $stmt = $db->prepare($sql);
    $stmt->execute($parentId ? [$parentId] : null);
    return $stmt->fetchAll();
}

Untuk mendapatkan semua kategori di database Anda:

$allCategories = getCategories($pdo);

Keluaran:

+----+--------------------------+--------------------------+
| id | name                     | parent_id | left | right |
+----+--------------------------+--------------------------+
|  1 | Electronics              |      NULL |    1 |    22 |
|  2 | Apparel & Clothing       |      NULL |   23 |    28 |
|  3 | Phones & Accessories     |         1 |    2 |     9 |
|  4 | Computer & Office        |         1 |   10 |    21 |
|  5 | Men's Clothing           |         2 |   24 |    25 |
|  6 | Women's Clothing         |         2 |   26 |    27 |
|  7 | Cell Phones              |         3 |    3 |     4 |
|  8 | Cell Phone Accessories   |         3 |    5 |     6 |
|  9 | Phone Parts              |         3 |    7 |     8 |
| 10 | Computers & Accessories  |         4 |   11 |    12 |
| 11 | Tablets & Accessories    |         4 |   13 |    14 |
| 12 | Computer Peripherals     |         4 |   15 |    16 |
| 13 | Computer Components      |         4 |   17 |    18 |
| 14 | Office Electronics       |         4 |   19 |    20 |
+----+--------------------------+--------------------------+

Untuk mendapatkan subkategori dari suatu kategori:

$subCategories = getCategories($pdo, 1); // 1 is parent_id

Keluaran:

+----+--------------------------+--------------------------+
| id | name                     | parent_id | left | right |
+----+--------------------------+--------------------------+
|  3 | Phones & Accessories     |         1 |    2 |     9 |
|  4 | Computer & Office        |         1 |   10 |    21 |
|  7 | Cell Phones              |         3 |    3 |     4 |
|  8 | Cell Phone Accessories   |         3 |    5 |     6 |
|  9 | Phone Parts              |         3 |    7 |     8 |
| 10 | Computers & Accessories  |         4 |   11 |    12 |
| 11 | Tablets & Accessories    |         4 |   13 |    14 |
| 12 | Computer Peripherals     |         4 |   15 |    16 |
| 13 | Computer Components      |         4 |   17 |    18 |
| 14 | Office Electronics       |         4 |   19 |    20 |
+----+--------------------------+--------------------------+

Anda dapat merender HTML seperti yang ditunjukkan dalam Solusi 1 . Baca selengkapnya tentang memperbarui dan menyisipkan data baru dalam model kumpulan bersarang.

Sumber &Bacaan:




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. string yang dipisahkan koma dari nilai yang dipilih di mysql

  2. Apakah mysql_real_escape_string() diperlukan saat menggunakan pernyataan yang disiapkan?

  3. Apakah saya menggunakan Java PooledConnections dengan benar?

  4. MySQL:Cara Mendapatkan Panjang Teks Dalam Kolom

  5. Mengapa memuat objek SQLAlchemy melalui ORM 5-8x lebih lambat daripada baris melalui kursor MySQLdb mentah?