Building your first Twitter mash-up

By Alex Ciobanu (iscandr)
Simple tutorial to help you build your first twitter app

Before you start


1. have a webserver running;
2. have a SQL server running;
(for these you can use something like XAMPP)
3. have basic CakePHP knowledge. The CakePHP book covers this.

What will the application do


It will be searching for a given keyword and store found tweets in our database.

Getting started


1. Get the latest CakePHP and drop it in your DocumentRoot. You'll have something like this:

Download code
/caketweet
    /app
    /cake
    /docs
    /vendors
    .htaccess
    index.php

2. Don't forget to customise your app/config/core.php and set write permissions to your app/tmp folder (chmod -R 777 app/tmp)

3. Get Twitter datasource and put it in your app/models/datasources directory
http://bakery.cakephp.org/articles/view/twitter-datasource

Setup


1. Create a database:

Download code CREATE DATABASE `caketweet`;
USE `caketweet`;
CREATE TABLE IF NOT EXISTS `tweets` (
  `id` int(11) NOT NULL auto_increment,
  `twitter_username` varchar(255) NOT NULL,
  `tweet_content` text NOT NULL,
  `created` datetime default NULL,
  `updated` datetime default NULL,
  PRIMARY KEY  (`id`)
);

2. Edit your app/config/database.php
Example:
Download code
<?php
class DATABASE_CONFIG {

    var 
$default = array(
        
'driver' => 'mysql',
        
'persistent' => false,
        
'host' => 'localhost',
        
'login' => 'user',
        
'password' => 'password',
        
'database' => 'caketweet',
        
'prefix' => '',
    );

    var 
$twitter = array(
        
'datasource' => 'twitter',
        
'username' => 'your_twitter_username',
        
'password' => 'your_twitter_password',
    ); 
}
?>

MVC


1. Create a tweet model.
app/models/tweet.php:
Download code
<?php
class Tweet extends AppModel {
    var 
$name 'Tweet';
}
2. Create the tweets controller.
app/controllers/tweets_controller.php
Download code
<?php
class TweetsController extends AppController {
    
    var 
$name 'Tweets';
    
    function 
index(){
        
$this->set('tweets'$this->paginate());
    }
    function 
search(){
        if(!empty(
$this->data['Tweet']['keyword'])){
            
$this->Twitter ConnectionManager::getDataSource('twitter');
            
$search_results $this->Twitter->search($this->data['Tweet']['keyword'], 'all'5);
            
// let's loop through tweets
            
foreach($search_results['Feed']['Entry'] as $rawtweet){
                
// format to our needs
                
$i explode(' '$rawtweet['Author']['name']);
                
$tweet['Tweet']['twitter_username'] = $i[0];
                
$tweet['Tweet']['tweet_content'] = $rawtweet['content']['value'];
                
$tweet['Tweet']['created'] = date('Y-m-d H:i:s' strtotime($rawtweet['published']));
                
$tweet['Tweet']['updated'] = date('Y-m-d H:i:s' ,strtotime($rawtweet['updated']));
                
// and save
                                
$this->Tweet->create();            
                
$this->Tweet->save($tweet);
            }
            
$this->Session->setFlash(__('Got tweets.'true));
        }    
    }
}
?>

3. Create the views.
app/views/tweets/index.ctp:
Download code
<div class="tweets index">
<h2><?php __('Tweets');?></h2>
<table cellpadding="0" cellspacing="0">
<tr>
    <th><?php echo $paginator->sort('id');?></th>
    <th><?php echo $paginator->sort('twitter_username');?></th>
    <th><?php echo $paginator->sort('tweet_content');?></th>
    <th><?php echo $paginator->sort('created');?></th>
    <th class="actions"><?php __('Actions');?></th>
</tr>
<?php
$i 
0;
foreach (
$tweets as $tweet):
    
$class null;
    if (
$i++ % == 0) {
        
$class ' class="altrow"';
    }
?>
    <tr<?php echo $class;?>>
        <td>
            <?php echo $tweet['Tweet']['id']; ?>
        </td>
        <td>
            <?php echo $tweet['Tweet']['twitter_username']; ?>
        </td>
        <td>
            <?php echo $tweet['Tweet']['tweet_content']; ?>
        </td>
        <td>
            <?php echo $tweet['Tweet']['created']; ?>
        </td>
        <td class="actions">
           <?php echo $html->link(__('Delete'true), array('action'=>'delete'$tweet['Tweet']['id']), nullsprintf(__('Are you sure you want to delete # %s?'true), $tweet['Tweet']['id'])); ?>
        </td>
    </tr>
