Данный топик будет полезен и интересен всем тем, кто использует виджет Cackle и хотел бы реализовать индексацию комментариев в поисковиках. Все что будет описано ниже, уже реализовано в плагине для WordPress версии 2.0 и выше. Если вы не используете данную CMS, то под катом подробное описание процесса синхронизации комментариев с примерами на php.
Для индексации, комментарии должны находится в вашей локальной базе данных и отрисовываться на html страницах с помощью вашего сайта, без использования виджета Cackle. В общем виде процесс синхронизации выглядит так:
Тут все просто, вам нужна структура данных, которая хранила бы комментарии и необходимы нам параметры(пример mysql):
Небольшие ремарки:
PS: Для простоты я не стал разделять таблицу на сущности — post, author, anonym, хотя для быстродействия и нормализации это было бы не плохо сделать.
Получить Cackle комментарии можно по следующему RESTful API сервису:
Где siteApiKey (Site API Key) и accountApiKey (Account API Key) можно найти в панели администрирования, на вкладке «Виджет», снизу выбрав WordPress, как показано на рисунках ниже:
Необязательный параметр id служит курсором, то есть данный запрос вернет все комментарии id, которых больше чем id в запросе. Если параметр id отсутствует, будут переданы первые 100 комментариев.
Синхронизация должна работать по схеме:
Интервал между вызовами API нужен из-за установленного лимита (1000 раз в час, на вызов любого API запроса).
Код на php:
Во — первых нам необходимо определить все константы для работы скрипты: подключение к БД, время крона, ключи к api Cackle
Нам понадобится функция для реализации кастомного крона:
Функция comment_sync реализует запрос к апи, и сохранит комментарии в бд.
Сама функция insert_comment() реализующая сохранение комментариев
Полный рабочий код синхронизации комментариев доступен здесь.
Финальный пункт — отрисуйте комментарии на вашей странице, в следующем виде:
Код на php:
Получим все комментарии для данной страницы из локальной БД:
Создадим шаблон-функцию для отрисовки отдельного комментария
Пробегаем по списку комментариев
Отображаем html комментариев вместе с виджетом
Как видно из js мы очищаем mc-container, для того чтобы сгенеренный нами список комментариев не отображался на странице.
В итоге на странице будет виден только виджет Cackle с комментариями, а в html коде будет список для индексации поисковыми системами.
Для индексации, комментарии должны находится в вашей локальной базе данных и отрисовываться на html страницах с помощью вашего сайта, без использования виджета Cackle. В общем виде процесс синхронизации выглядит так:
- Необходимо создать таблицы для хранения комментариев
- Добавить контроллер, которые будет получал комментарии через определенный интервал времени
- Вывести комментарии из локальной базы данных на страницу в определенный div
Создание таблицы
Тут все просто, вам нужна структура данных, которая хранила бы комментарии и необходимы нам параметры(пример mysql):
CREATE TABLE `comment` (
`comment_id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`post_id` BIGINT(20) NULL DEFAULT NULL,
`url` VARCHAR(2000) NULL DEFAULT NULL,
`parent` VARCHAR(20) NULL DEFAULT NULL,
`message` TEXT NULL,
`media` VARCHAR(1000) NULL DEFAULT NULL,
`status` VARCHAR(11) NULL DEFAULT NULL,
`rating` INT(11) NULL DEFAULT NULL,
`user_agent` VARCHAR(1000) NULL DEFAULT NULL,
`ip` VARCHAR(39) NULL DEFAULT NULL,
`author_name` VARCHAR(60) NULL DEFAULT NULL,
`author_email` VARCHAR(100) NULL DEFAULT NULL,
`author_www` VARCHAR(200) NULL DEFAULT NULL,
`author_avatar` VARCHAR(200) NULL DEFAULT NULL,
`author_provider` VARCHAR(32) NULL DEFAULT NULL,
`anonym_name` VARCHAR(60) NULL DEFAULT NULL,
`anonym_email` VARCHAR(100) NULL DEFAULT NULL,
`created` DATETIME NULL DEFAULT NULL,
PRIMARY KEY (`comment_id`)
);
CREATE TABLE `common` (
`common_name` VARCHAR(50) NULL DEFAULT NULL,
`common_value` VARCHAR(50) NULL DEFAULT NULL
)
Небольшие ремарки:
- post_id — идентификатор текущего поста, в самом простом случае url страницы
- media — медиа контент, ссылки на изображения (png, jpg, gif), видео (youtube, vimeo, вконтакте, rutube), презентации (google, slideshare)
- status — 0 на рассмотрении, 1 одобрено, 2 отклонено, 3 спам, 4 удалено
- author_provider — социальная сеть (facebook, twitter, linkedin, ..)
- created — дата создания
- common — «утильная» таблица для хранения параметров
PS: Для простоты я не стал разделять таблицу на сущности — post, author, anonym, хотя для быстродействия и нормализации это было бы не плохо сделать.
Синхронизация комментариев
Получить Cackle комментарии можно по следующему RESTful API сервису:
http://cackle.me/api/comment/list?siteApiKey={siteApiKey}&accountApiKey={accountApiKey}&id={id}
Где siteApiKey (Site API Key) и accountApiKey (Account API Key) можно найти в панели администрирования, на вкладке «Виджет», снизу выбрав WordPress, как показано на рисунках ниже:
Необязательный параметр id служит курсором, то есть данный запрос вернет все комментарии id, которых больше чем id в запросе. Если параметр id отсутствует, будут переданы первые 100 комментариев.
Синхронизация должна работать по схеме:
- Проверяем прошло ли 5 минут с последнего вызова API, если да, то идем дальше
- Берем максимальный Cackle ID комментария из локальной базы данных или 0, если комментариев нет
- Вызываем API с ключами и полученным Cackle ID
- Сохраняем комментарии
- Получаем текущее время и сохраняем его как время последнего вызова API
Интервал между вызовами API нужен из-за установленного лимита (1000 раз в час, на вызов любого API запроса).
Код на php:
Во — первых нам необходимо определить все константы для работы скрипты: подключение к БД, время крона, ключи к api Cackle
//Define db connection settings
define('CACKLE_DB_LOCALHOST', "localhost");
define('CACKLE_DB_USER', "root");
define('CACKLE_DB_PASSWORD', "");
define('CACKLE_DB_NAME', "cackle-php" );
//Define timer
define('CACKLE_TIMER', 60);
//Define Cackle API
define('ACCOUNT_API_KEY', "");
define('SITE_API_KEY', "");
Нам понадобится функция для реализации кастомного крона:
function time_is_over($cron_time){
$sql="select common_value from common where `common_name` = 'last_time'";
$get_last_time = $this->db_connect($sql, "common_value");
$now=time();
$establish_time_sql="insert into `common` (`common_name`,`common_value`) values ('last_time',$now)";
$delete_time_sql="delete from `common` where `common_name` = 'last_time' and `common_value` > 0;";
if ($get_last_time==null){
$this->db_connect($establish_time_sql);
return time();
}
else{
if($get_last_time + $cron_time > $now){
return false;
}
if($get_last_time + $cron_time < $now){
$this->db_connect($delete_time_sql);
$this->db_connect($establish_time_sql);
return $cron_time;
}
}
}
Функция comment_sync реализует запрос к апи, и сохранит комментарии в бд.
function comment_sync($accountApiKey,$siteApiKey,$cackle_last_comment=0){
$params = "accountApiKey=$accountApiKey&siteApiKey=$siteApiKey&id=$cackle_last_comment";
$host="cackle.me/api/comment/list?$params";
$response = curl($host);
$response = $this->cackle_json_decodes($response);
$this->push_comments($response); //вызов for цикла пробегающего по всем комментариям функцией insert_comment()
}
Сама функция insert_comment() реализующая сохранение комментариев
function insert_comm($comment){
...
if ($comment['parentId']) {
$comment_parent_id = $comment['parentId'];
$sql = "select comment_id from comment where user_agent='Cackle:$comment_parent_id';";
$get_parent_local_id = $this->db_connect($sql, "comment_id"); //если у коммента есть родитель,то в локальную БД пишем локальный comment_id который находим по user_agent
}
$commentdata = array(
'url' => $url,
'author_name' => $author_name,
'author_email' => $author_email,
'author_www' => $author_www,
'author_avatar' => $author_avatar,
'author_provider' => $author_provider,
'anonym_name' => $author_anonym_name,
'anonym_email' => $anonym_email,
'rating' => $comment['rating'],
'created' => strftime("%Y-%m-%d %H:%M:%S", $comment['created']/1000),
'ip' => $comment['ip'],
'message' =>$comment['message'],
'status' => $status,
'user_agent' => 'Cackle:' . $comment['id'],
'parent' => $get_parent_local_id
);
// в массив $commentdata необходимо добавить 'post_id' = > $post_id, который можно получить средствами вашего движка по url страницы с комментариями
$this->db_connect($this->insCreate("comment",$commentdata)); //запись коммента в БД
}
Полный рабочий код синхронизации комментариев доступен здесь.
Отрисовка комментариев на html
Финальный пункт — отрисуйте комментарии на вашей странице, в следующем виде:
<div id="mc-container">
[... тут нужно вывести комментарии из локальной базы данных ...]
</div>
<script>
[... код виджета Cackle ...]
</script>
Код на php:
Получим все комментарии для данной страницы из локальной БД:
function get_local_comments(){
//getting all comments for special post_id from database.
//$post_id = 1;
$get_all_comments = $this->db_connect("select * from `comment` where `post_id` = $post_id;");
return $get_all_comments;
}
Создадим шаблон-функцию для отрисовки отдельного комментария
<?php function cackle_comment( $comment) {?>
<li id="cackle-comment-<?php echo $comment['comment_id']; ?>">
<div id="cackle-comment-header-<?php echo $comment['comment_id']; ?>" class="cackle-comment-header">
<cite id="cackle-cite-<?php echo $comment['comment_id']; ?>">
<?php if($comment['author_name']) : ?>
<a id="cackle-author-user-<?php echo $comment['comment_id']; ?>" href="<?php echo $comment['author_www']; ?>" target="_blank" rel="nofollow"><?php echo $comment['author_name']; ?></a>
<?php else : ?>
<span id="cackle-author-user-<?php echo $comment['comment_id']; ?>"><?php echo $comment['anonym_name']; ?></span>
<?php endif; ?>
</cite>
</div>
<div id="cackle-comment-body-<?php echo $comment['comment_id']; ?>" class="cackle-comment-body">
<div id="cackle-comment-message-<?php echo $comment['comment_id']; ?>" class="cackle-comment-message">
<?php echo $comment['message']; ?>
</div>
</div>
</li>
<?php }
Пробегаем по списку комментариев
function list_comments(){
$obj = $this->get_local_comments();
foreach ($obj as $comment) {
$this->cackle_comment($comment);
}
}
Отображаем html комментариев вместе с виджетом
function cackle_display_comments(){ ?>
<div id="mc-container">
<div id="mc-content">
<ul id="cackle-comments">
<?php $this->list_comments(); ?>
</ul>
</div>
</div>
<script type="text/javascript">
var mcSite = '<?php echo $api_id?>';
var mcChannel = '<?php echo $post->ID?>';
document.getElementById('mc-container').innerHTML = '';
(function() {
var mc = document.createElement('script');
mc.type = 'text/javascript';
mc.async = true;
mc.src = 'http://cackle.me/mc.widget-min.js';
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(mc);
})();
</script>
<?php }
Как видно из js мы очищаем mc-container, для того чтобы сгенеренный нами список комментариев не отображался на странице.
В итоге на странице будет виден только виджет Cackle с комментариями, а в html коде будет список для индексации поисковыми системами.