Building your first Twitter mash-up
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++ % 2 == 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']), null, sprintf(__('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('«' .__('prev', true), array('escape' => false), null, array('class'=>'disabled', 'escape' => false));?>
| <?php echo $paginator->numbers();?>
<?php echo $paginator->next(__('next', true).' »', 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
Comment
1 I'm sick of this.
Comment
2 I'm sick of this.
If you have some pointers in making it better I'll be more than happy to learn.
Question
3 echo echo echo
thx,
iM
Comment
4 echo echo echo
Comment
5 Error: Create TweetsController::add()
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() {
}
}
?>
Comment
6 Error: Create TweetsController::add()
I just solved the problem. The following line in the search.ctp
create('Tweet');?>
should be
create('Tweet',array('action' => 'search'));?>
Comment
7 I am sick of such comments
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.
Comment
8 error in TweetsController search method
$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 :)
Comment
9 error in TweetsController search method
Hi Maros,
Thanks. I thought saving one record was the original design :).
Comment
10 error in TweetsController search method
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.
Comment
11 error in TweetsController
Comment
12 that's why
Question
13 Html tags?
Thanks for this tutorial. I was able to run it. But I notice that the html tags (> and <) 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.
Comment
14 I am am sick of you (and people like you)
This is a good, quick and dirty, introductory CakePhp article. What more do we want? :)
Comment
15 The Documentation is still horrible
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.