<?php endforeach; ?>
</table>
</div>
<div class="paging">
    <?php echo $paginator->prev('&#0171;' .__('prev'true), array('escape' => false), null, array('class'=>'disabled''escape' => false));?>
 |  <?php echo $paginator->numbers();?>
    <?php echo $paginator->next(__('next'true).' &#0187;', array('escape' => false), null, array('class'=>'disabled''escape' => false));?>
</div>
<div class="actions">
    <ul>
        <li><?php echo $html->link(__('Search tweets'true), array('action'=>'search')); ?></li>
    </ul>
</div>
app/views/tweets/search.ctp:
Download code
<div class="tweets form">
<?php echo $form->create('Tweet', array('action' => 'search'));?>
    <fieldset>
         <legend><?php __('Search tweet');?></legend>
    <?php
        
echo $form->input('keyword');
    
?>
    </fieldset>
<?php echo $form->end('Search');?>
</div>
<div class="actions">
    <ul>
        <li><?php echo $html->link(__('List tweets'true), array('action'=>'index'));?></li>
    </ul>
</div>

Now browse to http://yourhost/caketweet/tweets/search and input your desired keyword.

Final notes

As you probably noticed this is not even near of being a full application but it will get you started.
To see what else you can do browse the twitter datasource to view the available methods.

 

Comments 962

CakePHP Team Comments Author Comments
 

Comment

1 I'm sick of this.

All I hear when I ask people if they've heard of CakePHP is that the documentation sucks. This post here is a prime example. Twitter is an amazingly easy service for beginners to play with, and yet you still manage to horribly screw up your code examples. This frustrates people and makes you look really stupid.
Posted Mar 18, 2009 by J Adam Moore
 

Comment

2 I'm sick of this.

Adam please fell free to write a better one or modify this one (it sucks though, so you're better off writing from scratch) and I'll delete mine.
If you have some pointers in making it better I'll be more than happy to learn.
Posted Mar 19, 2009 by Alex Ciobanu
 

Question

3 echo echo echo

why wouldn't you use < ? = instead of < ? php echo .....?

thx,
iM
Posted Apr 5, 2009 by Imre Mehesz
 

Comment

4 echo echo echo

Most of the code is baked. On the other hand I tend to use "< ? php echo" because I find it more readable.
Posted Apr 8, 2009 by Alex Ciobanu
 

Comment

5 Error: Create TweetsController::add()

Everything setup fine, but when I hit the Search button, i get this error, and I cannot understand where is the 'add' function coming from. Please help.

Missing Method in TweetsController
Error: The action add is not defined in controller TweetsController

Error: Create TweetsController::add() in file: app/controllers/tweets_controller.php.

class TweetsController extends AppController {

var $name = 'Tweets';


function add() {

}

}
?>
Posted Apr 15, 2009 by Chee-Siong Yee
 

Comment

6 Error: Create TweetsController::add()

Everything setup fine, but when I hit the Search button, i get this error, and I cannot understand where is the 'add' function coming from. Please help.

Missing Method in TweetsController
Error: The action add is not defined in controller TweetsController

Error: Create TweetsController::add() in file: app/controllers/tweets_controller.php.

class TweetsController extends AppController {

var $name = 'Tweets';


function add() {

}

}
?>

I just solved the problem. The following line in the search.ctp

create('Tweet');?>

should be

create('Tweet',array('action' => 'search'));?>
Posted Apr 15, 2009 by Chee-Siong Yee
 

Comment

7 I am sick of such comments

All I hear when I ask people if they've heard of CakePHP is that the documentation sucks. This post here is a prime example. Twitter is an amazingly easy service for beginners to play with, and yet you still manage to horribly screw up your code examples. This frustrates people and makes you look really stupid.
Why did you even write this comment in the first place? If you have problems with the code, provide the snippet author some comments and helpful feedback. You have gone out of your way to write a comment that lacks any constructive criticism.

And you can tell the people that the documentation has gotten a lot better over the past months.
Posted Apr 23, 2009 by Tim Koschuetzki
 

Comment

8 error in TweetsController search method

There's a bug in TweetsController search method, you should call
$this->Tweet->create();

just before saving the tweet to database with
$this->Tweet->save($tweet);

Otherwise it just overwrites same row in the database, ending with only one tweet as a result of the search.

Thanks for creating the tutorial, helped me anyway :)
Posted Apr 24, 2009 by Maros Miskerik
 

