X

Пакетное изменение даты для постов DLE

В DLE (да и не только в нем) есть замечательная функция - отложенный постинг. Теперь представьте ситуацию у Вас есть много контента, например 100к постов, и Вы хотите его разбросать на публикацию, да так чтобы посты получили даты от минус года до плюс 2х лет.

Собственно вот сам код, написанный и проверенный на DLE

<?php
 set_time_limit(0);  

 class db {}
 require_once('engine/data/dbconfig.php');  

 if  (!mysql_connect(DBHOST,DBUSER, DBPASS) || !mysql_select_db(DBNAME))  trigger_error('Can not connect to database',E_USER_ERROR);  

 $query="SELECT * FROM `".PREFIX."_post`";
 $result = mysql_query($query) or trigger_error('SQL: Query error at line '.__LINE__,E_USER_ERROR);  

 if (mysql_num_rows($result)>0) while ($row = mysql_fetch_assoc($result)) {
   if (file_exists('stop.txt')) die('Cancelled by the user!');
   $query="UPDATE `".PREFIX."_post` SET `date`= DATE_ADD(FROM_DAYS( FLOOR( TO_DAYS( NOW( )) +  ( RAND( ) * 1560 ) -  ( RAND( ) *730 ) ) ), INTERVAL  (FLOOR(RAND()*86400)) SECOND)  WHERE `id`=".intval($row['id']);
   mysql_query($query) or trigger_error('SQL: Query error at line '.__LINE__,E_USER_ERROR);
 }  

 echo 'Complete';  

?>

кидаем его в
www/updater.php
и запускаем
http://site.ru/updater.php

После того как скрипт будет выполнен, Ваши посты раскидаются по датам:

Апрель 2010 (2676)
Март 2010 (3879)
Февраль 2010 (3433)
Январь 2010 (3527)
Декабрь 2009 (3422)
Ноябрь 2009 (3088)
Октябрь 2009 (3008)
Сентябрь 2009 (2682)
Август 2009 (2736)
Июль 2009 (2506)
Июнь 2009 (2329)
Май 2009 (2131)
Апрель 2009 (1928)
Март 2009 (1914)
Февраль 2009 (1455)
Январь 2009 (1465)
Декабрь 2008 (1353)
Ноябрь 2008 (1064)
Октябрь 2008 (1007)
Сентябрь 2008 (804)
Август 2008 (685)
Июль 2008 (481)
Июнь 2008 (297)
Май 2008 (146)
Апрель 2008 (3)

--[добавлено 09.11.2010]--

По просьбе посетителя добавил, так же генерацию случайного времени, т.е. дата теперь будет иметь вид: 21.04.2010 11:45:01, вместо 21.04.2010 00:00:00

Так же распишу, что означают числа в скрипте:

1560 = кол-во дней вперед, от текущей даты
730 = кол-во дней назад от текущей даты
86400 = время в секундах которое будет добавляться для генерации чч:мм:сс

В основном, конечно же, Вас будут интересовать первые два параметра.

--[добавлено 25.01.2011]--
Для тех кто хочет раскидать новости только на прошлое, запрос примет вид:

$query="UPDATE `".PREFIX."_post` SET `date`= DATE_ADD(FROM_DAYS( FLOOR( TO_DAYS( NOW( )) +  ( RAND( ) * 1 ) -  ( RAND( ) *730 ) ) ), INTERVAL  (FLOOR(RAND()*86400)) SECOND)  WHERE `id`=".intval($row['id']);

--[добавлено 20.11.2013]--

Аналогичный скрипт для WordPress: Пакетное изменение даты постов в WordPress

--[добавлено 05.02.2019]--

В связи с тем, что PHP 7+ отказались от поддержки функций семейства mysql_, переписал скрипт на mysqli_. Изменений не много:

<?php 
    set_time_limit(0); 
    class db {} 
    require_once('engine/data/dbconfig.php'); 

    $link = mysqli_connect(DBHOST,DBUSER, DBPASS, DBNAME);

    if  (!$link)  trigger_error('Can not connect to database',E_USER_ERROR);  
 
    $query="SELECT * FROM `".PREFIX."_post`";
    $result = mysqli_query($link, $query) or trigger_error('SQL: Query error at line '.__LINE__,E_USER_ERROR);  
 
    if (mysqli_num_rows($result)>0) while ($row = mysqli_fetch_assoc($result)) {
       if (file_exists('stop.txt')) die('Cancelled by the user!');
       $query="UPDATE `".PREFIX."_post` SET `date`= DATE_ADD(FROM_DAYS( FLOOR( TO_DAYS( NOW( )) +  ( RAND( ) * 1560 ) -  ( RAND( ) *730 ) ) ), INTERVAL  (FLOOR(RAND()*86400)) SECOND)  WHERE `id`=".intval($row['id']);
       mysqli_query($link,$query) or trigger_error('SQL: Query error at line '.__LINE__,E_USER_ERROR);
     }  
 
     echo 'Complete';

Версия не требующая подключения dbconfig.php, но требующая указать данные подключения к базе в самом скрипте

<?php

define('DBHOST', 'localhost');
define('DBUSER', 'mysql');
define('DBPASS', 'mysql');
define('DBNAME', 'sandbox');

define('PREFIX', 'dle');

$link = mysqli_connect(DBHOST,DBUSER, DBPASS, DBNAME);

if  (!$link)  trigger_error('Can not connect to database',E_USER_ERROR);  
 
$query="SELECT * FROM `".PREFIX."_post`";
$result = mysqli_query($link, $query) or trigger_error('SQL: Query error at line '.__LINE__,E_USER_ERROR);  
 
if (mysqli_num_rows($result)>0) while ($row = mysqli_fetch_assoc($result)) {
   if (file_exists('stop.txt')) die('Cancelled by the user!');
   $query="UPDATE `".PREFIX."_post` SET `date`= DATE_ADD(FROM_DAYS( FLOOR( TO_DAYS( NOW( )) +  ( RAND( ) * 1560 ) -  ( RAND( ) *730 ) ) ), INTERVAL  (FLOOR(RAND()*86400)) SECOND)  WHERE `id`=".intval($row['id']);
   mysqli_query($link,$query) or trigger_error('SQL: Query error at line '.__LINE__,E_USER_ERROR);
}  
 
echo 'Complete';

--[добавлено 08.02.2019]--

Написал скрипт, где все это можно сделать в пару кликов: https://github.com/orlov0562/ddle

--[добавлено 13.02.2019]--

Обновил скрипт , скачать можно тут: ddle.php, репозиторий тут: https://github.com/orlov0562/ddle

Добавил обновление комментариев

Между комментариями можно задать интервал (по-умолчанию от 1 до 7 дней).

Работает это так:
- обновляется дата поста
- выбираются все комментарии к посту с сортировкой по дате добавления
- поочередно комментарии обновляются
- к дате поста добавляется случайное смещение из заданного диапазона (например, 2 дн, из диапазона от 1 дн до 7дн )
- это смещение, выбирается относительно даты поста/комментария

Т.е. даты комментариев внутри одного поста будут обновлены от даты поста, в настройках можно задать интервал времени между комментариями

Тэги: datedlemysql

