Getting a Random Tweet using the Twitter Search API and PHP

Kyle Scheer
7 min readDec 28, 2017

WARNING: I don’t know if this still works, as I don’t want to pay for access to the Twitter API, and therefore can’t test it.

Twitter API Changes: The missing FAQ for Free & Basic access — Superface.ai

The Custom Coding Way

Introduction:

In 14 steps, this tutorial will teach you how to retrieve a “random” tweet from the Twitter Search API using your own specified parameters.

Access this code on GitHub

Step 1) Go into your specified directory and create two new files:

  • index.php
  • TwitterAPIExchange.php

Step 2) Open both in a text editor.

Step 3) In TwitterAPIExchange.php, place the following text exactly:

<?php
class TwitterAPIExchange
{
private $oauth_access_token;
private $oauth_access_token_secret;
private $consumer_key;
private $consumer_secret;
private $postfields;
private $getfield;
protected $oauth;
public $url;
public $requestMethod;
protected $httpStatusCode;
public function __construct(array $settings)
{
if (!function_exists('curl_init'))
{
throw new RuntimeException('TwitterAPIExchange requires cURL extension to be loaded, see: http://curl.haxx.se/docs/install.html');
}
if (!isset($settings['oauth_access_token'])
|| !isset($settings['oauth_access_token_secret'])
|| !isset($settings['consumer_key'])
|| !isset($settings['consumer_secret']))
{
throw new InvalidArgumentException('Incomplete settings passed to TwitterAPIExchange');
}
$this->oauth_access_token = $settings['oauth_access_token'];
$this->oauth_access_token_secret = $settings['oauth_access_token_secret'];
$this->consumer_key = $settings['consumer_key'];
$this->consumer_secret = $settings['consumer_secret'];
}
public function setPostfields(array $array)
{
if (!is_null($this->getGetfield()))
{
throw new Exception('You can only choose get OR post fields (post fields include put).');
}
if (isset($array['status']) && substr($array['status'], 0, 1) === '@')
{
$array['status'] = sprintf("\0%s", $array['status']);
}
foreach ($array as $key => &$value)
{
if (is_bool($value))
{
$value = ($value === true) ? 'true' : 'false';
}
}
$this->postfields = $array;
if (isset($this->oauth['oauth_signature']))
{
$this->buildOauth($this->url, $this->requestMethod);
}
return $this;
}
public function setGetfield($string)
{
if (!is_null($this->getPostfields()))
{
throw new Exception('You can only choose get OR post / post fields.');
}
$getfields = preg_replace('/^\?/', '', explode('&', $string));
$params = array();
foreach ($getfields as $field)
{
if ($field !== '')
{
list($key, $value) = explode('=', $field);
$params[$key] = $value;
}
}
$this->getfield = '?' . http_build_query($params, '', '&');
return $this;
}
public function getGetfield()
{
return $this->getfield;
}
public function getPostfields()
{
return $this->postfields;
}
public function buildOauth($url, $requestMethod)
{
if (!in_array(strtolower($requestMethod), array('post', 'get', 'put', 'delete')))
{
throw new Exception('Request method must be either POST, GET or PUT or DELETE');
}
$consumer_key = $this->consumer_key;
$consumer_secret = $this->consumer_secret;
$oauth_access_token = $this->oauth_access_token;
$oauth_access_token_secret = $this->oauth_access_token_secret;
$oauth = array(
'oauth_consumer_key' => $consumer_key,
'oauth_nonce' => time(),
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_token' => $oauth_access_token,
'oauth_timestamp' => time(),
'oauth_version' => '1.0'
);
$getfield = $this->getGetfield();
if (!is_null($getfield))
{
$getfields = str_replace('?', '', explode('&', $getfield));
foreach ($getfields as $g)
{
$split = explode('=', $g);
if (isset($split[1]))
{
$oauth[$split[0]] = urldecode($split[1]);
}
}
}
$postfields = $this->getPostfields();
if (!is_null($postfields)) {
foreach ($postfields as $key => $value) {
$oauth[$key] = $value;
}
}
$base_info = $this->buildBaseString($url, $requestMethod, $oauth);
$composite_key = rawurlencode($consumer_secret) . '&' . rawurlencode($oauth_access_token_secret);
$oauth_signature = base64_encode(hash_hmac('sha1', $base_info, $composite_key, true));
$oauth['oauth_signature'] = $oauth_signature;
$this->url = $url;
$this->requestMethod = $requestMethod;
$this->oauth = $oauth;
return $this;
}
public function performRequest($return = true, $curlOptions = array())
{
if (!is_bool($return))
{
throw new Exception('performRequest parameter must be true or false');
}
$header = array($this->buildAuthorizationHeader($this->oauth), 'Expect:');
$getfield = $this->getGetfield();
$postfields = $this->getPostfields();
if (in_array(strtolower($this->requestMethod), array('put', 'delete')))
{
$curlOptions[CURLOPT_CUSTOMREQUEST] = $this->requestMethod;
}
$options = $curlOptions + array(
CURLOPT_HTTPHEADER => $header,
CURLOPT_HEADER => false,
CURLOPT_URL => $this->url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
);
if (!is_null($postfields))
{
$options[CURLOPT_POSTFIELDS] = http_build_query($postfields, '', '&');
}
else
{
if ($getfield !== '')
{
$options[CURLOPT_URL] .= $getfield;
}
}
$feed = curl_init();
curl_setopt_array($feed, $options);
$json = curl_exec($feed);
$this->httpStatusCode = curl_getinfo($feed, CURLINFO_HTTP_CODE);
if (($error = curl_error($feed)) !== '')
{
curl_close($feed);
throw new \Exception($error);
}
curl_close($feed);
return $json;
}
private function buildBaseString($baseURI, $method, $params)
{
$return = array();
ksort($params);
foreach($params as $key => $value)
{
$return[] = rawurlencode($key) . '=' . rawurlencode($value);
}
return $method . "&" . rawurlencode($baseURI) . '&' . rawurlencode(implode('&', $return));
}
private function buildAuthorizationHeader(array $oauth)
{
$return = 'Authorization: OAuth ';
$values = array();
foreach($oauth as $key => $value)
{
if (in_array($key, array('oauth_consumer_key', 'oauth_nonce', 'oauth_signature',
'oauth_signature_method', 'oauth_timestamp', 'oauth_token', 'oauth_version'))) {
$values[] = "$key=\"" . rawurlencode($value) . "\"";
}
}
$return .= implode(', ', $values);
return $return;
}
public function request($url, $method = 'get', $data = null, $curlOptions = array())
{
if (strtolower($method) === 'get')
{
$this->setGetfield($data);
}
else
{
$this->setPostfields($data);
}
return $this->buildOauth($url, $method)->performRequest(true, $curlOptions);
}
public function getHttpStatusCode()
{
return $this->httpStatusCode;
}
}

