Blog «EM1£1Ø»2HÐ

Porque compartilhar conhecimento é evoluir!

Olá caros leitores.

Alguns dias atrás estava procurando como fazer uma integração do zend framework com twitter. Estava com uma certa dúvidas, pois muitos sites que vi faziam requisições REST e passavam uma url de callback.

No meu caso não precisava fazer isso, era só autenticar e poder obter a timeline, enviar um novo tweet.

Pesquisando por algum tempo, achei partes da solução que desejava. Neste post vou mostrar como fazer um cliente para twitter usando o Zend Framework. Este cliente vai poder obtera timeline do usuário, enviar tweets e fazer busca por algum termo. Não fiz páginação apesar da api do Zend permitir isso. Para mais detalhes veja a API de Twitter que a Zend disponibiliza.

Para você poder fazer tal cliente, primeiramente você precisa ir no twitter, na área de desenvolvedores(Developers) e cadastrar sua aplicação e configurar permissão de leitura e escrita. Após isso o twitter irá gerar algumas informações. Para este post vamos precisar do consumerKey, consumerSecret, accessToken, accessTokenSecret.

De posse desses dados, vamos configurar o application.ini(estou baseando o cliente no ZendFrameworkQuickstart) e adicionar os dados como mostrar o código abaixo:

application/configs/application.ini

[production]
;código existente no Quickstart

oauth.twitter.accessToken = "Seu Access Token"
oauth.twitter.accessTokenSecret = "Sua Access Token Secret"
oauth.twitter.consumerKey = "Sua Consumer Key"
oauth.twitter.consumerSecret = "Sua Consumer Secret"

Na pasta library crie uma pasta chamada ZendX. Dentro dessa pasta vamos criar algumas classes customizadas. De inicio crie a classe ZendX_DadosDaAplicacao. Lembrando o autoload do ZF, ZendX_DadosDaAplicacao significa que existe um arquivo library/ZendX/DadosDaAplicacao.php.

ZendX/DadosDaAplicacao.php

<?php
class ZendX_DadosDaAplicacao
{
    const CHAVE_DE_CONFIGURACAO = 'config';
}

Agora vamos alterar algumas coisas no Bootstrap.php e adicionar o código abaixo.

application/Bootstrap.php

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    // Restante do código existente
    protected function _initConfig()
    {
        $config = new Zend_Config($this->getOptions());

        Zend_Registry::set(ZendX_DadosDaAplicacao::CHAVE_DE_CONFIGURACAO, $config);

        return $config;
    }
}

No código acima, estou registrando os dados do application.ini, para serem usados posteriormente para configurar o OAuth e assim poder conectar no twitter.

Agora vamos criar uma classe a qual vou chamar de credencial, e que será usada para autenticar no twitter.

ZendX/Twitter/Credencial.php

<?php
class ZendX_Twitter_Credencial
{
    private $_accessToken;
    private $_accessTokenSecret;
    private $_consumerKey;
    private $_consumerSecret;

    public function __construct($accessToken, $accessTokenSecret, $consumerKey, $consumerSecret)
    {
        $this->_accessToken         = $accessToken;
        $this->_accessTokenSecret   = $accessTokenSecret;
        $this->_consumerKey         = $consumerKey;
        $this->_consumerSecret      = $consumerSecret;
    }

    public function setAccessToken($accessToken)
    {
        $this->_accessToken = $accessToken;
    }

    public function getAccessToken()
    {
        return $this->_accessToken;
    }

    public function setAccessTokenSecret($accessTokenSecret)
    {
        $this->_accessTokenSecret = $accessTokenSecret;
    }

    public function getAccessTokenSecret()
    {
        return $this->_accessTokenSecret;
    }

    public function setConsumerKey($consumerKey)
    {
        $this->_consumerKey = $consumerKey;
    }

    public function getConsumerKey()
    {
        return $this->_consumerKey;
    }

    public function setConsumerSecret($consumerSecret)
    {
        $this->_consumerSecret = $consumerSecret;
    }

    public function getConsumerSecret()
    {
        return $this->_consumerSecret;
    }

    public function getTokenDeAcesso()
    {
        $token = new Zend_Oauth_Token_Access();

        $token->setToken($this->_accessToken)
              ->setTokenSecret($this->_accessTokenSecret);

        return $token;
    }
}

Ao criar uma credencial é preciso passar os dados que o twitter gerou, que são consumerKey, consumerSecret, accessToken e accessTokenSecret. Para fazer esse processo de instanciar a credencial, vou criar uma fábrica, onde ela vai obter os dados necessários, instanciar a classe credencial e passar os dados que ela precisa.

ZendX/Twitter/FabricaDeCredencial.php

<?php
require_once 'Credencial.php';
require_once 'Exception.php';

