Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Jak zaimplementować hierarchiczne witryny cms?

Oto struktura tabeli, której użyłem do testowania tego -

CREATE TABLE  `test`.`pages` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    `slug` varchar(45) NOT NULL,
    `title` varchar(45) NOT NULL,
    `content` text NOT NULL,
    `parent_id` int(10) unsigned DEFAULT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `UQ_page_parent_id_slug` (`parent_id`,`slug`),
    CONSTRAINT `FK_page_parent_id` FOREIGN KEY (`parent_id`) REFERENCES `pages` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Zwróć uwagę na unikalny klucz (parent_id, slug). Jest to klucz do uzyskania najlepszej wydajności z następującego zapytania. Przetestowałem to z 50 tys. wierszy i nadal zwracało to mniej niż 1 ms dla ścieżki z pięcioma ślimakami - /cms/slug-1/slug-2/slug-3/slug-4/slug-5/

Oto kod PHP, który wymyśliłem, aby zbudować odpowiednie zapytanie -

<?php

// I will assume the rest of the url has already been stripped away
$url = '/fruits/tropical/bananas/';

// lets just make sure we don't have any leading or trailing /
$url = trim($url, '/');

// now let's split the remaining string based on the /
$aUrl = explode('/', $url);

/**
* Now let's build the query to retrieve this
*/

// this array stores the values to be bound to the query at the end
$aParams = array();

$field_list = 'SELECT p1.* ';
$tables = 'FROM pages p1 ';
$where = "WHERE p1.parent_id IS NULL AND p1.slug = ? ";

// this array stores the values to be bound to the query at the end
$aParams[] = $aUrl[0];

// if we have more than one element in our array we need to add to the query
$count = count($aUrl);

for ($i = 1; $i < $count; $i++) {

    // add another table to our query
    $table_alias = 'p' . ($i + 1);
    $prev_table_alias = 'p' . $i;
    $tables .= "INNER JOIN pages $table_alias ON {$prev_table_alias}.id = {$table_alias}.parent_id ";

    // add to where clause
    $where .= "AND {$table_alias}.slug = ? ";
    $aParams[] = $aUrl[$i];

    // overwrite the content of $field_list each time so we
    // only retrieve the data for the actual page requested
    $field_list = "SELECT {$table_alias}.* ";

}

$sql = $field_list . $tables . $where;

$result = $this->db->query($sql, $aParams);


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. skrócone zapytanie PDO

  2. mysql wyszukiwanie słów kluczowych

  3. Długość nazwy tabeli lub nazwy kolumny wpływa na wydajność?

  4. SQL do pliku outfile - gdzie jest przechowywany plik? (MySQL, Windows)

  5. Wybierasz wszystkie kolumny, które zaczynają się od XXX, używając symbolu wieloznacznego?