Tweeting from PHP

Fabien Potencier

June 14, 2009

Twitter is everywhere nowadays. Odds are eventually you will want to tweet from PHP. No need to use one of the numerous PHP Twitter libraries, as tweeting is as simple as using the PHP built-in file_get_contents() function:

function tweet($message, $username, $password)
{
  $context = stream_context_create(array(
    'http' => array(
      'method'  => 'POST',
      'header'  => sprintf("Authorization: Basic %s\r\n", base64_encode($username.':'.$password)).
                   "Content-type: application/x-www-form-urlencoded\r\n",
      'content' => http_build_query(array('status' => $message)),
      'timeout' => 5,
    ),
  ));
  $ret = file_get_contents('http://twitter.com/statuses/update.xml', false, $context);
 
  return false !== $ret;
}
 

Pretty easy, no? Using the tweet() function is of course a piece of cake:

tweet('From PHP, yeah...', 'fabpot', 'Pa$$');
 

As an added bonus, the function returns true if everything went fine, or false otherwise.

As we talk about Twitter, you can follow me.

Discussion

gravatar Hugo Hamon  — June 14, 2009 23:10   #1
Nice piece of code ! I'm currently writing a new plugin that allows to use the Twitter API within CURL requests. Your example gives me some new ideas of implementation :)
gravatar Allain Lalonde  — June 15, 2009 01:07   #2
Nice! This code is a perfect example of PHP done right. Thanks
gravatar EllisGL  — June 15, 2009 06:10   #3
@Hugo - Shouldn't be hard to convert over. Also I would use the JSON method myself.
gravatar Vojto  — June 15, 2009 06:40   #4
Nice, I didn't even know that there is something like stream_context_create :)
gravatar Peter Mescalchin  — June 15, 2009 12:08   #5
I stumbled on stream_context_create() for exactly the same reasons the other week - to fetch a twitter timeline (which of course also needs HTTP auth) - and Curl seemed like overkill for such things.

Changing the above code to a GET request, and removing the "Content-type/content" sections and calling the URL http://twitter.com/statuses/user_timeline.json will get you back your JSON timeline...
gravatar EllisGL  — June 15, 2009 14:12   #6
The reason to use CURL is because a lot of host have remote file inclusion turned off, which would prevent this from working.
gravatar EllisGL  — June 15, 2009 14:34   #7
Here's my CURL version:
function postTweet($message, $username, $password)
{
$url = 'http://twitter.com/statuses/update.json';
$fld = http_build_query(array('status' => $message));
$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERPWD, $username.':'.$password);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fld);

$ret = curl_exec($ch);

return false !== $ret;
}
gravatar Rob Douglas  — June 15, 2009 19:45   #8
any way to add client code in there too? like from 'client url'
gravatar Stray Cat passing by  — June 15, 2009 22:52   #9
Rob D. - you can pass any string you want to Fabian's tweet function. (Is that really your question?)

<?php

$MsgToTweet = "Dude, welcome to programming. :) " .
"$_SERVER['SERVER_NAME']" .
"$_SERVER['PHP_SELF']" ;

$TwitterUserName = "Rob";
$TwitterPassword = "Rob'sPassword";

tweet ($MsgToTweet,
$TwitterUserName,
$TwitterPassword);

// Cut and paste Fabien's code defining the tweet function here.
?>

p.s.
This page of predefined server variables in PHP might be helpful to you (depending on what you're trying to do).
http://us2.php.net/manual/en/reserved.variables.server.php


gravatar JonTheNiceGuy  — June 17, 2009 17:28   #10
Just a quick reminder - Laconica, the PHP based, federated Free & Open Source software behind identi.ca (which is very similar to Twitter) has a completely compatible API with Twitter.

Identi.ca is being used in a lot of places, as it contains many features which exceed that which you currently get from Twitter! Including; XMPP, Groups, Messaging to tagged followers and, best yet, it's being developed in the open.

If you're interested, check out http://laconi.ca for the source code, and http://identi.ca to see how it works!
gravatar Martius  — June 17, 2009 22:01   #11
I saw a little trick in the symfony code and I see it here once more, I don't understand why you use
return false !== $ret;
and not
return (bool) $ret;
gravatar Fabien  — June 19, 2009 07:35   #12
@Martius:

Both constructs are different: false !== $ret returns true only if $ret is exactly equal to false. Your construct also returns false if $ret is the empty string for instance, which can be a valid return value.