class ZendX_Twitter_FabricaDeCredencial
{
    public static function fabrique()
    {
        $config = self::_getConfiguracoes();
        if($config == null)
            new ZendX_Twitter_Exception("Configuração está nula.");

        $oauth = $config->get('oauth');
        if($oauth == null)
            new ZendX_Twitter_Exception("Elemento oauth não foi encontrado nas configurações.");

        $twitter = $oauth->twitter;

        return new ZendX_Twitter_Credencial($twitter->accessToken, $twitter->accessTokenSecret
                                            , $twitter->consumerKey, $twitter->consumerSecret);
    }

    private static function _getConfiguracoes()
    {
        if(!Zend_Registry::isRegistered(ZendX_DadosDaAplicacao::CHAVE_DE_CONFIGURACAO)) return null;

        return Zend_Registry::get(ZendX_DadosDaAplicacao::CHAVE_DE_CONFIGURACAO);
    }
}

Agora que temos a credencial, vamos criar uma classe que fara as requisições ao twitter usando a api do zend.

ZendX/Twitter/Servico.php

<?php
class ZendX_Twitter_Servico
{
    private $_configuracoes;
    private $_twitter;

    public function __construct(ZendX_Twitter_Credencial $credencial)
    {
        $this->_configuracoes = array('accessToken' => $credencial->getTokenDeAcesso()
                                        ,'consumerKey' => $credencial->getConsumerKey()
                                        ,'consumerSecret' => $credencial->getConsumerSecret());
    }

    public function getMinhaTimeLine()
    {
        $listaDeTweets = array();

        $timeLine = $this->_getServico()->status->userTimeline();

        if(!isset($timeLine->status)) return $listaDeTweets;

        foreach($timeLine->status as $elemento){
            $tweet = new stdClass();
            $listaDeTweets[] = $tweet;

            $tweet->texto = (string)$elemento->text;
            $tweet->usuario = (string)$elemento->user->name;
            $tweet->criadoEm =  (string)$elemento->created_at;
        }

        return $listaDeTweets;
    }

    public function enviarTweet($tweet)
    {
        if(empty($tweet)) return null;

        return $this->_getServico()->status->update($tweet);
    }

    public function busquePor($termo)
    {
        $twitterSearch  = new Zend_Service_Twitter_Search('json');

        $listaDeItens = array();

        $resultado = $twitterSearch->search($termo);

        if(!isset($resultado['results'])) return $listaDeItens;

        foreach($resultado['results'] as $item){
            $tweet = new stdClass();
            $listaDeItens[] = $tweet;

            $tweet->texto   = $item['text'];
            $tweet->usuario = $item['from_user'];
        }

        return $listaDeItens;
    }

    private function _getServico()
    {
        if($this->_twitter != null) return $this->_twitter;

        $this->_twitter =  new Zend_Service_Twitter($this->_configuracoes);

        return $this->_twitter;
    }
}

Ela também precisa receber parametro em seu contrutor, então também vou criar uma fábrica para esse objeto.

ZendX/Twitter/FabricaDeServico.php

<?php
class ZendX_Twitter_FabricaDeServico
{
    public static function fabrique()
    {
        $credencial = ZendX_Twitter_FabricaDeCredencial::fabrique();

        return new ZendX_Twitter_Servico($credencial);
    }
}

Agora para usar o serviço vou criar um model.

application/Model/Twitter.php

<?php
class Application_Model_Twitter
{
    private $_servico;

    public function __construct()
    {
        $this->_servico = ZendX_Twitter_FabricaDeServico::fabrique();
    }

    public function envieTweet($texto)
    {
        $this->_servico->enviarTweet($texto);
    }

    public function getMinhaTimeLine()
    {
        return $this->_servico->getMinhaTimeLine();
    }

    public function pesquisePor($termo)
    {
        return $this->_servico->busquePor($termo);
    }
}

Com o modelo pronto agora podemos criar o controller.

application/controllers/IndexController.php

<?php
class IndexController extends Zend_Controller_Action
{
    private $_modelo;

    public function init()
    {
        $this->_modelo = new Application_Model_Twitter();
    }

    public function indexAction()
    {
        $tweets = array();

        try{
            $tweets = $this->_modelo->getMinhaTimeLine();
        }catch(Exception $ex){
        }

        $this->view->assign('tweets', $tweets);
    }

    public function enviarTweetAction()
    {
        if (!$this->_request->isPost()) {
            $this->_helper->redirector('index');
            return;
        }

        $dadosDoForm = $this->_request->getPost();

        try{
            if(isset($dadosDoForm['texto']) &amp;amp;amp;amp;&amp;amp;amp;amp; !empty($dadosDoForm['texto']))
                $this->_modelo->envieTweet($dadosDoForm['texto']);

        }catch(Exception $ex){
        }

        $this->_helper->redirector('index');
    }

