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; !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; !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.