Step 4) Save the TwitterAPIExchange.php file and close it.

Step 5) Go to the below website and go through steps 1–4 to retrieve your Twitter API access tokens.

Step 6) In index.php, place the following text:

<?
require_once('TwitterAPIExchange.php');
/** Set access tokens here - see: https://dev.twitter.com/apps/ **/
$settings = array(
'oauth_access_token' => "xxxxxxxxxxxxxxxxxxxxxxxx",
'oauth_access_token_secret' => "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
'consumer_key' => "xxxxxxxxxxxxxxxxxx",
'consumer_secret' => "xxxxxxxxxxxxxxxxxxxxxxxxx"
);
$url = "https://api.twitter.com/1.1/search/tweets.json";
$requestMethod = "GET";
$searchfield = "?f=tweets&vertical=default&q=’random’ AND -filter:retweets &src=typd";
$getfield = $searchfield . "&count=100&result_type=mixed&tweet_mode=extended";
$twitter = new TwitterAPIExchange($settings);
$string = json_decode($twitter->setGetfield($getfield)
->buildOauth($url, $requestMethod)
->performRequest(),true);
if($string["errors"][0]["message"] != "") {echo "<h3>Sorry, there was a problem.</h3><p>Twitter returned the following error message:</p><p><em>".$string[errors][0]["message"]."</em></p>";exit();}
shuffle($string['statuses']);
$i = 1;
foreach($string['statuses'] as $tweets) {
$time = $tweets['created_at'];
$id = $tweets['id'];
$source = $tweets['source'];
$tweet = $tweets['full_text'];
$name = $tweets['user']['name'];
$user = $tweets['user']['screen_name'];
$profile_image = $tweets['user']['profile_image_url'];
$followers = $tweets['user']['followers_count'];
$friends = $tweets['user']['friends_count'];
$listed = $tweets['user']['listed_count'];
echo "Time and Date of Tweet: " . $time ."<br />";
echo "ID of Tweet: " . $id . "<br />";
echo "Source of Tweet: " . $source . "<br />";
echo "Tweet: ". $tweet ."<br />";
echo "Tweeted by: ". $name ."<br />";
echo "Screen name: ". $user ."<br />";
echo "<a href=\"http://twitter.com/$user\">@$user</a><br />";
echo "<img src=\"".$profile_image."\" width=\"100px\" height=\"100px\" /><br />";
echo "Followers: ". $followers ."<br />";
echo "Friends: ". $friends ."<br />";
echo "Listed: ". $listed ."<br /><hr />";
$i++;
if($i == 2) break;
}
echo "<button type='button' class='btn' onClick='window.location.reload()'>Anotha One</button>";
?>