Комментарии (51)

  • Здравствуйте. Спасибо за скрипт. Очень выручает. Подскажите, пожалуйста, как сделать, чтобы новости распределились по датам равномерно? Например, 100 000 новостей на 1000 дней ровно по 100 штук на дату. Спасибо

    • Привет, к сожалению, в контексте реализации текущего скрипта, такого не сделать. Мб, в будущем добавлю, но пока такой возможности нет.

  • Виталий, здравствуйте!
    Есть возможность доработать скрипт, чтобы можно было массово менять дату редактирования новостей в заданном диапазоне дат?

    p.s. Ваш скрипт почему-то на хостинге циклически просит ввести логин/пароль, а на локальном openserver работает.

    • Привет,
      1) Не могу точно сказать, почему не работает на хостинге, но могу посоветовать просто отключить авторизацию. Открой файл и измени

      $useHttpBasicAuth = true;

      на

      $useHttpBasicAuth = false;

      Это полностью отключит авторизацию, только не забудь удалить файл, после того как поработаешь.

      2) Про массовую смену в диапазоне дат. Подумаю как это реализовать в интерфейсе, пока это можно делать через расширенные настройки.
      - Нажать "Расширенные настройки"
      - Поставить галочку "Добавить SQL к выборке постов"
      - В поле "Добавить SQL к выборке постов", написать:

      date > "2019-02-12 16:48:20" AND date <= "2019-02-13 16:48:20"

      таким же образом можно делать и более сложные выборки используя любые столбцы таблицы dle_post, например, можно обновить только посты определенного автора из определенной категории

      - Просмотреть результирующий SQL можно кнопкой "Показать SQL"

  • Спасибо большое автору за столь чудесное решение простой задачи. Возможно, Вы подскажете еще такой вопрос.
    Мне нужно, чтобы скрипт выполнял такую же задачу в 3 этапа:
    Для первых допустим 200 публикаций дата бралась рандомно (0... +14 дней)
    Потом для следующих 10 000 публикаций RAND +15 + 45
    И далее последние 1800 публикаций растянулись бы от +45 дней до нескольких лет.

    Возможно ли такое реализовать? Отсчет публикации можно брать по id или по счетчику какому-нибудь срабатываний

    • Привет :)

      1) Делаешь бэкап базы

      2) Качаешь файлик вот отсюда:
      https://raw.githubusercontent.com/orlov0562/ddle/master/ddle.php
      копируешь его в корень сайта.

      3) Открываешь site.com/ddle.php , данные для входа admin / ddle

      4) Там в расширенных настройках ставишь:
      а) нужные даты; сортировка id 0-9; лимит: начать с = 0, кол-во = 200
      б) нужные даты; сортировка id 0-9; лимит: начать с = 201, кол-во = 10000
      в) нужные даты; сортировка id 0-9; лимит: начать с = 10201, кол-во = 1000000

      5) Если делаешь прямо на хостинге, не забудь удалить файл ddle.php когда закончишь

      Подробнее про скрипт и скриншот, в моем гитхабе: https://github.com/orlov0562/ddle

      • Невероятно просто! Спасибо огромнейшее!
        А комментарии можно каким-то образом учитывать и ставить их дату позже чем дата поста? :)))

  • Спасибо за скрипт! А есть версия, поддерживаемя php 7.0? простая замена. mysql на mysqli на помогает

    • Привет! Спасибо за комментарий. Версию с mysqli добавил в конец статьи.

  • Приветствую!
    Подскажите пожалуйста правильный код, чтобы рандомно изменить даты у постов которые были опубликованы на сайте в промежутке от 27 января 2013 до 20 апреля 2016 - в этом же промежутке т.е. от 27 января 2013 до 20 апреля 2016 Новости которые идут после 20 апреля 2016 не трогать. Например была новость от 30 января 2013, я запускаю файл и чтобы новость стала например уже от 10 марта 2014 и т.д.
    Сделал код (самый первый), залил на сайт, запускаю файл, но ничего не происходит - белый экран.
    DLE 10.6 utf-8

    Спасибо!

  • Круто уж столько вариантов обсудили, подскажите как еще сделать выбор по определенному пользователю?

    • Добавить условие сюда

      $query="SELECT * FROM `".PREFIX."_post`";

      примерно вот так

      $query='SELECT * FROM `'.PREFIX.'_post` WHERE `autor`="username"';

  • Наверное что с хостингом, выходит ошибка даже при LIMIT 1, скрипт не срабатывает.

    <?php

    set_time_limit(0);

    class db {}
    require_once('engine/data/dbconfig.php');

    if (!mysql_connect(DBHOST,DBUSER, DBPASS) || !mysql_select_db(DBNAME)) trigger_error('Can not connect to database',E_USER_ERROR);

    $query="SELECT * FROM `".PREFIX."_post` AND `date`>"2016-11-17 00:00:00" ; // от этой даты + 44дня

    $result = mysql_query($query) or trigger_error('SQL: Query error at line '.__LINE__,E_USER_ERROR);

    if (mysql_num_rows($result)>0) while ($row = mysql_fetch_assoc($result)) {
    if (file_exists('stop.txt')) die('Cancel by the user!');
    $query="UPDATE `".PREFIX."_post` SET `date`= DATE_ADD(FROM_DAYS( FLOOR( TO_DAYS( NOW( )) + ( RAND( ) * 1 ) - ( RAND( ) *44 ) ) ), INTERVAL (FLOOR(RAND()*86400)) SECOND) WHERE `id`=".intval($row['id']);
    mysql_query($query) or trigger_error('SQL: Query error at line '.__LINE__,E_USER_ERROR);
    }

    echo 'Complete';

    ?>

    Подскажите все верно? если от текущей даты + 44 дня

    • Нужно понять что за ошибка происходит. Если на экране просто пусто, попробуй посмотреть логи в панеле управления. Там всего скорее есть что-то вроде "Error log" или "Журнал ошибок" и там после запуска скрипта должны появляться сообщения об ошибках. Эти сообщения и расскажут что именно происходит. Например, на сервере может не быть поддержки mysql_* функций, т.к. они старые более не рекомендуются к использованию, может еще 1000 причин быть, смотри в логи что за ошибка происходит. Так же, как вариант, создай тикет в поддержку, написав что у тебя скрипт не работает и спроси где посмотреть ошибки.

  • Здравствуйте Виталий, покажите пожалуйста пример скрипта от текущей даты +30 дней. Посмотрела комментарии, но к сожалению не совсем поняла приведенного примера.

    Если возможно полностью рабочий вариант скрипта, заранее спасибо!

    • Привет! В самом первом примере строку с запросом ($query="...") замени на:

      $query="UPDATE `".PREFIX."_post` SET `date`= SELECT DATE_ADD(NOW(), INTERVAL(FLOOR(RAND()*30*24*60*60)) SECOND) WHERE `id`=".intval($row['id']);

      тут 30*24*60*60 = 30 дней в секундах

      и не забудь перед тестами сделать бэкап

      • это из консоли:

        Failed to load resource: the server responded with a status of 500 (Internal Server Error)

        К сожалению не сработал запрос, добавили время на выполнения скрипта, открылась пустая страница без ошибок в консоли, но новости в базе остались прежними, не подскажите с чем связано?

        • Возможно, это связанно с большим кол-вом постов и нехваткой ресурсов, т.е. скрипту попросту не хватает времени.
          Попробуй следующее:
          - проверь работает ли этот код вообще, добавь в запрос выбора постов "LIMIT 1", Т.е.

          $query='$query="SELECT * FROM `".PREFIX."_post` LIMIT 1";';

          это ограничит изменения постов до одного и будет понятно ошибки в большом кол-ве постов или нет.
          - Если ошибок нет, тогда попробуй следующее:
          1) Если есть доступ по ssh, авторизоваться и выполнить скрипт из консоли - так не будет лимитов на время выполнения.
          2) Если доступа нет, нужно узнать последний id поста, это можно сделать либо в админке, либо в phpmyadmin-е. Дальше, за 1 запуск обрабатывать только часть постов, например 500. Надо будет перед каждым запуском менять ограничения так:

          $query='$query="SELECT * FROM `".PREFIX."_post` WHERE id >=1 AND id < 500";';

          обработает записи 1-500, потом меняешь дальше

          $query='$query="SELECT * FROM `".PREFIX."_post` WHERE id >=500 AND id < 1000";';

          ну, и дальше по аналогии, пока не дойдешь до максимального id

  • Можете помочь за вознаграждение? (если возможно, подскажите как с Вами связаться)

    • В данный момент, нет. Если нужно срочно, попробуй найти кого-то на weblancer.net или freelansim.ru . Если не срочно, то зарегистрируйся на форуме, создай тему в разделе Помощь пользователям и опиши подробно что хочешь сделать и какие у тебя исходные данные (имя таблицы, название полей и т.д.). Попробую помочь безвозмездно, в свободное время.

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

    Всеобщем возникла непростая для меня задача. Есть сайт на DLE с заполненными (description), но к сожалению в полной новости описание отсутствует, т.к заполняли именно поле Описание для статьи (description).

    Не поможете реализовать скрипт или запрос что-бы скопировать данные из таблиц?

    посмотрел в базе: descr varchar(200) нужно скопировать в full_story text (желательно в начало таьлицы перед <!--dle_image_begin во основном в постах картинки и ножно реализовать к ним описание.

    • Привет. Давно не работаю с DLE и мне лень туда заглядывать.

      Если просто нужно скопировать одно поле в начало другого, то запрос будет выглядеть примерно так:

      UPDATE `table` SET `full_story_text` = CONCAT(`descr`, ' ', `full_story_text`)

      Про строковые операции в mysql можно почитать тут: Mysql string functons

      И не забудь сделать бэкап базы, перед тестами :)

      • #1146 - Table '**.table' doesn't exist к сожалению несрабатывает запрос((

        • Это был пример запроса, тебе его надо подогнать под свои нужды. В частности, вместо table указать нужную таблицу, проверить название полей (descr, full_story_text и т.д.) и по необходимости дополнить всем остальным (WHERE, LIMIT и т.д.).

  • Здраствуйте, на первом сайте сработало (3к новостей).

    А вот на 2 к сожалению не вышло, (20 к новостей) - пишет 502 Bad Gateway, возможно как-то поменять скрипт чтобы изменить нагрузку на сервер, спасибо!

    • Это ограничение nginx-а на вермя выполнения скрипта. Самый простой вариант - запустить скрипт из командной строки авторизовавшись по ssh. Если такой возможности нет, тогда разделить диапозон по id на равные части, типа того:


      ... WHERE (id>=1 AND id < 100) AND (...)

      потом следующий диапозон:

      ... WHERE (id>=100 AND id < 200) AND (...)

      и т.д.

      • Возможно это из-за недостачи памяти на сервере. Пишет "Killed", если пытаюсь запустить с ssh.

        Можно получить полную строчку, после того как начинаеться - "WHERE".

        Я в этом коде вообще не понимаю, не получилось запустить ))

        • Killed = не должно быть, возможно какие-то ограничения провайдера, это обсуждать с ним надо.

          чтобы добавить выборку по id, для DLE (первый пример в статье), надо, это


          $query="SELECT * FROM `".PREFIX."_post`";

          изменить на


          $query="SELECT * FROM `".PREFIX."_post` WHERE `id`>=1 AND `id`<=100";

          и дальше, по аналогии, пока не пройдешь весь диапозон:


          $query="SELECT * FROM `".PREFIX."_post` WHERE `id`>=100 AND `id`<=200";

          максимальный id можно глянуть либо в админке, либо в phpmyadmin, либо в adminer

          Есть еще другой вариант:
          - качаешь openserver к себе на пк
          - перетаскиваешь базу и сайт в него
          - делаешь все что задумал, без ограничений
          - готовую версию заливаешь обратно на хостинг

          • Получилось! Вы даже для инвалида костыль подберёте ))

  • Возможно ли раскидать материалы только от 22-04-16 например, а все что раньше не трогать?

    • Возможно:

      1) если даты на которые будут раскидываться посты, так же начинаются от 22-04-16, тогда можно добавить условие в выборку, типа того:

      UPDATE tbl ... WHERE (...)
      AND `date`>"2016-04-22 00:00:00"

      2) другой вариант, делать выборку изменяемых постов подзапросом:

      UPDATE tbl ... WHERE (...)
      AND `id` IN (SELECT id FROM tbl WHERE date>"2016-04-22 00:00:00" AND date<"2016-04-27 00:00:00")

  • А можно ли сделать тоже самое, но не от текущей даты а от даты самих постов плясать? Тоесть к примеру каждый пост поменяет дату +/- месяц от собственной даты (даты самого поста), это позволило бы сохранить общий порядок когда есть посты на пару лет назад

    • Можно, SQL будет типа того:

      .. SET `date`= DATE_ADD(`date`, INTERVAL 1 MONTH) WHERE ..

      интервал можно указывать в разных форматах, как "+время" так и "-время". Подробнее про форматы тут: Date and Time Functions

  • Хороший скрипт, как реализовать для определенных категорий???

    • Привет, спасибо :)

      У меня нет сейчас возможности убедиться в правильном названии поля, но если мне не изменяет память, в таблице `dle_post` есть поле `category`, в котором хранится id категории. Это можно проверть в phpMyAdmin или Adminer.

      Если там действительно есть такое поле, тогда надо этот запрос:

      $query="SELECT * FROM `".PREFIX."_post`";

      поменять на:

      $query="SELECT * FROM `".PREFIX."_post` WHERE `category`=123";

      либо если нужно сразу несколько категорий, тогда так:

      $query="SELECT * FROM `".PREFIX."_post` WHERE `category` IN (123, 124, 125)";

      если в WHERE будут какие-то другие поля кроме категории, по которым нет индекса, а постов много (например больше 100k), тогда быстрее будет работать запрос такого вида:

      $query="SELECT * FROM `".PREFIX."_post` WHERE `xfields`<>"" AND (`category`=123 OR `category`=124 OR `category`=125)";

  • Еще один SQL сниппет позволяющий отнять кол-во дней от текущей даты для всех постов:

    UPDATE `dle_post` SET `date` = DATE_SUB(`date`, INTERVAL 365 DAY)

  • Отличный скрипт! Неплохо было бы сделать аналогию, но только для комментариев к постам...

      • Впринципе неплохо работает вариант просто в скрипте заменить _posts на _comments.
        Но даты комментариев разбрасываются случайно, иногда получается, что комментарий размещен раньше, чем была размещена сама статья. Нужно встроить проверку на то, чтобы дата комментария была не раньше даты поста, к которому он размещен...

        • Надо после раскидывания всех постов, выполнить такой запрос:
          UPDATE `wp_comments` SET
          `comment_date` = DATE_ADD(FROM_DAYS( FLOOR( TO_DAYS( (SELECT `post_date` FROM `wp_posts` WHERE `ID`=`wp_comments`.`comment_post_ID`) ) + ( RAND( ) * 365 ) ) ), INTERVAL (FLOOR(RAND()*86400)) SECOND),
          `comment_date_gmt` = `comment_date`

          Тут 365 = это кол-во дней от даты поста, т.е. "дата поста" + (от 0 до 365 дней). Единственное не знаю работает ли отложенный постинг для комментариев.. Отпишите кто воспользуется :)

  • Подскажите пожалуйста как сделать что бы новости распределились типа они были залиты 5 лет назад самая первая и до 10 лет назад были рандомно распределены
    Заранее большое спасибо за ответ

    • В первом скрипте из поста изменится строчка на такую:

      $query="UPDATE `".PREFIX."_post` SET `date`=DATE_ADD( FROM_DAYS( FLOOR( TO_DAYS( NOW( ) ) - 1825 - ( RAND( ) *1825 ) ) ) , INTERVAL( FLOOR( RAND( ) *86400 ) )
      SECOND ) WHERE `id`=".intval($row['id']);

      Мы отнимаем от текущей даты 5 лет: 1825 = 5 * 365
      Потом рандомно отнимаем еще от 1го до 1825 дней
      В итоге получается диапозон от -10 до -5 лет от текущей даты

  • Помогите, пожалуйста, как переделать такой скрипт для работы с wordpress?

  • Большое спасибо за столь развернутый и оперативный ответ! Вечером обязательно попробую :-)

  • Привет, Мария!

    Смотри, вычесть кол-во дней можно с помощью команды INTERVAL * DAY

    SELECT NOW() - INTERVAL 60 DAY

    Вот тут подробнее: mysql, date and time functions

    соответственно, чтобы тебе передвинуть все даты постов на 60 дней назад надо выполнить такой запрос в скрипте:

    $query="UPDATE `".PREFIX."_post` SET `date`= `date` - INTERVAL 60 DAY WHERE `id`=".intval($row['id']);

    либо тоже самое можешь сделать без скрипта, например в phpmyadmin:

    UPDATE `dle_post` SET `date`= `date` - INTERVAL 60 DAY

    Важно! Только сделай бэкап базы перед тем как будешь выполнять эти команды!

  • Виталий, скажите пожайлуста, а что изменить в этих строках, чтобы все даты автоматически поменялись ровно на 60 дней назад, а не рандомно как сейчас? Понимаю что нужно убрать RAND, но как это сделать правильно, к сожалению не знаю:(