Comment

9 error in TweetsController search method

There's a bug in TweetsController search method, you should call
$this->Tweet->create();

just before saving the tweet to database with
$this->Tweet->save($tweet);

Otherwise it just overwrites same row in the database, ending with only one tweet as a result of the search.

Thanks for creating the tutorial, helped me anyway :)

Hi Maros,

Thanks. I thought saving one record was the original design :).
Posted Apr 24, 2009 by Chee-Siong Yee
 

Comment

10 error in TweetsController search method

Hi Maros,

Thanks. I thought saving one record was the original design :).

No, it wasn't :) You could see it in debug information on the bottom, one insert and then 4 updates on the same row in tweets table.
Posted Apr 24, 2009 by Maros Miskerik
 

Comment

11 error in TweetsController

Edited. Thanks guys.
Posted Apr 24, 2009 by Alex Ciobanu
 

Comment

12 that's why

Some web servers do not permit the use of the shorthand code. it's always best if you want portability to use
why wouldn't you use < ? = instead of < ? php echo .....?

thx,
iM
Posted May 28, 2009 by Tim
 

Question

13 Html tags?

Hi,

Thanks for this tutorial. I was able to run it. But I notice that the html tags (&gt; and &lt;) are removed from links in the tweets.

I tried to echo each step of searching tweets and I think that the XML class that parses the http get is removing the tags...

if I'm right, then why??

I know the possibility of xss things. But I want to have the option to store the data with html tags in database. How to do that?

Or is there a way in cakephp to display
a href='http://...' /a
as html links?

Thanks again.
Posted Jun 13, 2009 by Saleh
 

Comment

14 I am am sick of you (and people like you)

All I hear when I ask people if they've heard of CakePHP is that the documentation sucks. This post here is a prime example. Twitter is an amazingly easy service for beginners to play with, and yet you still manage to horribly screw up your code examples. This frustrates people and makes you look really stupid. I am am sick of you (and people like you) - luckily, the CakePhp community seems to be full of people not like you. I bet you never, ever even considered giving something back to others..

This is a good, quick and dirty, introductory CakePhp article. What more do we want? :)
Posted Oct 3, 2009 by Jacob Moen
 

Comment

15 The Documentation is still horrible

I never said that CakePHP sucks, or that the authors are idiots. They are brilliant and I *like* CakePHP. What I don't like is how bad the supporting documentation is. Tutorials like this give people the wrong idea about what is possible using CakePHP and services like Twitter or Facebook or Flickr.
Maybe you're all wildly successful with your Twitter mash-ups. But I think the replies directed toward me are full of it. The problem I have with this is three-fold:

1) If you are using CakePHP to handle any amount of Twitter data, it had better be a very small amount because it will choke and die quickly. It is not designed to scale well by following tutorials like this.

2) If you need help accessing Twitter data, or "getting CakePHP to work" then you probably don't understand rate-limiting or asynchronous blocking request and will be blacklisted by the Twitter servers for what will seem like every other hour, or just long enough to make your noob brain crash and burn.

3) Twitter is a new and changing service. API changes and new features like lists and retweets mean that tutorials like this one should be depreciated, but they are not because THE DOCUMENTATION IS STILL HORRIBLE.

If you would like to refute my claim that this particular tutorial is a complete waste of time, then please list the website you created along with usage statistics showing a non-trivial amount of real-time traffic. Yeah, that's what I thought. Reactionary fan-boys rushing to defend CakePHP. If you love it so much, fix the documentation. I'm doing my part to educate people by utilizing the comment section the way it was intended.

P.S. Alex Ciobanu, my only suggestion would be to write a disclaimer that your code can not be modified into any sort of robust, publicly accessible website and is only to demonstrate the concepts involved.
Posted Nov 15, 2009 by J Adam Moore