Step 7) Replace the access token placeholder text (all the xxxxxx’s) on lines 5–8 in index.php with the tokens you received from Step 5.

Step 8) Save the index.php file. Go to the index.php file in a web browser to check that the API tokens are working.

If you did receive an output, you are all good to continue to step 9. If you didn’t receive an output, recheck your tokens and consumer keys and make sure there are no spaces inside the quotation marks.

Step 9) Right now, we are running a search which finds tweets with the exact keyword “random” and are excluding retweets. This is shown on line 12 in the $searchfield variable.

NOTE: THE BELOW DOESN’T SEEM TO BE WORKING PROPERLY ANYMORE. YOU’LL NEED TO PLAY AROUND WITH THE QUERY A BIT TO MAKE IT WORK PROPERLY.

To create your own search, go to https://twitter.com/search-home and create your query. Once you’ve run the search, copy the end section of the URL in the browsers search bar. Only copy the section including and after the “?”. Do NOT include the “ https://twitter.com/search” text. Replace the current $searchfield value with this text.

Step 10) Go to the index.php file in a web browser to check that the query is working.

Step 11) If you look at line 13, the $getfield variable, I’ve specified certain parameters that should be looked at. More information here –

https://developer.twitter.com/en/docs/tweets/search/api-reference/get-search-tweets

&count=100

Currently, the Twitter Standard Search API only allows for a maximum of 100 tweets to be pulled for a query. Including this text ensures we get as many tweets as possible, rather than the default 15.

&result_type=mixed

The result_type parameter specifies which results to get. Because we can only get 100 results, we need to specify which results we want. There are 3 types of result_type option available: popular, recent, and mixed. Popular gets the most popular tweets that fit the criteria specified. Recent get the most recent tweets that fit the criteria specified. Mixed gets a mixture of popular and recent tweets that fit the criteria specified. For this example, I’ve chosen to use the mixed option.

tweet_mode=extended”

Now that Twitter allows people to post 280 characters instead of 140 characters, this parameter specifies that we want to see the entire tweet rather than a parsed 140 character version. Keeping this parameter is highly recommended.

Step 12) Making the results randomized and returning 1 result required 4 lines of code.

Line 19: shuffle($string[‘statuses’]); randomized the 100 results.

Line 20: $i=1 specifies a variable to count with.

Line 44: $i++ increments $i by 1.

Line 45: if($i == 2) break; specifies how many times we want the foreach loop to occur before it ends. If you want 1 result, it should be 2. If you want 5 results, it should be 4.

Step 13) Lines 21–43 specify which variables we want to echo and how we want to see them.

https://developer.twitter.com/en/docs/tweets/data-dictionary/overview/user-object has a full list of variables available to view.

Here is where you can remove variables, add new variables, and customize the HTML and CSS to make the variables look better on the page.

Step 14) You can change the button text at the very bottom. The button functions to reload the page and restarts the query, so you get a new set of tweets and in a different order.

Conclusion: You have now created a webpage to get a random tweet. Congratulations! Let me know if you have any questions.

Contributions

The entire TwitterAPIExchange.php code is thanks to J7mbo — https://github.com/J7mbo/twitter-api-php

--

--

Kyle Scheer

I like writing about things that interest me. I’m hoping some of it may be interesting to you as well. Keep up with me and my projects at www.kylescheer.com