Steamer Lane Studio技術備忘録WordPress

WordPressの投稿をX=Twitterへ自動投稿するPHPコード-非プラグイン&非ライブラリ

wordpress WordPressの投稿をX=Twitterへ自動投稿するPHPコード-非プラグイン&非ライブラリ
最終更新日: 2025年3月8日

WordPressの投稿をX=Twitterへ自動投稿するPHPコード-非プラグイン&非ライブラリ先日「Autoshare for twitter」の改造コードを作ったが、API2移行以来できなかった連携自動投稿コードができた。
件のプラグインなぜか2.0でないとPOSTしないので、バージョンアップせず使って、タグをハッシュに変えて投稿したかったので弄ったが、コードができたことで投稿内容も自由にカスタマイズできるようになった。
そのコード案内。

作動確認要件

  • WordPress 6.7.2
  • ACFとxml用他必要なプラグインを最低限使用
  • php8up
  • MySql8
  • さくら(ビジネスのなんか)、KAGOYA(ライトだったかな)

まぁ、多分大概のレンタルサーバーなら動くだろうと思う。
*テーマファイルなどの文字コードによってはバグるかも知れません。

メリット

  • 軽い
  • 無料(function.php記述とか手間はかかる)
  • シンプルコードでカスタマイズできるので投稿内容自在(ただし、OGP使用が前提のシンプルコード)
  • 環境が変わって連携できなくなっても修正できるかも

デメリット

  • 開発面倒なのでプラットフォームの改変で使えなくなるかも(逆に自前で対応できるかも)
  • 自己責任です(タダだから当然)
  • Xの都合でいつ使えなくなるかわからない(プラグイン・ライブラリ皆そうだけど)

コード(1)Bearertokenの記述

作成当初はwp-config.phpに記述していたが、作業性が悪いのでfunction.php記述とした。
<?php
// Twitter API 2.0用Bearerトークン直書き設定
add_action('init', function() {define('TWITTER_BEARER_TOKEN', 'YOUR_BEARER_TOKEN');});
?>
これの「YOUR_BEARER_TOKEN」にBearertokenを書く。
次のメイン部分と一緒でOK。
当方テーマでは、WPの設定画面のカスタムフィールド記述でDBから呼び出す形なので、APIキーなどもそうだが、この投稿用にちと作り直した。

コード(2)メイン部分

<?php// Twitter API 2.0連携自動投稿用ファイルrequire_once ABSPATH . 'wp-includes/pluggable.php';function twitter_auto_post($post_id, $post, $update) {if (wp_is_post_revision($post_id)) return;if ($post->post_status !== 'publish') return;// 更新時の自動投稿を防止if ($update && !wp_next_scheduled('future_to_publish')) return;if ($update && get_post_meta($post_id, '_twitter_posted', true)) return;

$consumer_key = 'twi_api_key';$consumer_secret = 'twi_api_keysec';$access_token = 'twi_acctoken';$access_token_secret = 'twi_acctokensec';

$post_title = get_the_title($post_id);$post_url = get_permalink($post_id);

$tags = get_the_tags($post_id);$hashtags = '';if ($tags) {foreach ($tags as $tag) {$hashtags .= ' #' . $tag->name;}}

$message = $post_title . "\n" . $post_url . $hashtags;

$twitter_api_url = 'https://api.twitter.com/2/tweets';$payload = json_encode(['text' => $message]);

$oauth = ['oauth_consumer_key' => $consumer_key,'oauth_token' => $access_token,'oauth_nonce' => wp_generate_password(16, false),'oauth_timestamp' => time(),'oauth_signature_method' => 'HMAC-SHA1','oauth_version' => '1.0'];

$base_info = build_base_string($twitter_api_url, 'POST', $oauth);$composite_key = rawurlencode($consumer_secret) . '&' . rawurlencode($access_token_secret);$oauth['oauth_signature'] = base64_encode(hash_hmac('sha1', $base_info, $composite_key, true));

$header = [build_authorization_header($oauth), 'Content-Type: application/json'];

$options = ['http' => ['header' => implode("\r\n", $header),'method' => 'POST','content' => $payload,'ignore_errors' => true]];

$context = stream_context_create($options);$result = file_get_contents($twitter_api_url, false, $context);

