Simple Twitter Feed with Cache Using Laravel and Twitter API
Sep 9, 2013  

Now that we know how to create a helpers class, We're going to put it to work to generate our twitter feed. Here are a few things that you're going to need...

Once you run the command php artisan config:publish thujohn/twitter, you need to modify app/config/packages/thujohn/twitter/config.php with the correct API information.

Once you have the two required items above configured and setup, we're ready to begin. Now, you don't have to put this in a helpers class, but it helps me stay organized. If you would like to modify it's location, do that...

Skip to TL:DR Version

In my app/classes/helpers.php I have something very similar to..

    public static function twitterFeed($screen_name='mackhankins', $count='3', $include_retweets='false', $exclude_replies='true')
    {
        $twitterfeed = Cache::remember('twitterfeed', 30, function() use ($screen_name, $count, $include_retweets, $exclude_replies) {
            return Twitter::getUserTimeline(array('screen_name' => $screen_name, 'count' => $count, 'include_rts' => $include_retweets, 'exclude_replies' => $exclude_replies));
        });
        if(!empty($twitterfeed))
        {
            return $twitterfeed;
        }
        else
        {
            return array();
        }        
    }

I like to call my helper from the _construct method of my HomeController.php because I want the feed to load on every public page in a sidebar I've created. This is a condensed version of what it might look like.

<?php
class HomeController extends BaseController {
    public function __construct()
    {       
        /*Get Tweets*/
        View::share('tweets', Helpers::twitterFeed('mackhankins', '10', false, true));
    }
}

Special Note

Using exclude_replies or include_rts with the count parameter will mean you will receive up-to count tweets — this is because the count parameter retrieves that many tweets before filtering out retweets and replies. These parameters are only supported for JSON and XML responses. (API V1.1 Get Status/User_Timeline)

The View

Now we're just going to loop through $tweets in our blade template.

<div class="twitter">
    @if(!empty($tweets))
        @foreach($tweets as $tweet)
            <div class="twitter-block">
                {{$tweet->user->name}} ({{Twitter::linkify('@'.$tweet->user->screen_name)}})
                <p>{{Twitter::linkify($tweet->text)}}</p>
                <span class="timeago" title="{{$tweet->created_at}}">{{ date('H:i, M d', strtotime($tweet->created_at)) }}</span>        
            </div>
        @endforeach
    @else
        <p>We are having a problem with our Twitter Feed right now.</p>
    @endif
</div>

I used jQuery timeago to convert my timestamps in to ago formats and I used the Twitter L4 package's built in linkify method to convert screen names, hashtags, and urls into links.

Reply, Retweet, and Favorite with Twitter Web Intent

Web Intents are the simplest way to make the Tweets you display on your website interactive.

Web Intents automatically detect whether the end user is currently logged in to twitter.com and asks for login when necessary. If the user does not yet have a Twitter account, they'll have the opportunity to create one before realizing their original intention.

To get started, we need to include the lightweight javascript <script type="text/javascript" src="//platform.twitter.com/widgets.js"></script> through whatever method you prefer. I'm using the Basset package for asset management

Now we need to modify our blade template to look like this.

<div class="twitter">
    @if(!empty($tweets))
        @foreach($tweets as $tweet)
            <div class="twitter-block">
                {{$tweet->user->name}} (>{{Twitter::linkify('@'.$tweet->user->screen_name)}})
                <p>{{Twitter::linkify($tweet->text)}}</p>
                <span class="timeago" title="{{$tweet->created_at}}">{{ date('H:i, M d', strtotime($tweet->created_at)) }}</span>
                <span class="tintent">
                    <a href="https://twitter.com/intent/tweet?in_reply_to={{$tweet->id}}">Reply</a>
                    <a href="https://twitter.com/intent/retweet?tweet_id={{$tweet->id}}">Retweet</a>
                    <a href="https://twitter.com/intent/favorite?tweet_id={{$tweet->id}}">Favorite</a>
                </span>        
            </div>
        @endforeach
    @else
        <p>We are having a problem with our Twitter Feed right now.</p>
    @endif
</div>

I've modified mine to use icons instead of text, but that's up to you.. If you don't have an icon set already in place, Twitter provides us with some familiar images to use.

The last tidbit is just some simple jquery to make the magic happen on mouseover. I've also included timeago in the snippet in hopes of really confusing you.

<script>
jQuery(document).ready(function() {       
    jQuery("span.timeago").timeago();
    jQuery("span.tintent").hide();
    jQuery(".twitter-block").hover(
        function() { $(this).children("span.tintent").fadeIn('fast'); },
        function() { $(this).children("span.tintent").fadeOut('fast'); }
        );
});
</script>

Follow Button

The styling for the follow button is going to be a little different for everyone. The important part is the href="https://twitter.com/intent/user?screen_name=your_screen_name". If the snippet wasn't a clue, you're also going to need Web Intent to pull this off. You can view the final version below.

Final Output TL:DR Version

Helper Method

    public static function twitterFeed($screen_name='mackhankins', $count='3', $include_retweets='false', $exclude_replies='true')
    {
        $twitterfeed = Cache::remember('twitterfeed', 30, function() use ($screen_name, $count, $include_retweets, $exclude_replies) {
            return Twitter::getUserTimeline(array('screen_name' => $screen_name, 'count' => $count, 'include_rts' => $include_retweets, 'exclude_replies' => $exclude_replies));
        });
        if(!empty($twitterfeed))
        {
            return $twitterfeed;
        }
        else
        {
            return array();
        }        
    }

Controller

<?php
class HomeController extends BaseController {
    public function __construct()
    {       
        /*Get Tweets*/
        View::share('tweets', Helpers::twitterFeed('mackhankins', '10', false, true));
    }
}

View

<div class="twitter">
    @if(!empty($tweets))
        @foreach($tweets as $tweet)
            <div class="twitter-block">
                {{$tweet->user->name}} ({{Twitter::linkify('@'.$tweet->user->screen_name)}})
                <p>{{Twitter::linkify($tweet->text)}}</p>
                <span class="timeago" title="{{$tweet->created_at}}">{{ date('H:i, M d', strtotime($tweet->created_at)) }}</span>
                <span class="tintent">
                    <a href="https://twitter.com/intent/tweet?in_reply_to={{$tweet->id}}">Reply</a>
                    <a href="https://twitter.com/intent/retweet?tweet_id={{$tweet->id}}">Retweet</a>
                    <a href="https://twitter.com/intent/favorite?tweet_id={{$tweet->id}}">Favorite</a>
                </span>        
            </div>
        @endforeach
        <a href="https://twitter.com/intent/user?screen_name=your_screen_name"> Follow User</a>
    @else
        <p>We are having a problem with our Twitter Feed right now.</p>
    @endif
</div>

Javascript

<script type="text/javascript" src="jquery.timeago.js"></script>
<script type="text/javascript" src="//platform.twitter.com/widgets.js"></script>
<script>
jQuery(document).ready(function() {       
    jQuery("span.timeago").timeago();
    jQuery("span.tintent").hide();
    jQuery(".twitter-block").hover(
        function() { $(this).children("span.tintent").fadeIn('fast'); },
        function() { $(this).children("span.tintent").fadeOut('fast'); }
        );
});
</script>

Conclusion

So now we have our latest tweets with interactions. If you have any questions or spot any errors, let me know in the comments.