首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 封裝 Twitter API 訪問類:獲取用戶時間線、解析連結/標籤/提及

     編輯:PHP 相關知識

Twitter API v1.1 客戶端類別封裝

雖然 Twitter API 已升級至 v2,但本封裝類展示了使用 cURL 呼叫 REST API、XML 解析、實體連結化等核心技術,可作為社交媒體 API 整合的參考架構。

完整類別程式碼

<?php
class TwitterClient {
    private const API_BASE = 'https://api.twitter.com/1.1/statuses/user_timeline.xml';
    private const ENTITY_REGEX_URL = '@(https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?)@';
    private const ENTITY_REGEX_MENTION = "/(^|[\n ])@([^ \"\t\n\r<]*)/";
    private const ENTITY_REGEX_HASHTAG = "/(^|[\n ])#([^ \"\t\n\r<]*)/";

    /**
     * 獲取用戶推文並生成 HTML
     * @param string $screenName Twitter 用戶名(不含 @)
     * @param int $count 獲取條數(最大 200)
     * @param string $timezone 時區識別碼
     * @param bool $includeReplies 是否包含回覆推文
     * @return string HTML 片段
     */
    public function getUserTimelineHtml(string $screenName, int $count = 3, string $timezone = 'Asia/Taipei', bool $includeReplies = false): string {
        date_default_timezone_set($timezone);
        
        $xml = $this->fetchTimelineXml($screenName, $count);
        if(!$xml) {
            return $this->renderError('Twitter 服務暫時無法訪問,請稍後再試。');
        }

        $html = '<div id="tweets">' . "\n";
        $tweetCount = 0;
        
        foreach($xml->status as $status) {
            // 過濾回覆推文
            if(!$includeReplies && $this->isReply($status->text)) continue;
            if($tweetCount >= $count) break;
            
            $tweetText = $this->processEntities($status->text);
            $createdAt = date('D jS M Y H:i', strtotime($status->created_at));
            
            $html .= '<div class="status">' . "\n";
            $html .= $tweetText . "\n";
            $html .= '</div>' . "\n";
            $html .= '<div class="details">' . $createdAt . '</div>' . "\n\n";
            $tweetCount++;
        }
        
        $html .= '</div>' . "\n";
        return $html;
    }

    /**
     * 呼叫 API 獲取 XML 回應
     */
    private function fetchTimelineXml(string $screenName, int $count): ?SimpleXMLElement {
        $url = self::API_BASE . "?screen_name=" . urlencode($screenName) . "&count=" . min($count, 200);
        
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_CONNECTTIMEOUT => 5,
            CURLOPT_TIMEOUT => 10,
            CURLOPT_SSL_VERIFYPEER => true,
            CURLOPT_USERAGENT => 'PHP-TwitterClient/1.0',
        ]);
        
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        
        if($httpCode !== 200 || !$response) {
            error_log("Twitter API error: HTTP $httpCode for $screenName");
            return null;
        }
        
        try {
            return new SimpleXMLElement($response);
        } catch(Exception $e) {
            error_log("Twitter XML parse error: " . $e->getMessage());
            return null;
        }
    }

    /**
     * 處理推文中的實體:URL、@提及、#標籤轉為可點擊連結
     */
    private function processEntities(string $text): string {
        $text = utf8_decode($text);
        
        // URL 連結化
        $text = preg_replace(self::ENTITY_REGEX_URL, '<a href="$1" target="_blank" rel="noopener">$1</a>', $text);
        
        // @提及 連結化
        $text = preg_replace_callback(self::ENTITY_REGEX_MENTION, function($m) {
            return $m[1] . '<a href="https://twitter.com/' . urlencode($m[2]) . '" target="_blank" rel="noopener">@' . $m[2] . '</a>';
        }, $text);
        
        // #標籤 連結化
        $text = preg_replace_callback(self::ENTITY_REGEX_HASHTAG, function($m) {
            return $m[1] . '<a href="https://twitter.com/hashtag/' . urlencode($m[2]) . '" target="_blank" rel="noopener">#' . $m[2] . '</a>';
        }, $text);
        
        return $text;
    }

    /**
     * 判斷是否為回覆推文(以 @ 開頭)
     */
    private function isReply(string $text): bool {
        return strpos(ltrim($text), '@') === 0;
    }

    private function renderError(string $message): string {
        return '<div id="tweets"><div class="status">' . htmlspecialchars($message) . '</div></div>';
    }
}

// 使用範例
$twitter = new TwitterClient();
echo $twitter->getUserTimelineHtml('php_net', 5, 'Asia/Taipei');
?>

CSS 樣式建議

#tweets { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; max-width: 500px; }
.status { padding: 12px 0; border-bottom: 1px solid #e1e8ed; line-height: 1.5; word-wrap: break-word; }
.status a { color: #1da1f2; text-decoration: none; }
.status a:hover { text-decoration: underline; }
.details { font-size: 0.85em; color: #657786; margin-top: 4px; }

遷移至 Twitter API v2 重點

  • 端點改為 https://api.twitter.com/2/users/:id/tweets
  • 需使用 Bearer Token (OAuth 2.0) 而非舊版 OAuth 1.0a
  • 回應格式為 JSON,欄位名稱變更(如 created_at 格式不同)
  • 支援更豐富的展開欄位(expansions、tweet.fields、media.fields)
  • 必須申請開發者帳號並獲得 Elevated/ Academic Access 才能完整存取

快速遷移參考

// v2 版本獲取用戶推文(需 Bearer Token)
private function fetchTimelineV2(string $userId, int $count): ?array {
    $url = "https://api.twitter.com/2/users/$userId/tweets?max_results=" . min($count, 100) 
         . "&tweet.fields=created_at,public_metrics,entities";
    
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $this->bearerToken],
        CURLOPT_TIMEOUT => 10,
    ]);
    $response = curl_exec($ch);
    curl_close($ch);
    return $response ? json_decode($response, true) : null;
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved