LoginSignup
4
1

More than 5 years have passed since last update.

WordPressのブログタイトル・URLを1時間ごとにループで順番にツイートするSQL

Last updated at Posted at 2017-12-08

アドベントカレンダー初投稿です。よろしくお願いいたします。
WordPressのブログタイトル・URLを1時間ごとにループで順番にツイートするシステムを作成してみました。
私はwordpress初心者ですので、wordpress関数や、プラグインとか使わずにやる方法でやっています。
また自動ツイートはwp_cronではなく、crontabで行なっています。

仕様など

  1. 1時間に一回、ブログ記事のタイトルとURLをツイートしていく。
  2. 公開日の古い順番にツイートしていく。全てツイートしたら最も古い投稿に戻ってまた順番にツイートする。
  3. 新しいブログ記事が公開されたら、直近のツイートは最新記事をツイートし、その後は元の順番に戻ってツイートしていく。
  4. 新しいブログ記事が2つ以上だった場合は、そのうちの古い投稿からツイートしていく。
  5. ツイートしたブログ記事は回数、ツイート日時を全て保存しておく。

また、今回作成したものは自分のSQLの勉強のために作ったものです。

cron設定

1時間おきに設定

0 */1 * * * /usr/local/bin/php /var/www/html/tweet.php

ツイートしたID、日時を保存しておくテーブルを作成

CREATE TABLE IF NOT EXISTS `wp_tweet` (
  `wp_posts_id` bigint(20) unsigned NOT NULL,
  `tweet_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`wp_posts_id`,`tweet_date`)
) DEFAULT CHARSET=utf8mb4;

現在のツイート数を見れるVIEWを作成

CREATE OR REPLACE VIEW `wp_tweet_cnt` AS
SELECT wp_posts_id,
       MAX(tweet_date) tweet_date,
       COUNT(*) cnt
FROM wp_tweet
GROUP BY wp_posts_id;

CREATE OR REPLACE VIEW `wp_posts_tweet` AS
SELECT a.id,
       a.post_date,
       a.post_title,
       a.guid,
       a.post_status,
       a.post_type,
       b.tweet_date,
       b.cnt
FROM wp_posts a
LEFT JOIN wp_tweet_cnt b
ON a.id = b.wp_posts_id
WHERE a.post_status = 'publish' -- 公開済のみを選択
AND a.post_type = 'post'; -- ブログ記事のみを選択

SQL作成

以下のようにすることで現在ある記事を順番にループしてツイートすることができました。
処理の流れとしては、対象のidをwp_tweetにインサート→wp_tweetの最新データをツイートするという感じです。
新しいブログ記事が公開されたら、次のツイートは元の順番に戻ってツイートするというのがかなりややこしい、、

tweet.php
<?php
require_once __DIR__.'/vendor/autoload.php';
use Abraham\TwitterOAuth\TwitterOAuth;

try {
    $pdo = new PDO('mysql:dbname=wp_tests;host=localhost;charset=utf8','root','password');

    $stmt = $pdo->exec(
       "INSERT INTO wp_tweet(
           wp_posts_id
        )
        SELECT a.id
        FROM   wp_posts_tweet a
        JOIN (
            SELECT tmp.*
                  ,CASE WHEN new_flg = 1
                        AND  min_cnt < last_cnt_tmp
                        THEN last_cnt_tmp
                        ELSE last_cnt    -- 前回ツイートが新規投稿だった場合、次のツイートは元の順番に戻さないといけないため、
                   END  last_tweet_cnt   -- 合計ツイート数が1 より大きいもの中で直近を前回ツイート数とする
            FROM (
                SELECT (SELECT COUNT(*) FROM wp_posts_tweet WHERE cnt IS NULL) new_post_cnt
                      ,(SELECT MIN(cnt) FROM wp_posts_tweet WHERE tweet_date <= (SELECT tweet_date FROM wp_posts_tweet WHERE cnt > 1 ORDER BY tweet_date DESC LIMIT 1)) min_cnt
                      ,(SELECT cnt FROM wp_posts_tweet ORDER BY tweet_date DESC LIMIT 1) last_cnt
                      ,(SELECT cnt FROM wp_posts_tweet WHERE cnt > 1 ORDER BY tweet_date DESC LIMIT 1) last_cnt_tmp
                      ,CASE WHEN (SELECT cnt FROM wp_posts_tweet ORDER BY tweet_date DESC LIMIT 1) = 1
                            AND  (SELECT COUNT(*) FROM wp_posts_tweet WHERE cnt > 1) > 0
                            THEN 1
                       END  new_flg  -- 前回ツイートが新規投稿だったかどうか判定するフラグ
            ) tmp
        ) b
        WHERE IFNULL(a.cnt,0) = 
                   -- 条件  :まだツイートしていない記事が1つ以上ある場合
                   -- true :合計ツイート数0のものをツイートする
              CASE WHEN b.new_post_cnt > 0
                   THEN 0
                   -- 条件  :「直近にツイートしたidの合計ツイート数-1」と同じ合計ツイート数の記事が1つ以上ある場合
                   -- true :「直近にツイートしたidの合計ツイート数-1」と同じの合計ツイート数の記事を次にツイートする 
                   WHEN (SELECT COUNT(*) FROM wp_posts_tweet WHERE cnt = b.last_tweet_cnt - 1) > 0
                   THEN b.last_tweet_cnt - 1
                   -- 条件  :「直近にツイートしたidの合計ツイート数-1」より小さい合計ツイート数の記事が1つ以上ある場合
                   -- true :「「直近にツイートしたidの合計ツイート数-1」より小さい合計ツイート数」の記事の中で最大の合計ツイート数の記事を次にツイートする
                   -- false:合計ツイート数が最大のものをツイートする
                   WHEN (SELECT COUNT(*) FROM wp_posts_tweet WHERE cnt < b.last_tweet_cnt - 1) > 0
                   THEN (SELECT MAX(cnt) FROM wp_posts_tweet WHERE cnt < b.last_tweet_cnt - 1)
                   ELSE (SELECT MAX(cnt) FROM wp_posts_tweet)
              END
        ORDER BY post_date
        LIMIT 1"
   );

    $stmt = $pdo->query("SELECT CONCAT(post_title,'\r\n',guid) post 
                         FROM wp_posts_tweet 
                         WHERE tweet_date = (SELECT MAX(tweet_date) FROM wp_posts_tweet)");

    $res = $stmt->fetch(PDO::FETCH_ASSOC);
    $paramater['status'] = $res['post'];

    $connection = new TwitterOAuth(
        'xxxxxxxxxxxxx',
        'xxxxxxxxxxxxx',
        'xxxxxxxxxxxxx',
        'xxxxxxxxxxxxx'
    );
    $connection->post(
        'statuses/update',
        $paramater
    );

} catch (PDOException $e) {

    exit($e->getMessage()); 

}

動作


最初にブログ記事が3つある場合、古いものから順にツイート(データを保存)していき、全てツイートしたら、最初のidに戻る。
Cuy7ctupkx.gif


さらに、新しい記事が2つ追加される。
この状態ですと、まず新しい記事を2つツイートした後に、元の順番に戻るので、id:182が新しい記事の次にツイートされます。

WhLxHT9vjt.gif

もっと色々なテスト条件でテストした方がいいですが、とりあえず仕様通りの動きにできたようです。
人によって、全然違う書き方をするような内容だと思いますので、やってみると結構面白いんじゃないかなと思います。

最後まで読んでいただきありがとうございました。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1