Структура комментариев в Wordpress

Ранее я сообщил что планирую рассмотреть способы хранения комментариев в популярных CMS, В данной статье я фиксирую свои наблюдения о том, как устроена система комментариев в WordPress

Структура базы данных

Описание структуры таблицы комментариев находится в файле wordpress/wp-admin/includes/schema.php и содержит следующие поля:

  • comment_ID
  • comment_post_ID
  • comment_author
  • comment_author_email
  • comment_author_url
  • comment_author_IP
  • comment_date
  • comment_date_gmt
  • comment_content
  • comment_karma
  • comment_approved
  • comment_agent
  • comment_type
  • comment_parent
  • user_id

Здесь нам интересны comment_parent и comment_ID, поскольку именно эти два поля позволяют сформировать древовидную структуру комментариев. Рассмотрим как данные извлекаются из БД и строится дерево комментариев

Методы для работы с комментариями

fill_descendants - очень важная штука для загрузки комментариев, именно этот метод строит дерево комментариев

<?php class WP_Comment_Query { protected function fill_descendants( $comments ) { global $wpdb; $levels = array( 0 => wp_list_pluck( $comments, 'comment_ID' ), ); $key = md5( serialize( wp_array_slice_assoc( $this->query_vars, array_keys( $this->query_var_defaults ) ) ) ); $last_changed = wp_cache_get_last_changed( 'comment' ); // Fetch an entire level of the descendant tree at a time. $level = 0; $exclude_keys = array( 'parent', 'parent__in', 'parent__not_in' ); do { // Parent-child relationships may be cached. Only query for those that are not. $child_ids = array(); $uncached_parent_ids = array(); $_parent_ids = $levels[ $level ]; foreach ( $_parent_ids as $parent_id ) { $cache_key = "get_comment_child_ids:$parent_id:$key:$last_changed"; $parent_child_ids = wp_cache_get( $cache_key, 'comment' ); if ( false !== $parent_child_ids ) { $child_ids = array_merge( $child_ids, $parent_child_ids ); } else { $uncached_parent_ids[] = $parent_id; } } if ( $uncached_parent_ids ) { // Fetch this level of comments. $parent_query_args = $this->query_vars; foreach ( $exclude_keys as $exclude_key ) { $parent_query_args[ $exclude_key ] = ''; } $parent_query_args['parent__in'] = $uncached_parent_ids; $parent_query_args['no_found_rows'] = true; $parent_query_args['hierarchical'] = false; $parent_query_args['offset'] = 0; $parent_query_args['number'] = 0; $level_comments = get_comments( $parent_query_args ); // Cache parent-child relationships. $parent_map = array_fill_keys( $uncached_parent_ids, array() ); foreach ( $level_comments as $level_comment ) { $parent_map[ $level_comment->comment_parent ][] = $level_comment->comment_ID; $child_ids[] = $level_comment->comment_ID; } foreach ( $parent_map as $parent_id => $children ) { $cache_key = "get_comment_child_ids:$parent_id:$key:$last_changed"; wp_cache_set( $cache_key, $children, 'comment' ); } } $level++; $levels[ $level ] = $child_ids; } while ( $child_ids ); // Prime comment caches for non-top-level comments. $descendant_ids = array(); for ( $i = 1, $c = count( $levels ); $i < $c; $i++ ) { $descendant_ids = array_merge( $descendant_ids, $levels[ $i ] ); } _prime_comment_caches( $descendant_ids, $this->query_vars['update_comment_meta_cache'] ); // Assemble a flat array of all comments + descendants. $all_comments = $comments; foreach ( $descendant_ids as $descendant_id ) { $all_comments[] = get_comment( $descendant_id ); } // If a threaded representation was requested, build the tree. if ( 'threaded' === $this->query_vars['hierarchical'] ) { $threaded_comments = array(); $ref = array(); foreach ( $all_comments as $k => $c ) { $_c = get_comment( $c->comment_ID ); // If the comment isn't in the reference array, it goes in the top level of the thread. if ( ! isset( $ref[ $c->comment_parent ] ) ) { $threaded_comments[ $_c->comment_ID ] = $_c; $ref[ $_c->comment_ID ] = $threaded_comments[ $_c->comment_ID ]; // Otherwise, set it as a child of its parent. } else { $ref[ $_c->comment_parent ]->add_child( $_c ); $ref[ $_c->comment_ID ] = $ref[ $_c->comment_parent ]->get_child( $_c->comment_ID ); } } // Set the 'populated_children' flag, to ensure additional database queries aren't run. foreach ( $ref as $_ref ) { $_ref->populated_children( true ); } $comments = $threaded_comments; } else { $comments = $all_comments; } return $comments; } }

Важно наблюдение - комментарии не хранятся каким то особым образом, используется плоская таблица с указанием родительского комментария. Далее дерево комментариев строится по требованию. Сейчас это исследование на скорую руку, я опубликую эту статью исключительно с целью индексации поисковиками.

Оставляйте комментарии, если считаете мои выводы неверными.

начало: Модуль комментариев для сайта

ну собственно на этом я и остановился
Авторизуйтесь чтобы оставлять комментарии