if ($result === false) {error_log('Twitter連携投稿に失敗しました: ' . print_r($http_response_header, true));} else {update_post_meta($post_id, '_twitter_posted', 1);foreach ($http_response_header as $header_line) {if (stripos($header_line, 'HTTP/') === 0) {error_log('HTTPステータス: ' . $header_line);}if (stripos($header_line, 'x-rate-limit-reset:') !== false) {error_log('X-Rate-Limit-Reset: ' . $header_line);}}}}

function build_base_string($baseURI, $method, $params) {ksort($params);$r = [];foreach ($params as $key => $value) {$r[] = "$key=" . rawurlencode($value);}return $method . "&" . rawurlencode($baseURI) . '&' . rawurlencode(implode('&', $r));}

function build_authorization_header($oauth) {$r = 'Authorization: OAuth ';$values = [];foreach ($oauth as $key => $value) {$values[] = "$key=\"" . rawurlencode($value) . "\"";}$r .= implode(', ', $values);return $r;}

function add_twitter_post_button() {add_meta_box('twitter_post_meta_box','Twitterへの自動投稿','render_twitter_post_button','post','side','high');}add_action('add_meta_boxes', 'add_twitter_post_button');

function render_twitter_post_button($post) {echo '<button type="button" id="twitter-post-button" class="button">Twitterに再投稿</button>';echo '<script>jQuery(document).ready(function($) {$("#twitter-post-button").on("click", function() {var data = {action: "twitter_manual_post",post_id: ' . $post->ID . '};$.post(ajaxurl, data, function(response) {alert(response);});});});</script>';}

add_action('wp_ajax_twitter_manual_post', function() {if (isset($_POST['post_id'])) {$post_id = (int) $_POST['post_id'];$post = get_post($post_id);delete_post_meta($post_id, '_twitter_posted');twitter_auto_post($post_id, $post, false);echo 'Twitterに投稿しました。';} else {echo '投稿IDが見つかりません。';}wp_die();});

add_action('save_post', function($post_id, $post, $update) {if (defined('DOING_CRON') && DOING_CRON) {if (get_post_meta($post_id, '_twitter_posted', true)) return;twitter_auto_post($post_id, $post, false);} elseif (!$update) {twitter_auto_post($post_id, $post, false);}}, 10, 3);

// カスタムテーブルエラー回避用の存在確認処理を追加function check_custom_codes_table() {global $wpdb;$table_name = $wpdb->prefix . 'custom_codes';if ($wpdb->get_var("SHOW TABLES LIKE '{$table_name}'") !== $table_name) {remove_action('edit_form_after_title', 'add_custom_code_button');}}add_action('admin_init', 'check_custom_codes_table');

?>

$consumer_key = get_option(‘twi_api_key’);
$consumer_secret = get_option(‘twi_api_keysec’);
$access_token = get_option(‘twi_acctoken’);
$access_token_secret = get_option(‘twi_acctokensec’);
上記四行の「twi_api_key」「twi_api_keysec」「twi_acctoken」「twi_acctokensec」にTwitter(X)のAPIキーとシークレット、アクセストークンとそのシークレットを記述。

$tags = get_the_tags($post_id);
$hashtags = ”;
if ($tags) {foreach ($tags as $tag) {$hashtags .= ‘ #’ . $tag->name;
}
}
この部分でタグに#を付けて投稿内容に追加しているので、これに関する部分を削除すればタグに#を付けて投稿されることはなくなると思う。
ここではやってないので必要なら自己責任で。

-推奨-動作確認のためのwp-config.php記述

define('WP_DEBUG', true);define('WP_DEBUG_LOG', true);define('WP_DEBUG_DISPLAY', false); // 表示せずログにのみ記録

設置当初はこれでdebug.logを確認することを推奨。
レートリミットで15分は間をあけた方が良い。実際連投できるが、連投した場合レートリミットが長くなっていた。
プラグイン「PPF」での予約投稿でも稼働するので、連投するなら予約投稿機能をい使って分けた方がベター。
「Too many rquests」と出るが、一度の投稿でもDebug logにはそう書かれる。

Twitter(X)の各キーなどはDeveloper Portalで

ここで各キーを取得しないと始まらないので、Twitter(X)ログイン中のブラウザでdeveloper potalにアクセスして作成しましょう。