    public function pesquisarAction()
    {
        if (!$this->_request->isPost()) {
            $this->_helper->redirector('index');
            return;
        }

        $dadosDoForm = $this->_request->getPost();
        $resultado = array();

        try{
            if(isset($dadosDoForm['termo']) &amp;amp;amp;amp;&amp;amp;amp;amp; !empty($dadosDoForm['termo']))
                $resultado = $this->_modelo->pesquisePor($dadosDoForm['termo']);
        }catch(Exception $ex){
        }

        $this->view->assign('termo', $dadosDoForm['termo']);
        $this->view->assign('resultado', $resultado);
    }
}

Dei uma alterada no arquivo de layout do exemplo do zend framework.

application/layouts/scripts/layout.phtml

<?php echo $this->doctype() ?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Integrando Zend Framework com Twitter</title>
    <?php echo $this->headLink()->appendStylesheet('/public/css/global.css') ?>
</head>
<body>
<div id="corpo">
    <div id="topo">
        <div class="titulo">
            Integrando Zend Framework com Twitter
            -
            <a href="<?php echo $this->url(array('controller'=>'index'), null, true); ?>">
                Ir para Timeline
            </a>
        </div>
        <div class="formPesquisa">
            <form id="formAdd" action="<?php echo $this->url(array('controller'=>'index', 'action'=>'pesquisar'), null, true); ?>" method="post">
                <input type="text" name="termo" />
                <input type="submit" value="buscar" />
            </form>
        </div>
        <div class="clr"></div>
    </div>
    <div id="conteudo">
        <?php echo $this->layout()->content ?>
    </div>
</div>
</body>
</html>

Abaixo o css que usei no layout.

public/css/global.css


body{
background: #c0deed;
}

#corpo{
width: 700px;
margin: 0 auto;
background: #fff;
}

#topo{
background: #000;
color: #fff;
margin-bottom: 10px;
padding: 5px;
line-height: 25px;
}

#topo .titulo{ float: left; }

#topo .titulo a{
color: #fff;
text-decoration: none;
font-weight: bold;
}

#topo .titulo a:hover{ text-decoration: underline; }

#topo .formPesquisa{ float: right; }

#conteudo{ padding: 10px;}

.clr{ clear:both; }

#tweetForm{ margin-bottom: 5px; }

#tweetForm textarea{
width: 100%;
margin: 0px;
padding: 0px;
}

#tweetForm .submitTweet{ text-align: right; }

#timeline .titulo{
background: #dfdfdf;
color: #000;
text-align: center;
height: 30px;
line-height: 30px;
margin-bottom: 5px;
}

#timeline .tweet, #resultado .tweet{
padding: 5px;
background: #e5f2f7;
margin: 4px 0px;
}

#timeline .tweet .data{
font-size: 11px;
text-align: right;
}

#timeline .tweet .texto{

}

#resultado .pesquisa{
margin-bottom: 15px;
font-weight: bold;
}

#resultado .pesquisa .termo{
color: #109bd0;
font-weight: normal;
}

#resultado .tweet .usuario{ font-weight: bold; }

#resultado .tweet .usuario a{ text-decoration: none; }

Agora vou colocar as views que fiz para o controller.

application/views/scripts/index/index.phtml

<div id="tweetForm">
    <form id="formAdd" action="<?php echo $this->url(array('controller'=>'index', 'action'=>'enviar-tweet'), null, true); ?>" method="post">
        <div><textarea rows="3" name="texto"></textarea></div>
        <div class="submitTweet"><input type="submit" value="Enviar" /></div>
    </form>
</div>
<div id="timeline">
    <div class="titulo">Timeline</div>
    <?php foreach($this->tweets as $tweet): ?>
        <div class="tweet">
            <div class="usuario" style="float:left;"><?php echo $tweet->usuario; ?></div>
            <div class="data" style="float:right; line-height:20px;"><?php echo $tweet->criadoEm; ?></div>
            <div class="clr"></div>
            <div class="texto"><?php echo $tweet->texto; ?></div>
        </div>
    <?php endforeach; ?>
</div>

application/views/scripts/index/pesquisar.phtml

<div id="resultado">
    <div class="pesquisa">Pesquisando por: <span class="termo"><?php echo $this->termo; ?></span></div>
    <?php foreach($this->resultado as $item): ?>
        <div class="tweet">
            <span class="usuario">
                <a href="http://twitter.com/<?php echo $item->usuario; ?>" target="_blank">
                    @<?php echo $item->usuario; ?>
                </a>
            </span>
            -
            <span class="texto"><?php echo $item->texto; ?></span>
        </div>
    <?php endforeach; ?>
</div>

Bom, é isso. Espero que esse tutorial sirva de ajuda para outra pessoas.

Download

Cliente Twitter ZF 1.11.3.zip

Categorias: Tutoriais Tags: , ,

Leave a Reply