tag:blogger.com,1999:blog-9422312567266690062024-03-14T01:25:54.099-03:00Cesar ScurUma breve história sobre PHP, Web, Mobile e quase tudo.Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.comBlogger27125tag:blogger.com,1999:blog-942231256726669006.post-26597872801226710032011-06-02T23:21:00.001-03:002015-09-21T12:52:38.336-03:00Cs_Table Parte 1 - Doctrine Query + Zend Paginator<div class="separator" style="clear: both; text-align: center;">
<a class="lightbox" href="http://www.webtuts.com.br/wp-content/uploads/2010/09/pagination.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br /></a></div>
Apesar de muito simples, este pequeno código é bem poderoso. Ele abre as portas para as próximas partes neste projeto. De uma olhada no no exemplo de implementação a baixo e se achar útil é só baixar pelo github e sair usando.<br />
<br />
<a name='more'></a><br /><br />
Este é um exemplo de como utilizar este Adapter.<br />
<br />
<div class="syntaxhighlightercontainer">
<pre class="brush: php"><?php
$schedulesQuery = Doctrine_Query::create()
->select()
->from('Schedule');
$adapter = new Cs_Paginator_Adapter_DoctrineQuery($schedulesQuery);
$paginator = new Zend_Paginator($adapter);
$this->view->schedules = $paginator;</pre>
</div>
<br />
O resto segue exatamente o funcionamento do <a href="http://framework.zend.com/manual/en/zend.paginator.introduction.html">Zend_Paginator</a>. Internamente o Adapter utiliza <a href="http://www.doctrine-project.org/documentation/manual/1_2/en/utilities">Doctrine Pager</a> o que faz com que o funcionamento do Zend_Paginator seja ótimo, buscando no banco apenas a pagina corrente.<br />
<br />
Esse é o primeiro componente que fará parte de algo maior, apesar de ser completamente funcional sozinho. As outras partes do Cs_Table eu vou postando com o tempo.<br />
<br />
Onde baixar?<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://github.com/CesarScur/TableDisplay" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-0zhZe50-Hrw/TehEc3wj7EI/AAAAAAAABj4/H0PIKon0cjk/s1600/github_icon.png" /></a></div>
Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com0tag:blogger.com,1999:blog-942231256726669006.post-18215574112463377752011-05-16T12:51:00.003-03:002011-05-16T12:55:20.573-03:00FlashMessenger<div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-Y3uj_3HMQp8/TdFE-85iBgI/AAAAAAAABik/JsmghZOLmpY/s1600/flashMessenger.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-Y3uj_3HMQp8/TdFE-85iBgI/AAAAAAAABik/JsmghZOLmpY/s1600/flashMessenger.jpg" /></a></div>Eu já andei utilizando esse fonte do <a href="http://noumenal.co.uk/resources/downloads/">Noumenal</a> em um ou dois projetos, mas cada vez que eu uso ele eu tenho que ajustar para o projeto. Então eu tive a idéia de implementar algo que fosse configuravel e reaproveitavel e o que surgiu é esse projeto a parte.<br />
<br />
<a name='more'></a><br />
<br />
O Cs_FlashMessenger é o primeiro de uma serie de componentes que eu pretendo ir implementando ao longo de outros projetos para resolver problemas comuns. O primeiro objetivo desse componente é simplificar o uso do helper de controller do ZF na view. Mas isso o fonte do Noumenal fazia bem, portanto os aspectos: fácil de usar e configurar foram os que eu tentei resolver.<br />
<br />
Pra completar acressentei um css e um conjunto de imgs pra coisa ficar ainda mais fácil já no arranque, muito embora não exista nenhum configuração delas, isso é fácil de ser arranjado.<br />
<br />
<h4>Ao uso</h4><h5>No controller</h5><div class="syntaxhighlightercontainer"><pre class="brush: php">$schedule->fromArray($form->getValues());
$schedule->save();
Cs_FlashMessenger::addMessage('Adicionado um novo agendamento!');
$this->_redirect('/schedule');
</pre></div><br />
<h5>Na View</h5><div class="syntaxhighlightercontainer"><pre class="brush: html"><content>
<div id="messenger">
<?php echo $this->flashMessenger();?>
</div>
<div id="content">
<?php echo $this->layout()->content; ?>
</div>
</pre></div><br />
<br />
E é isso, ele não é uma versão final da lib mas já é usável. Ele pode ser baixado, clonado, o o que vc quiser fazer no link <a href="https://github.com/CesarScur/FlashMessenger">https://github.com/CesarScur/FlashMessenger</a>.Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com0tag:blogger.com,1999:blog-942231256726669006.post-12187625923348064692010-12-15T00:21:00.004-02:002010-12-15T00:25:19.549-02:00Zend_Auth uma Implementação Completa<div class="separator" style="clear: both; text-align: center;"><a class="lightbox" href="http://3.bp.blogspot.com/_4ttj6YxZQtQ/TQgkC8y1NSI/AAAAAAAABiY/GTAxnMsVNmQ/s1600/The_Heart_Key_by_deaddamien.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="239" src="http://3.bp.blogspot.com/_4ttj6YxZQtQ/TQgkC8y1NSI/AAAAAAAABiY/GTAxnMsVNmQ/s320/The_Heart_Key_by_deaddamien.jpg" width="320" /></a></div><br />
Sim eu gostaria muito de colocar um screencast explicando, mas é fim de ano e as coisas nem sempre são fáceis quando se tem mais tempo livre. Mas por sorte eu tive tempo de arrumar uma imagem e de terminar o código que eu vou explicar mais tarde. Com sorte vai ter algumas pessoas contentes.<br />
<br />
<a name='more'></a><br />
<br />
<br />
<div class="syntaxhighlightercontainer"><pre class="brush: php">//indexController.php
<?php
class IndexController
extends Zend_Controller_Action
{
/**
* TODO: move to a auth controller as login action
*/
public function indexAction()
{
$request = $this->getRequest();
/**
* TODO: change to Zend_Form isValid()
*/
if($request->isPost()
&& $request->getParam('login')
&& $request->getParam('pass')) {
$adapter = new My_Auth_Adapter(
$request->getParam('login'),
$request->getParam('pass')
);
$auth = Zend_Auth::getInstance();
$result = $auth->authenticate($adapter);
if(! $auth->hasIdentity() ) {
$this->view->msgs = $result->getMessages();
} else {
/**
* BONUS!!!
* Redirect to the place that the user
* was trying to access before
*/
$this->_redirect(
$request->getControllerName()
. '/'
. $request->getActionName()
);
}
}
echo 'Params';
Zend_Debug::dump($this->getRequest()->getParams());
}
/**
* TODO: move to a auth controller as logout action
*/
public function logoutAction()
{
Zend_Auth::getInstance()->clearIdentity();
$this->_redirect('');
}
/**
* Some restrict stuff to test
*/
public function secretAction()
{
echo 'Este &eacute; um conteudo Secreto';
Zend_Debug::dump(Zend_Auth::getInstance()->hasIdentity());
//todo:bad die
die();
}
}
</pre></div><br />
<div class="syntaxhighlightercontainer"><pre class="brush: php">// library/My/Auth/Adapter.php
<?php
class My_Auth_Adapter
implements Zend_Auth_Adapter_Interface
{
/**
* Error messeges
*/
const BAD_LOGIN = 'Login ou Senha Invalido!';
/**
*
* @var string
*/
protected $_login = null;
/**
*
* @var string
*/
protected $_pass = null;
/**
* Constructor
* @param string $login
* @param string $pass
*/
public function __construct($login, $pass)
{
$this->_login = $login;
$this->_pass = $pass;
}
/**
* Implementation of authenticate for Zend_Auth
* @return Zend_Auth_Result
*/
public function authenticate()
{
$user = Doctrine::getTable('User')->findOneByLogin($this->_login);
if($user) {
if('ldap' == $user->type) {
return $this->ldapAuth($user);
} else {
return $this->defaultAuth($user);
}
}
/**
* TODO: What if
* $type = $user->type . 'Auth';
* $this->$type();
* ???
*/
$result = new Zend_Auth_Result(
Zend_Auth_Result::FAILURE,
$user,
array(self::BAD_LOGIN)
);
return $result;
}
/**
* Default Auth Method
* @param User $user
* @return Zend_Auth_Result
*/
public function defaultAuth($user)
{
if($user->pass == $this->_pass) {
$result = new Zend_Auth_Result(
Zend_Auth_Result::SUCCESS,
$user,
array('hoorey')
);
return $result;
}
$result = new Zend_Auth_Result(
Zend_Auth_Result::FAILURE,
$user,
array(self::BAD_LOGIN)
);
return $result;
}
/**
* Ldap Auth method
* @param User $user
* @return Zend_Auth_Result
*/
public function ldapAuth($user)
{
/**
* TODO: LDAP Logic with Zend_Auth_Adapter_Ldap
*/
$result = new Zend_Auth_Result(
Zend_Auth_Result::FAILURE,
$user,
array(self::BAD_LOGIN)
);
return $result;
}
}
</pre></div><br />
<div class="syntaxhighlightercontainer"><pre class="brush: php">// library/My/Controller/Plugin/Auth.php
<?php
class My_Controller_Plugin_Auth
extends Zend_Controller_Plugin_Abstract
{
public function preDispatch(Zend_Controller_Request_Abstract $request)
{
if(!Zend_Auth::getInstance()->hasIdentity()) {
$request->setControllerName('index');
$request->setActionName('index');
}
}
}
</pre></div><br />
<br />
[img por <a href="http://deaddamien.deviantart.com/">deaddamien</a>]Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com0tag:blogger.com,1999:blog-942231256726669006.post-17969049354609022282010-10-18T21:16:00.008-02:002015-09-21T12:53:26.405-03:00Uma maneira de reescrever GET usando JS<a class="lightbox" href="http://contactdubai.com/wp-content/uploads/2009/04/seo.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"></a> <br />
Eu andei procurando como reescrever o get method de um form no formato usado tradicionalmente do url rewrite, e para minha surpresa a resposta mais popular tratava esse problema simples de maneira pouco otimizada.<br />
<a name='more'></a>O primeiro link do google é do site do <a href="http://matthewjamestaylor.com/blog/how-to-post-forms-to-clean-rewritten-urls" rel="nofolow">Matthew</a>, assim como vários subsequentes que referenciam o proprio site do Matthew. A abordagem dele consistem em gerar um get para uma url que converte no lado do servidor a url para o estilo com barras e retorna o cabeçalho http com o location da url "ajeitada". A argumentação e motivação de porque esse é um assunto importante, para mim, é a mesma do Matthew. Então vou deixar essa parte para que vc leia no site do autor original. <br />
Porém, é totalmente desnecessário fazer uma consulta para o servidor para gerar uma string. Então eu escrevi esse simples script usando dojo que converte os forms get para <i>forms url rewrited</i>. <br />
<div class="syntaxhighlightercontainer">
<pre class="brush: js; html-script: true"><script type="text/javascript">
dojo.addOnLoad(function() {
var form = dojo.query('form[method=get]');
//pode existir mais de 1 form; Não foi tratado aqui!
dojo.connect(form[0], 'onsubmit', function(e) {
e.preventDefault();
var location = '';
var inputs = dojo.query('form[method=get] input[name]');
for(i = 0; i < inputs.length; i++) {
location += '/' + inputs[i].name + '/' + inputs[i].value;
//sempre deve existir um campo hidden com name como controller e value como action
}
document.location = location;
});
});
</script>
<form method="GET" >
<input type="hidden" name="paginator" value="index" >
<input type="text" name="q">
</form></pre>
</div>
Eu não tratei múltiplos forms, mas você não vai ter dificuldade de descobrir como fazer isso certo? A mesma coisa vale se vc não gosta de dojo e quer esse script em jQuery ou mooTool.Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com0tag:blogger.com,1999:blog-942231256726669006.post-19199010900057106722010-10-07T12:43:00.012-03:002011-03-10T11:15:20.583-03:00Oauth Twitter<a class="lightbox" href="http://3.bp.blogspot.com/_4ttj6YxZQtQ/TK-sgwiWOvI/AAAAAAAABiI/-Oqb3CjLOWw/s1600/twitter+api.png"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5525824946591644402" src="http://3.bp.blogspot.com/_4ttj6YxZQtQ/TK-sgwiWOvI/AAAAAAAABiI/-Oqb3CjLOWw/s320/twitter+api.png" style="cursor: hand; cursor: pointer; display: block; height: 172px; margin: 0px auto 10px; text-align: center; width: 320px;" /></a> <br />
Seguindo a mesma lógica do ultimo post, irei dividir o conteúdo em algumas partes e vou atualizando o post a medida que o tempo me permite. O tema dessa vez é o twitter e sua api. Vou utilizar o zend oauth pra autenticar no twitter e fazer algumas operações bem básicas que podem ser aproveitadas em qualquer site.<br />
<a name='more'></a>Os passos que vamos seguir serão: o registro de uma app no site do twitter, a implementação do oauth, a implementação de alguns métodos básicos (como listar timeline e tweetar) e derrepente uma interface pra completar tudo. Espero ao final disponibilizar o fonte completo que foi gerado.<br />
<h4>Criando App</h4>Para utilizar o protocolo oauth precisa de uma chave de aplicativo. Essa chave serve para identificar quem é o responsável pela aplicação e limitar a quantidade de acessos. Essa chave é independente de que usa a app.<br />
Para obter esse registro basta acessar o side <a href="http://dev.twitter.com/">http://dev.twitter.com</a> fazer o login com o seu usuário de twitter (ou um usuário especial para a app, se preferir) e acessar "Your apps". Então em "Register a app", vc vai preencher um cadastro onde duas informações são importantes para o funcionamento do app. <i>Callback Url</i>, que deve ser a url que o twitter vai chamar quando completar o login do usuário (http://{url}/index/callback é o que eu usei) e o <i>Application type</i> que deve ser <i>browser.</i><br />
O callback tem uma questão importante. ele não pode ser localhost. Então se vc estiver testando na sua maquina, coloque um endereço qualquer (eu coloquei "twitter.cesarscur.com") e adicione ele no host apontando pra 127.0.0.1. Se vc tiver duvida nessa parte, não hesitarem perguntar.<br />
<h4>Colocando isso no código</h4>Eu resolvi deixar tudo em um controller apesar disso ser altamente desencorajado. Optei essa forma pois eu acho que didáticamente essa maneira é muito melhor. Então lembre-se de encapsular as coisa certas usando classes genéricas para poder reaproveitar o código depois. É possível que muito seja resolvido usando Zend_Rest, mas eu não cheguei a estudar essa possibilidade.<br />
<div class="syntaxhighlightercontainer"><pre class="brush: php"><?php
class IndexController extends Zend_Controller_Action
{
public $consumer;
public $config;
public function init()
{
$config = array(
'callbackUrl' => 'http://twitter.cesarscur.com/index/callback',
'requestTokenUrl' => 'http://twitter.com/oauth/request_token',
'authorizeUrl' => 'https://api.twitter.com/oauth/authorize',
'accessTokenUrl' => 'https://api.twitter.com/oauth/access_token',
'consumerKey' => '',
'consumerSecret' => '',
);
$this->config = $config;
$this->consumer = new Zend_Oauth_Consumer($config);
die('Você lembrou de settar a sua Key e Secret?
Procure no indexController::init()em application/controller/indexController.php');
}
public function indexAction()
{
$params = $this->getRequest()->getParams();
if (isset($_SESSION['TWITTER_ACCESS_TOKEN'])) {
if ($this->getRequest()->isPost()) {
$token = unserialize($_SESSION['TWITTER_ACCESS_TOKEN']);
$client = $token->getHttpClient($this->config);
$client->setUri('http://api.twitter.com/1/statuses/update.xml');
$client->setMethod(Zend_Http_Client::POST);
$client->setParameterPost('status', $params['tweetText']);
$response = $client->request();
$data = simplexml_load_string($response->getBody());
}
} else {
$this->_forward('login');
return ;
}
$token = unserialize($_SESSION['TWITTER_ACCESS_TOKEN']);
$client = $token->getHttpClient($this->config);
$client->setUri("http://api.twitter.com/1/users/show/{$token->user_id}.xml");
$response = $client->request();
$client->setMethod(Zend_Http_Client::GET);
$userData = simplexml_load_string($response->getBody());
$this->view->bgImg = $userData->profile_background_image_url;
$client->setUri('http://api.twitter.com/1/statuses/home_timeline.xml');
$response = $client->request();
$timeline = simplexml_load_string($response->getBody());
$this->view->timeline = $timeline;
}
public function loginAction()
{
}
public function oauthAction()
{
if(!isset($_SESSION['TWITTER_REQUEST_TOKEN'])) {
$token = $this->consumer->getRequestToken();
// persist the token to storage
$_SESSION['TWITTER_REQUEST_TOKEN'] = serialize($token);
// redirect the user
$this->consumer->redirect();
}
}
public function logoutAction()
{
$_SESSION['TWITTER_REQUEST_TOKEN'] = null;
$_SESSION['TWITTER_ACCESS_TOKEN'] = null;
$this->_redirect('');
}
public function callbackAction()
{
if (!empty($_GET) && isset($_SESSION['TWITTER_REQUEST_TOKEN'])) {
$token = $this->consumer
->getAccessToken($_GET,
unserialize($_SESSION['TWITTER_REQUEST_TOKEN']));
$_SESSION['TWITTER_ACCESS_TOKEN'] = serialize($token);
$_SESSION['TWITTER_REQUEST_TOKEN'] = null;
}
$this->_redirect('');
}
}
</pre></div>Certo, é um monte de código. Vamos entender o fluxo das coisas.<br />
1 - O usuário acessa a index sem estar autenticado e é redirecionado para uma pagina para efetuar o login. A interface apenas apresenta um link para oauthAction;<br />
2 - A action pega a requestToken com o twitter e redireciona o usuário para a pagina de login do twitter;<br />
3 - O twitter redireciona o usuário de volta a action callback passando a acessToken. acessToken é nossa chave de entrada para os serviços da api. Então o callback redireciona o usuário para index onde ele agora pode ver a sua timeline.<br />
4 - A index dessa vez faz uma consulta para /statuses/home_timeline e lista a timeline do usuário logado. Também usei a /users/show para pegar o papel de parede do usuário e deixar a interface um pouco mais "twitter" de ser.<br />
5 - Na index ainda temos o handler de tweets, onde usamos o /statuses/update para postar um tweet.<br />
<i><span class="Apple-style-span" style="font-size: small;">Perdão pela indentação que esta um lixo. Eu estou trocando meus tabs por 4 espaços e essa faze de transição é bem complicada.</span></i><br />
Por fim, o fonte de tudo isso, e novamente, o código precisa ser refatorado pesadamente e vários pontos, pois o propósito dele não é ser um modelo de sistemas, apenas uma demonstração de como o Zend_Oauth e a api do twitter funcionam. Não me crucifiquem pela bagunça nos css =).<br />
Se vc não tem o zend framework configurado no seu php pode baixar e colocar ele na pasta library.<br />
<div><a href="https://sites.google.com/site/xugarcult/twitter.zip?attredirects=0&d=1"><img alt="zip" border="0" src="http://msmvps.com/blogs/bill/WindowsLiveWriter/Shinynewiconsandimprovediconeditor_E115/zip_2.png" style="float: left; height: 32px; margin: 0pt; padding: 0pt; width: 32px;" />Download</a></div><div style="clear: both;"></div>[Via <a href="http://framework.zend.com/manual/en/zend.oauth.introduction.html">ZendFramework </a>e <a href="http://blog.astrumfutura.com/2009/07/writing-a-simple-twitter-client-using-the-php-zend-frameworks-oauth-library-zend_oauth/">Maugrim's blog</a>]Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com0tag:blogger.com,1999:blog-942231256726669006.post-22894671256344158422010-10-05T12:42:00.007-03:002010-10-07T07:33:12.146-03:00Encurtando URLs<img style="display:block; margin:0px auto 10px; text-align:center;width: 280px; height: 47px;" src="http://bit.ly/s/v126/graphics/logo_bitly.png" border="0" alt="" />
<p>Tenho tido pouco tempo pro blog, então vou tentar algo diferente. Em vez de um post completo dessa vez vou colocar parte dele, e vou atualizando até ele ficar pronto. O tema desse post vai ser a api para encurtar urls do <a href="http://bit.ly/">bit.ly</a>, já que o google ainda não tem a sua api.</p><a name='more'></a><p>Ok, a primeira coisa é identificar quais os requisitos para se usar a api. A documentação pode ser encontrada <a href="http://code.google.com/p/bitly-api/wiki/ApiDocumentation">aqui</a>. O que precisamos saber é que a api é construída em REST e requer uma autenticação. Para conseguir essa autenticação que é o login e a apiKey, vc tem que criar um login no site. Depois de criar o login e fazer login no site basta entrar nesse link <a href="http://bit.ly/a/your_api_key/">http://bit.ly/a/your_api_key/</a> para saber a sua apiKey.</p><p>Agora com o login e o apiKey da pra testar com essa url, por exemplo, <a href="http://api.bit.ly/v3/shorten?login={seuLogin}&apiKey={suaApiKey}&longUrl=http://www.cesarscur.com/&format=json">http://api.bit.ly/v3/shorten?login={seuLogin}&apiKey={suaApiKey}&longUrl=http://www.cesarscur.com/&format=json</a></p><p>Agora vamos ver como colocar isso no php sem muita dor.</p><div class="syntaxhighlightercontainer"><pre class="brush: php">
$client = new Zend_Rest_Client('http://api.bit.ly/v3/shorten');
$client->login('{seuLogin}')
->apiKey('{suaApiKey}')
->longUrl('http://www.cesarscur.com/')
->format('xml');
$response = $client->get();
echo $response->url();</pre></div><p>Com esse script vc obtém a url encolhida. Para pegar a longUrl de uma shotened ou quantos clicks esse link já recebeu basta dar uma olhada na documentação e segui a mesma lógica! </p><p>Usar o bit.ly é muito mais fácil do que criar o próprio. Além de ter todas as vantagens que serviços distribuídos na nuvem tem. Espero que aproveitem esse post \o.</p>Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com0tag:blogger.com,1999:blog-942231256726669006.post-5447809791292929462010-09-05T18:35:00.005-03:002010-09-08T09:12:56.150-03:00Avaliação de Desempenho<div class="separator" style="clear: both; text-align: center;"><object width="520" height="313"><param name="movie" value="http://www.youtube.com/v/a-9pCfyYPdQ?fs=1&hl=pt_BR"><param name="allowFullScreen" value="true"><param name="allowscriptaccess" value="always"><embed src="http://www.youtube.com/v/a-9pCfyYPdQ?fs=1&hl=pt_BR" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="520" height="313"></embed></object></div><p>O titulo desse post poderia ser "Criando cache de imagens no browser". Mas eu queria também apresentar uma ferramenta bem legal. O nome dela é Page Speed.</p><a name='more'></a><p>Eu usei essa ferramenta pra avaliar algumas partes de um site do qual eu não participei do desenvolvimento desde o começo. E ela foi bem eficiente em me mostrar os pontos onde eu podia melhorar o desempenho. Então foi só aplicar algumas correções rápidas e pronto. A pagina ficou um foguete.</p><p>Essa ferramenta é do próprio google e é um plugin para firebug. Ela esta com certeza na minha lista de must have de ferramentas de desenvolvimento. Você pode conseguir o Page Speed <a href="http://code.google.com/intl/pt-BR/speed/page-speed/">aqui</a>.</p><p>O problema que ela identificou, era que algumas imagens não estavam sendo colocadas no cache do navegador. Porque eram redimensionadas <i>on the fly</i> pelo php e o header não era setado apropriadamente. <a href="http://www.cesarscur.com/2010/08/o-cache-e-o-php.html">Eu falei sobre cache em outro post</a>, mas nesse caso especifico eu deixei faltando algum exemplo de código de como implementar o uso do cache do navegador. Então tá ai:</p><div class="syntaxhighlightercontainer"><pre class="brush: php">$etag = md5_file($foto);
$lastModified = gmdate("D, d M Y H:i:s", filemtime($foto)) . " GMT";
$expires = 604800;
header("Cache-Control: max-age= $expires, private");
header("Expires: $expires");
header("Pragma: cache");
header('Content-type: image/jpeg');
header("Last-Modified: $lastModified");
header("Etag: $etag");
if (@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $lastModified ||
trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag) {
header("HTTP/1.1 304 Not Modified");
exit;
}</pre></div><p>Com esse script o browser vai fazer cache da imagem o que vai evitar requisições desnecessárias. Em vez de baixar toda imagem a cada request, ele vai baixar apenas <i>HTTP/1.1 304 Not Modified</i>. Além disso vai evitar o resample que é feito a cada request da imagem, que era o meu caso. Pra resolver o resample é mais indicado fazer o cache no próprio servidor, mas isso é só gravar a img em uma pasta já redimensionada.</p>Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com0tag:blogger.com,1999:blog-942231256726669006.post-10960332634206721502010-09-02T12:30:00.002-03:002010-09-02T13:20:49.227-03:00Css Transition e Links<a class="lightbox shadowbox" href="http://4.bp.blogspot.com/_4ttj6YxZQtQ/THfdsXdt-YI/AAAAAAAABhY/flPB_9u4wzk/s1600/tags+hover.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;" src="http://4.bp.blogspot.com/_4ttj6YxZQtQ/THfdsXdt-YI/AAAAAAAABhY/flPB_9u4wzk/s320/tags+hover.jpg" /></a>
<p>Eu descobri a pouco tempo que o css sozinho é capas de criar algumas <a href="http://cesarscur.blogspot.com/2010/08/css-continua-me-impressionado.html">animações bem interessantes</a>. Uma delas eu coloquei nos links das tags. Se você usa o IE nem deve ter notado, mas se usa o Safari ou Chrome deve ter achado o máximo, como eu =D. Se vc curtiu eu dou a barbada de como criar.</p><a name='more'></a><div class="syntaxhighlightercontainer"><pre class="brush: css">.cpojer-links a {
display: inline-block;
padding: 4px;
outline: 0;
color: #3a599d;
-webkit-transition-duration: 0.25s;
-moz-transition-duration: 0.25s;
-o-transition-duration: 0.25s;
transition-duration: 0.25s;
-webkit-transition-property: -webkit-transform;
-moz-transition-property: -moz-transform;
-o-transition-property: -o-transform;
transition-property: transform;
-webkit-transform: scale(1) rotate(0);
-moz-transform: scale(1) rotate(0);
-o-transform: scale(1) rotate(0);
transform: scale(1) rotate(0);
}
.cpojer-links a:hover {
background: #3a599d;
text-decoration: none;
color: #fff;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
-o-border-radius: 4px;
border-radius: 4px;
-webkit-transform: scale(1.05) rotate(-1deg);
-moz-transform: scale(1.05) rotate(-1deg);
-o-transform: scale(1.05) rotate(-1deg);
transform: scale(1.05) rotate(-1deg);
}
.cpojer-links a:nth-child(2n):hover {
-webkit-transform: scale(1.05) rotate(1deg);
-moz-transform: scale(1.05) rotate(1deg);
-o-transform: scale(1.05) rotate(1deg);
transform: scale(1.05) rotate(1deg);
}
</pre></div><p>Esse é todo o código que vc vai precisar. Talvez vc vai querer um container diferente pra tag <a>. Mas tenho certeza que vc consegue ajeitar o seu html e esse css sem problemas pra fechar com a sua necessidade.</p><p>Essa animação, infelizmente só roda hoje no chrome, safari e opera. O Firefox não roda as transições, mas o transform sozinho já da um efeito bem agradável. Nas novas versões beta do FF e IE (4 e 9 respectivamente) a transição já funciona. Então é implementar e esperar pelo futuro preparado =D.</p>
<p>[<a href="http://cpojer.net/">Christoph Pojer</a> via <a href="http://davidwalsh.name/css-transformations">David Walsh</a>]</p>Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com2tag:blogger.com,1999:blog-942231256726669006.post-19778186338554190982010-08-31T07:29:00.008-03:002010-09-02T13:07:11.748-03:00HTML5 é impressionante<a class="lightbox" alt="The Wildness Downtown" title="The Wildness Downtown" href="http://2.bp.blogspot.com/_4ttj6YxZQtQ/THzbqene_2I/AAAAAAAABhw/kDTvnKAh3Q0/s1600/thewildnessdowntown.JPG"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 174px;" src="http://2.bp.blogspot.com/_4ttj6YxZQtQ/THzbqene_2I/AAAAAAAABhw/kDTvnKAh3Q0/s320/thewildnessdowntown.JPG" /></a>
<p>Sabe quando você vê uma coisa e sabe que ela tem o potencial pra ser <span style="font-style:italic;">the next big thing</span>? Foi o que eu senti quando eu vi esse site. Eu já ouvi que a <a href="http://www.gizmodo.com.br/conteudo/wired-diz-que-web-bateu-botas-devemos-comecar-o-velorio">web esta morrendo</a> e que não acreditam no potencial do HTML5. Mas com certeza isso não é verdade.</p><a name='more'></a><p><a href="http://thewildernessdowntown.com/">http://thewildernessdowntown.com/</a></p><p>Acho que até roda no firefox, mas pra garantir que vc não vai perder nada (e vale muito a pena, eu garanto) instale o <a href="http://www.google.com.br/chrome">Google Chrome</a> antes de assistir. E se a sua maquina tá precisando de upgrade as coisas vão ficar beeeeeem lenta.</p><p>Vc também ficou impressionado?</p><p>[<a href="http://thewildernessdowntown.com/">The Wildness Downtown</a> via <a href="http://www.gizmodo.com.br/conteudo/como-o-arcade-fire-mostrou-que-web-ainda-nao-morreu">Gizmodo</a>]</p>Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com0tag:blogger.com,1999:blog-942231256726669006.post-85363186786777958582010-08-28T19:27:00.005-03:002010-08-28T20:13:54.500-03:00Exemplo de implementação usando Zend framework<a class="lightbox" title="Zend Framework" alt="Zend Framework" href="http://www.profissionaisti.com.br/wp-content/uploads/2010/05/logo-zend-framework.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 282px; height: 190px;" src="http://www.profissionaisti.com.br/wp-content/uploads/2010/05/logo-zend-framework.jpg" border="0" alt="" /></a><p>Como aplicar os modulos na construção MVC usando ZF era uma pergunta que estava me faltando responder pra mim mesmo a algum tempo. Faltava clareza na minha interpretação. E conversando com o Maicon eu percebi que não era só eu que tinha dificuldade em entender o papel e aplicação do modulo.</p><a name='more'></a><p>Então fui atrás de uma resposta mais completa que o reference guide do framework. Encontrei o site do Ben Scholzen (<a href="http://www.dasprids.de/">Dasprid</a>) que disponibilizou o proprio site como open source nesse <a href="http://www.dasprids.de/behind-the-site">SVN aqui</a> (<a href="http://site.svn.dasprids.de/">http://site.svn.dasprids.de/</a>). E explorando o fonte do site do Ben eu devo ter encontrado mais novas perguntas que respostas. Esse não um bom lugar pra começar a usar zf, esse projeto é muita coisa pra digerir de uma vez. Mas a resposta que eu procurar eu encontrei, então guarde esse link:</p><p>A primeira impressão sobre modulos que eu tive, que o Maicon inclusive compartilhou comigo, é que deveríamos segmentar a frontend do backend usando modulo (site e admin). Mas o que o fonte do Ben mostra são modulos por componentes. Assim o componente blog é um modulo composto por 2 controllers, um index e um admin. Poderia ser noticias, a busca, o contato ou o catalogo de produtos que costumamos ver dentro de sites comerciais frequentemente.</p><p>Logo me dei conta que isso era praticamente obvio, como eu não tinha notado antes? Mais uma vez os patterns mostram pra que existem =D. A maneira mais fácil de enxergar um modulo era pelas entidades (tabelas) que ele faria uso. Como em um blog as entidades post e comentário só fazem sentido dentro do blog. Então elas podem ser encapsuladas dentro do modulo, junto com todas as interfaces que são pertinentes, administração/backend e exibição no frontend . Dessa mesma forma, um site sem blog que contem a sua própria admin faz muito mais sentido que um site sem uma admin nenhuma. A palavra modular faz muito sentido agora não?</p><hr /><p>A primeira duvida foi: Como ele define que a index vai ser a index do modulo blog se o modulo default não tem nenhum redirect e nas configs de rota não tem nada especifico apontando o blog? Talvez me falte conhecimento sobre as rotas. Talvez eu faça um post sobre isso logo =D</p>Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com0tag:blogger.com,1999:blog-942231256726669006.post-21211027749672689552010-08-27T12:58:00.004-03:002011-05-20T08:23:31.569-03:00Css Continua me Impressionado<a class="lightbox" href="http://4.bp.blogspot.com/_4ttj6YxZQtQ/THfiBoi4JII/AAAAAAAABho/DWSaiXchX-k/s1600/fail_whale.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 151px;" src="http://4.bp.blogspot.com/_4ttj6YxZQtQ/THfiBoi4JII/AAAAAAAABho/DWSaiXchX-k/s320/fail_whale.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5510118977918982018" /></a><p>Eu tenho post sobre css no forno, mas primeiro eu queria dar um gostinho do que o css é capaz. A imagem a cima foi criada inteiramente com css. Clique no leia mais para ver a versão em css.</p><a name='more'></a><p>O mais impressionante é que ela é uma animação. Mas como nem todo browser tem capacidade de interpreta-la da forma correta vc pode ter experiências diferentes. Então, com IE8 vc verá quadrados horríveis (porque o IE sux e não há hack que resolva - resamos pelo IE9), verá uma copia "idêntica" a imagem a cima no FF3+ e a animação no Chrome ou Safari. Confira ela rodando no seu browser no site <a href="http://www.subcide.com/experiments/fail-whale/">http://www.subcide.com/experiments/fail-whale/</a>.</p><p>Alias, tenho usado muito o chrome por causa disso, recomendo.</p>[<a href="http://www.subcide.com/articles/pure-css-twitter-fail-whale/">Subside.com</a>]Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com0tag:blogger.com,1999:blog-942231256726669006.post-80453388256401023362010-08-24T00:07:00.005-03:002010-09-28T12:49:51.319-03:00O Cache e o PHP<div class="separator" style="clear: both; text-align: center;"><a class="lightbox" alt="Cache Speed" title="Cache Speed" href="http://2.bp.blogspot.com/_4ttj6YxZQtQ/THLVLB7ZoVI/AAAAAAAABgY/nAQWzhSeyIQ/s1600/fast_lane_burbank.jpg"><img src="http://2.bp.blogspot.com/_4ttj6YxZQtQ/THLVLB7ZoVI/AAAAAAAABgY/nAQWzhSeyIQ/s320/fast_lane_burbank.jpg" border="0" /></a></div>
<p>Eu vejo muita confusão ainda nos dias de hoje sobre o que o cache é e qual o seu papel na aplicação. A idéia desse post é explicar o cache e mostrar algumas implementações simples onde o cache pode fazer grande diferença.</p><a name='more'></a><h4>Definindo Cache</h4><p>Cache, por definição não se restringe ao PHP. Na verdade é uma estratégia de otimização de um processo que é aplicada em uma camada superior do problema que esta sendo resolvido. Por exemplo, vemos cache em processadores armazenando pequenos blocos de memória que tem um volume de requisições grande. Vemos cache nos HDs que desempenham o mesmo papel.</p><p>Em suma, cache é um local de acesso mais rápido onde colocamos a informações que usamos mais. O cache também é o local onde colocamos resultados de processos dispendiosos que certamente iremos precisar novamente. Porem o recurso de hardware associado ao cache são geralmente bastante limitados. Por isso temos que escolher com cuidado o que colocar no cache.</p><h4>Cache e a Web</h4><p>Esse talvez seja o escopo que causa a maior confusão. Entre o brower e o servidor temos uma quantidade muito grande de "caches diferentes". Temos no navegador cache de imagens, cache de documentos, de DNS. No servidor temos cache do opcode (no caso do PHP), cache de output, de funções, de requisições, de web services.</p><p>E, talves, o ponto que cause maior confusão é o fado de que o servidor é capaz de manipular como o navegador deve fazer o cache de cada response. Vamos dividi-las e conquista-las uma a uma.</p><h4>Cache e o Browser</h4><p>Então até aqui varias explicações teóricas e a pratica? Tranquilo, aqui podemos ver algo mais interessante e ver como alterar o alterar o cache do browser.</p><div class="syntaxhighlightercontainer"><pre class="brush: php">header("Cache-Control: no-cache, must-revalidate");</pre></div><p>O header da resposta http é responsavel por indicar o tempo de cache para o browser. Esse código, por exemplo faz com que o browser ignore o cache para esse elemento, requisitando uma nova copia a cada necessidade. Mas lembre-se, cada navegador pode interpretar as instruções de maneira diferente. E que mesmo quando não é definido o header padrão é enviado, oque é o caso de imagens. Se precisar de mais detalhes do que usar no header <a href="http://www.cesarscur.com/2010/09/avaliacao-de-desempenho.html">começe por aqui</a>.</p><h4>Cache e o Servidor</h4><h5>Aceleradores</h5><p>Também conhecidos com aceleradores, algumas extensões do PHP são responsáveis por fazer cache do código intermediário gerado durante a execução de um script. Esse código, chamado opcode, pode levar alguns preciosos milésimos de segundos para ser gerado, mas em escala resulta num ganho considerável. Algumas alternativas de aceleradores:</p><ul><li><a href="http://php.net/manual/en/book.apc.php">APC</a></li><li><a href="http://xcache.lighttpd.net/">XCache</a></li><li><a href="http://eaccelerator.net/">eAccelerator</a></li></ul><p>O APC é bastante popular e vc pode notar que ele se encontra no manual do próprio PHP, apesar de ser uma extensão. Se vc quer performance é um tiro certo instala-lo.</p><h5>Implementando Cache</h5><p>As demais formas de cache passam por identificar o seu problema e ataca-lo diretamente. Identificar onde colocar o cache parece a parte mais fácil, mas não se engane, essa pode ser a parte mais traiçoeira, fazendo vc gastar recursos desnecessários. É importante identificar onde o cache pode ou não ser aplicado. Por exemplo, vc tem um web app que coloca o nome usuário logado na tela, ou qualquer outra informação especifica por usuário. Nesse caso é inviável vc aplicar um cache completo de output. Essa é analise que tem de ser feita antes de aplicar o cache. Ou seja, essa parte esta lenta? Da pra por cache? Cache nela!</p><p>Ok, mas isso é muito papo e pouco cache, digo, pouca ação. Como eu crio o cache de alguma coisa? Existem varias maneiras de criar um cache, desde usar a session a usar um framework pra cuidar do trabalho.</p><div class="syntaxhighlightercontainer"><pre class="brush: php">
$frontendOptions = array(
'lifetime' => 7200, // cache lifetime of 2 hours
'automatic_serialization' => true
);
$backendOptions = array(
// Directory where to put the cache files
'cache_dir' => './tmp/'
);
// getting a Zend_Cache_Core object
$cache = Zend_Cache::factory('Core',
'File',
$frontendOptions,
$backendOptions);
$id = 'myBigLoop'; // cache id of "what we want to cache"
if (!($data = $cache->load($id))) {
// cache miss
$data = '';
for ($i = 0; $i < 10000; $i++) {
$data = $data . $i;
}
$cache->save($data);
}
// [...] do something with $data (echo it, pass it on etc.)</pre></div><p>Usando esse trecho de código vc pode implementar o cache de qualquer coisa. Métodos, widgets, consultas, o que precisar. E o mais legal de usar o Zend_Cache é que vc pode fazer cache em arquivo, em sqlit, memcache, apc, xcache, entre outros só trocando a variável o parâmetro do factory desse jeito:</p><div class="syntaxhighlightercontainer"><pre class="brush: php">$cache = Zend_Cache::factory('Core',
'APC',
$frontendOptions,
$backendOptions);</pre></div><p>Mas lembre que os parâmetros do <i>$backendOptions</i> devem acompanhar o backend selecionado. Mais detalhes em <a href="http://framework.zend.com/manual/en/zend.cache.introduction.html">Zend_Cache</a></p>Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com0tag:blogger.com,1999:blog-942231256726669006.post-40327716309616326812010-08-19T19:35:00.004-03:002010-08-23T16:52:12.884-03:00Criando Vergonha na Cara e Usando o Debug do PHP<div class="separator" style="clear: both; text-align: center;"><a title="Chutando Bugs" alt="Chutando Bugs" class="lightbox" href="http://3.bp.blogspot.com/_4ttj6YxZQtQ/TG6SflEs8mI/AAAAAAAABgA/CNGP-LIQH8Y/s1600/kicking+bug.jpg"><img src="http://3.bp.blogspot.com/_4ttj6YxZQtQ/TG6SflEs8mI/AAAAAAAABgA/CNGP-LIQH8Y/s320/kicking+bug.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5507255005965549058" /></a></div>
<p>A preguiça sempre foi minha inimiga, mas já era tempo de dar um basta nessa lenga-lenga, criar vergonha na cara e começar a usar a porcaria dum debugger pra PHP. Chega de usar var_dump e print_r.</p><a name='more'></a><p>Esse post pode chegar ao nível do ridículo, a ponto deu pensar, porque eu vou postar isso. Mas eu acho que vale como marco, como referencia do dia em que mais um pequeno passo para se construir uma imagem decente do php foi dada.</p><p>Vamos la:</p><h4>Server Side</h4><p>Baixar e instalar o <a href="http://www.zend.com/en/download/355">Zend Server CE</a> (<a href="http://www.zend.com/en/products/server-ce/downloads">problemas com o link</a> ou <a href="http://www.zend.com/en/products/server-ce/downloads">não usa windows?</a>). A instalação é for dummies: next, next, finish.</p><h4>Client Side</h4><p>Baixar e instalar o <a href="http://www.eclipse.org/pdt/downloads/">Eclipse PDT</a> (note que nesse link vc também encontra o ZSCE e o Xdebug avulsos)</p><h4>Rodar o Debug</h4><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 63px; height: 56px;" src="http://3.bp.blogspot.com/_4ttj6YxZQtQ/TG24w6A8ZUI/AAAAAAAABfY/hElU-aFVBY0/s320/debug+icon.png" border="0" alt="Debug Icon" /><p>Sim, esse passo é complicao, cuidado para não se confundir. Abra o seu script e clique no icone de debug (dica: é o da imagem acima).</p><p>Ok, agora piadas a parte, eu sei que isso foi ridículo. Claro que isso pode ser feito bem mais complexo, caso você queira instalar o xdebug no seu xamp preferido ou com a sua IDE favorita. A questão é que não doi nada começar a usar. Eu prometo que as coisas começam a ficar bem mais divertidas quando o seu debug precisa acontecer num script que depende de login para rodar. E se você utiliza o Zend Studio, pode ficar tranquilo, ainda da pra usar o profiler pra medir o desempenho totalmente detalhado do seu script, método a método. (dizem... ainda não testei, mas estou ansioso)</p><p>De fato outras coisas tem que acontecer para começar a fazer um bom uso do debbuger. Isso se dá pois o debug ocorre para uma requisição por vez, e não uma sequência de acessos. Então ou se usar testUnit para debug ou se cria um login simulado para simular um usuário. A sugestão é implementação de test Units para rodar os testes (Zend Studio vem configurado assim, alias). Mas claro, nada de complicação se o seu site não depende de login por exemplo. Bom, eu detalho essas praticas mais pra frente em outro post.</p><p>Por enquanto é isso ae, e de agora em diante quando uso var_dump gera E_STRICT ;P</p><p><small>OBS.: A partir desse post os comentários são pelo Intense Debate. Se acharem muito ruim eu coloco o original de volta =D</small></p>Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com0tag:blogger.com,1999:blog-942231256726669006.post-81977063236785342152010-08-16T23:30:00.015-03:002010-08-28T21:29:38.958-03:00Acesso a Banco de Dados com PDO<div class="separator" style="clear: both; text-align: center;"><a class="lightbox" href="http://4.bp.blogspot.com/_4ttj6YxZQtQ/TGBEOpXbrTI/AAAAAAAABek/3QecLUAYj5g/s1600/__CODE____PHP_by_webblaster48.jpg"><img src="http://4.bp.blogspot.com/_4ttj6YxZQtQ/TGBEOpXbrTI/AAAAAAAABek/3QecLUAYj5g/s320/__CODE____PHP_by_webblaster48.jpg" border="0" alt="php" /></a></div>
<p>Quando eu comecei a programar PHP muitas práticas interessantes não faziam parte do meu cotidiano. Eu tive que aprender muita coisa errando e pesquisando na net. Trocar o banco de uma aplicação de mysql pra postgres pode dar bastante dor de cabeça. E esquecer de escapar as querys pode resultar em SQL injections. Muitos programadores não conhecem os perigos dos SQLs.</p><p>Bom, uma das ferramentas que deveríamos usar em nosso dia a dia é o PDO, ou algum DO (data object) qualquer. Por exemplo, você lembra de escapar <b>todas</b> as querys que você roda? Eu não culpo, eu também esqueceria. Mas isso leva a uma falha de segurança grave. E implementar usando PDO pode ser muito menos doloroso do que possa parecer.</p><a name='more'></a><p>Na verdade eu não vou mostrar como implementar uma conexão com PDO, mas sim usando Zend_DB. Optei por essa por ser possível integrar posteriormente com o Zend_Config e com o padrão MVC (algo que eu quero mostrar mais tarde). Mas fique tranquilo, as diferenças no que irei mostrar para o PDO em si são mínimas</p><div class="syntaxhighlightercontainer"><pre class="brush: php">
$db = Zend_Db::factory('Pdo_Oci', array(
'host' => 'banco.xxxxxx.com.br',
'port' => '1521',
'username' => 'adm',
'password' => 'xxx',
'dbname' => 'banco'
));</pre></div><p>Este é o código usado para a conexão com o banco. Nada de mistério até aqui. Fácil de entender, fácil de implementar, sem traumas como eu prometi.</p><div class="syntaxhighlightercontainer"><pre class="brush: php">
$nome = "admin' or 1 = 1 --";
$result1 = $db->fetchAll("select * from sistemas where nome = ?", $nome);
$result2 = $db->fetchAll("select * from sistemas where nome = '$nome'");
var_dump($result1, $result2, $nome, $db->quote($nome));
/*
Outputs
array(0) {
}
array(8) {
//dump da tabela
}
string(18) "admin' or 1 = 1 --"
string(21) "'admin'' or 1 = 1 --'"
*/</pre></div><p>Este segundo trecho pode ser bem mais interessantes. Existem algumas coisas aqui que realmente valem a pena serem detalhadas:</p><h4>Statement</h4><p>A sql dentro do fetchAll ganharão um statement, independente do SGDB que você usa. Eu digo isso por 2 motivos:</p><ul><li>Nem todo mundo utiliza as statements.</li><li>Nem todo mundo utiliza da forma correta ou ótima.</li></ul><p>Statements afirmam que essa sql será reutilizada da forma que ela esta escrita, o que permite o banco se preparar para executa-la de maneira otimizada. Isso representa um ganho de desempenho muito interessante. Ainda, muitas vezes as statements são feitas como <i>"select * from id = $id"</i>. O que acontece nesse caso é que cada nova execução gera uma sql diferente a anterior. Então o cache do banco sera feito uma vez para cada possibilidade, como <i>"select * from id = 9"</i> e assim por diante.</p><h4>Escaping</h4><p>Quantas vezes você se esqueceu de escapar os dados? Você sabe o que é <a href="http://pt.wikipedia.org/wiki/Inje%C3%A7%C3%A3o_de_SQL">sql injection</a>, então você está preocupado sobre isso certo? Então boas novas, muitas das suas preocupações vão embora. Com o uso de um DO você tem o escaping em todas as suas SQLs sem força.</p><h4>Acesso a banco flexível </h4><p>Trocar de banco de dados pode ser uma dor de cabeça certo? Bom, metade dos seus problemas você resolve com PDO. Sendo que você só precisa trocar o driver que o você vai usar na ora de criar a conexão só vai precisar trocar as SQL que você não usou SQL standard, certo? Errado! Se você for um pouquinho mais fundo, vai ver que existem construções de query dentro do Zend_Db que abstraem o SQL, então as preocupações com SQL standard vão embora</p><div class="syntaxhighlightercontainer"><pre class="brush: php">
$select = $db->select()
->from(' ...specify table and columns... ')
->where(' ...specify search criteria... ')
->order(' ...specify sorting criteria... ');</pre></div><p>Mas isso é um assunto mais long, e vai precisar de um outro post pra explorar =D. Bacana né? Fácil? Também.</p>Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com1tag:blogger.com,1999:blog-942231256726669006.post-1149930428510052712010-08-12T19:52:00.028-03:002010-08-14T14:36:30.459-03:00Colocando Código nos Posts<div class="separator" style="clear: both; text-align: center;"><a class="lightbox" href="http://2.bp.blogspot.com/_4ttj6YxZQtQ/TGR72mMdQFI/AAAAAAAABfE/8SPagSZEkaw/s1600/SyntaxHighlighter.png"><img src="http://2.bp.blogspot.com/_4ttj6YxZQtQ/TGR72mMdQFI/AAAAAAAABfE/8SPagSZEkaw/s320/SyntaxHighlighter.png" border="0" alt="Syntax Hightlighter " /></a></div>
<p>Colocar um hightlighter no site não é algo tão simples como deveria. Na verdade não é simples nem descobrir que esse é o nome do que você esta procurando. Então se o que você quer no seu site é algo como o da imagem, "bem vindo, você veio ao lugar certo".</p><a name='more'></a><p>Então vou dividir a implementação e alguns poucos passos:</p><p>1. Preparar o html:</p><div class="syntaxhighlightercontainer"><pre class="brush: js; html-script: true">
<pre class="brush:js">
&lt;script type=&quot;text/javascript&quot;&gt;
dojo.require(&quot;dojo.parser&quot;);
dojo.parser.parse();
&lt;/script&gt;
</pre></pre></div><p>O syntaxHighlighter vai procurar as tags <pre /> com a class brush. Então na própria class você coloca o tipo de código. No meu caso javascript (js). Mas se o seu código for outro, sem galho, no site <a href="http://alexgorbatchev.com/SyntaxHighlighter/">http://alexgorbatchev.com/SyntaxHighlighter/</a> tem uma lista dos nomes e dos highlights disponíveis, assim com uma serie de temas. Observe também que o seu código deve ser encodado com html entities. Dá para usar o php com htmlentities($html) ou um site que faça isso online. Como <a href="http://www.opinionatedgeek.com/dotnet/tools/htmlencode/encode.aspx">este</a>.</p><p>2. O código JS que fará o parse:</p><div class="syntaxhighlightercontainer"><pre class="brush: js; html-script: true">
<style type="text/css">
@import "http://alexgorbatchev.com/pub/sh/current/styles/shThemeEclipse.css";
@import "http://alexgorbatchev.com/pub/sh/current/styles/shCore.css";
</style>
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js" type="text/javascript"></script>
<script src="http://alexgorbatchev.com/pub/sh/current/scripts/shAutoloader.js" type="text/javascript"></script>
<script type="text/javascript">
dojo.addOnLoad(function() {
SyntaxHighlighter.defaults['toolbar'] = false;
SyntaxHighlighter.config.bloggerMode = true;
SyntaxHighlighter.autoloader(
'php http://alexgorbatchev.com/pub/sh/current/scripts/shBrushPhp.js',
'js http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js'
);
SyntaxHighlighter.all();
});
</script></pre></div><p>No lugar do dojo.addOnLoad pode-se usar o equivalente do framework que estiver utilizando ou window.onload. O bloggerMode = true é importante apenas se o código vai ganhar <br />s entre cada linha de código (o que ocorre aqui no blogger). O autoloader vai carregar dinamicamente o highlighter para o tipo de código que foi selecionado na tag <pre />. Lembre-se de adicionar outros se for usar. Eu utilizei o tema shThemeEclipse.css, existem outros para escolher no site do desenvolvedor também.</p><p>3. Customizando a aparência:</p><div class="syntaxhighlightercontainer"><pre class="brush: css; html-script: true">
<style>
.syntaxhighlightercontainer {
background:none repeat scroll 0 0 #E2F1F8;
border-left:1px solid #C2C9D1;
margin-bottom: 30px;
padding:20px;
}
.syntaxhighlighter,
.syntaxhighlighter .line.alt2,
.syntaxhighlighter .line.alt1 {
background-color: transparent !important;
}
.syntaxhighlighter .gutter .line {
border-right:0 !important;
margin-right: 20px;
}
</style></pre></div><p>Customizar a aparência é bem tranquilo, basta alguns CSSs. O que utilizei aqui para ficar parecido com o do zendframework docs foi esse. É preciso acresentar também essa tag <div class="syntaxhighlightercontainer"> em volta do <pre />.</p><p>É isso ai, espero que tenham curtido esse tutorial e que consiguam deixar seus blogs mais fáceis de ler sem quebrar muito a cabeça.Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com0tag:blogger.com,1999:blog-942231256726669006.post-76586479738291741572010-08-09T23:24:00.033-03:002010-11-28T20:13:25.335-02:00Implementando Lightbox no Blogspot<div class="separator" style="margin: 0 auto; width: 370px;"><a class="lightbox" href="http://1.bp.blogspot.com/_4ttj6YxZQtQ/TGC5mQCdtgI/AAAAAAAABes/SzDagDjX7_I/s1600/lightbox.jpg" style="float: left;" title="Lightbox"><img height="120" src="http://1.bp.blogspot.com/_4ttj6YxZQtQ/TGC5mQCdtgI/AAAAAAAABes/SzDagDjX7_I/s200/lightbox.jpg" width="200" /></a><a class="lightbox" href="http://3.bp.blogspot.com/_4ttj6YxZQtQ/TO2neMCPaJI/AAAAAAAABiU/YHkh7HRp1OI/s1600/flickrwheel_0.jpg" imageanchor="1" style="float: left;"><img border="0" height="120" src="http://3.bp.blogspot.com/_4ttj6YxZQtQ/TO2neMCPaJI/AAAAAAAABiU/YHkh7HRp1OI/s200/flickrwheel_0.jpg" width="120" /></a></div><br />
<div style="clear: both;">Eu passei um trabalho pra colocar o lightbox do jeito que eu queria aqui no blog. Então vou tirar um pouco mais desse trabalho e vou ensinar como eu fiz isso. Porque no fim das contas ficou muito pratico.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"></div><a name='more'></a>O primeiro passo é incluir um gadget de HTML/Javascript. Você faz isso na aba design, elementos da pagina no painel do seu blog. La você vai incluir um novo gadget do tipo HTML/Javascript e vai colar o seguinte scrip dentro.<br />
<br />
<div class="syntaxhighlightercontainer"><pre class="brush:js html-script: true"><script src="http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojo/dojo.xd.js" type="text/javascript"></script>
<style type="text/css">
@import "http://ajax.googleapis.com/ajax/libs/dojo/1.5/dijit/themes/tundra/tundra.css";
@import "http://ajax.googleapis.com/ajax/libs/dojo/1.5/dojox/image/resources/Lightbox.css";
</style>
<script type="text/javascript">
dojo.require("dojox.image.Lightbox");
var dialog;
dojo.query('body')[0].setAttribute('class', 'tundra');
dojo.addOnLoad(function() {
dialog = new dojox.image.LightboxDialog({});
dialog.startup();
var images = dojo.query('.lightbox');
for(var i = 0; i < images.length; i++) {
if(typeof(parseInt(i)) == 'number') {
dojo.connect(images[i], 'onclick', images[i], function(event) {
dialog.show({ title:this.title, href:this.href });
event.stopPropagation();
event.preventDefault();
});
}
}
});
</script></pre></div><i>Edit: Eu criei uma versão bem mais elegante que agrega a feature de grupos de imagens no script. Tem um link pro fonte em um dos meus comment, la em baixo!</i><br />
<br />
Lembre de deixar o título do gadget em branco.<br />
Feito! Agora é só incluir a class lightbox no link das imagens nos seus posts. Algum trabalho você tinha que ter né =). Da pra por um título no link pra exibir em baixo da imagem quando o lightbox abrir.<br />
<br />
<div class="syntaxhighlightercontainer"><pre class="brush:js html-script: true"><a class="lightbox" title="Lightbox" href="http://1.bp.blogspot.com/_4ttj6YxZQtQ/TGC5mQCdtgI/AAAAAAAABes/SzDagDjX7_I/s1600/lightbox.jpg">
<img src="http://1.bp.blogspot.com/_4ttj6YxZQtQ/TGC5mQCdtgI/AAAAAAAABes/SzDagDjX7_I/s320/lightbox.jpg">
</a>
</pre></div>Eu optei por dojo, caso você pergunte, pois ele não depende de nenhum plugin pra fazer todo o serviço. Eu cheguei a testar com o jquery mas não existe CDN pros plugins. E CDN é ótimo para os pé rapados como eu que não tem seu próprio servidor pra hospedar os js.</div>Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com0tag:blogger.com,1999:blog-942231256726669006.post-56028992404753110212010-08-08T21:24:00.007-03:002010-08-08T21:53:12.911-03:00Identificando recursos do Browser<div class="separator" style="clear: both; text-align: center;"><img border="0" src="http://1.bp.blogspot.com/_4ttj6YxZQtQ/TF9QLF8TynI/AAAAAAAABeU/G7OIAa-90wI/s320/browser-producers.jpg" /></div><p>A algum tempo eu postei sobre uma classe para identificar o tipo de browser do cliente. Nas minhas andanças pelo <a href="http://php.net/">manual do php</a> eu encontrei algo que pode tornar tornar aquela ferramenta muito mais simples e robusta e que diria que o php já tinha funções in build tão bacanas e tão pouco conhecidas.</p><a name='more'></a><p>A função mágica é a <a href="http://php.net/manual/en/function.get-browser.php">get_browser</a>. Mas o que ela faz não tem nada de mágico. A função é simples, você passa pra ela o user agent e ela te retorna o array com os parâmetros.<br />
Tá, mas isso com uns substr eu resolvo fácil você pode pensar. Mas talvez leve algum tempo pra você descobrir o que significa cada número em<i> Mozilla/5.0 (Windows; U; Windows NT 6.1; pt-BR; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9</i>. o get_browser tem a vantagem do conhecimento agregado de como extrair do user agent por exemplo se o browser roda js ou se ele é um browser wap.</p><code><br />
[browser_name_regex] => ^mozilla/5\.0 (windows; .; windows nt 5\.1; .*rv:.*) gecko/.* firefox/0\.9.*$<br />
[browser_name_pattern] => Mozilla/5.0 (Windows; ?; Windows NT 5.1; *rv:*) Gecko/* Firefox/0.9*<br />
[parent] => Firefox 0.9<br />
[platform] => WinXP<br />
[browser] => Firefox<br />
[version] => 0.9<br />
[majorver] => 0<br />
[minorver] => 9<br />
[cssversion] => 2<br />
[frames] => 1<br />
[iframes] => 1<br />
[tables] => 1<br />
[cookies] => 1<br />
[backgroundsounds] =><br />
[vbscript] =><br />
[javascript] => 1<br />
[javaapplets] => 1<br />
[activexcontrols] =><br />
[cdf] =><br />
[aol] =><br />
[beta] => 1<br />
[win16] =><br />
[crawler] =><br />
[stripper] =><br />
[wap] =><br />
[netclr] =></code><br />
<p>Bom, tá ai o array de retorno da função, é interessante lembrar dessa função, ela pode ser bem desejada em uma boa aplicação.</p>Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com0tag:blogger.com,1999:blog-942231256726669006.post-54130328101591707412010-08-05T23:07:00.007-03:002010-08-08T21:39:22.916-03:00Zend Certified Engineer<div class="separator" style="clear: both; text-align: center;"><a class="lightbox" href="http://4.bp.blogspot.com/_4ttj6YxZQtQ/TF8ilp6g-sI/AAAAAAAABeM/rHv8vDuPD1w/s1600/zce+scritp.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" dojotype="dojox.image.Lightbox" src="http://4.bp.blogspot.com/_4ttj6YxZQtQ/TF8ilp6g-sI/AAAAAAAABeM/rHv8vDuPD1w/s320/zce+scritp.png" /></a></div><br />
<p>Algum tempo sem postar aqui, mas era por uma boa causa, tenho tentado dar um gás na minha faculdade que junto com o trabalho acaba ocupando todo meu tempo. Bem, quase todo... Nas férias de inverno ainda deu tempo pra correr atrás deste que já era meu desejo a algum tempo.</p><a name='more'></a><p>Zend Certified Enginner, o que eu posso dizer. Tendo como base as provas de pratica que você pode adquirir com o voucher de certificação a prova pode ser considerada bem difícil. Eu acabei comprimido meu tempo livre para estudar todas as noites e todos os fins de semana durante 3 semanas para me sentir pronto para a prova. Na real eu nem posso falar nada da prova, pois tem o contrato la e tal. Mas tá ai.</p><p>O guia de estudos da certificação não é todo o conteúdo que você precisa saber para ir bem. Ele é realmente um guia. Por exemplo, o guia aponta que existem 11 métodos de ordenação de array. Mas digamos que você na verdade deve conhecer cada um deles e saber algumas pegadinhas comuns de cada um.</p><p>O guia é um ótimo teste "eu estou pronto?" para a certificação. Ele é em inglês, e pressuporem que você já programa PHP a algum tempo. Se o texto for muito alienígena para você, talvez você deveria adquirir mais pratica antes de tentar o exam.</p><p>Mas também não é nenhum absurdo. Com força de vontade e dedicação pode ser até fácil.</p><p>Então é isso, espero que tenham curtido minha classe de certificações e espero que logo eu venha a postar novidades e certificações novas o/</p>Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com3tag:blogger.com,1999:blog-942231256726669006.post-16856544909168707912010-04-27T01:15:00.007-03:002010-08-08T21:37:06.130-03:00Trocando a Abordagem de prendizagem<div class="separator" style="clear: both; text-align: center;"><a class="lightbox" href="http://2.bp.blogspot.com/_4ttj6YxZQtQ/S9ZkGbRoOfI/AAAAAAAABao/E-rEUDI7eQE/s1600/Deep_Sea_Wallpaper_by_orangeillini14.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/_4ttj6YxZQtQ/S9ZkGbRoOfI/AAAAAAAABao/E-rEUDI7eQE/s320/Deep_Sea_Wallpaper_by_orangeillini14.jpg" /></a></div><br />
<p>Optar por uma metodologia de aprendizagem mais profunda, indo indo atrás de mais detalhes dentro da mesma fonte, foi o que eu decidi pra mim, mas talvez você prefira uma abordagem diferente e já cansou de ouvir falar do <a href="http://cesarscur.blogspot.com/2010/04/mobile-design-development.html">Brian</a>. Então aqui estão algumas alternativas de fontes de dados que eu conheço e que podem ter bons frutos mas eu apenas não tive tempo suficiente de ler e trazer para cá os conteúdos e links interessantes.</p><a name='more'></a><p>Começando com o <a href="http://mobiforge.com/book/export/html/293">ebook no Mobiforge</a> que apresenta similaridades preocupastes com o livro que venho citando a algum tempo. Não sei se um copio do outro e não sei se isso é um sinal de credibilidade ou não. Mas é uma alternativa com o mesmo tema (e as mesma imagens e os mesmo títulos e os mesmo ...)</p><p>O próprio site <a href="http://mobiforge.com/">Mobiforge.com</a> se intitula como "the world's largest independent mobile development community" e aparenta ser digno de credibilidade. Talvez venha a ser uma ótima fonte. Porém, não é uma comunidade focada em <i>web</i>, o que pode atrapalhar um pouco.</p><p><a href="http://patterns.littlespringsdesign.com/">Design for Mobile</a> é um site que tem problemas com url rewrite e usa um wiki pra gerenciar o conteúdo. Talvez ele tenha um conteúdo bem interessante eu só ainda não encontrei. Talvez você tenha mais sorte e paciência. Ah, eu acho que eu vi algo desse site no livro... talvez....<br />
Bom, essas são algumas das referencias que eu esbarro por ai, e umas vão levando as outras. Eu vou continuar tentando esgotar o livro e então darei minha atenção plena a essas outras fontes. Porem não vou parar de buscar outras referencias e materiais legais. </p><p><span style="font-size: x-small;">Obs.: E caso você esteja se perguntando sobre a imagem, era para ser uma referencia para profundidade =D</span></p>Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com0tag:blogger.com,1999:blog-942231256726669006.post-26991737143849241972010-04-26T18:08:00.003-03:002010-09-02T13:06:04.600-03:00Tamando Disponivel da Tela<div class="separator" style="clear: both; text-align: center;"><a class="lightbox" href="http://4.bp.blogspot.com/_4ttj6YxZQtQ/S9X5kog-W-I/AAAAAAAABaY/do3vrqGzI_U/s1600/sreen+sizes.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/_4ttj6YxZQtQ/S9X5kog-W-I/AAAAAAAABaY/do3vrqGzI_U/s320/sreen+sizes.jpg" /></a></div>Eu sei que esse era o gráfico que você estava procurando pra responder todas as suas perguntas sobre o tamanho máximo que o seu aplicativo ou site deveriam ter. Mas a resposta não esta ai pronta nesse gráfico. Na verdade a resposta depende muito mais de você do que, talvez, você possa imaginar. <br />
<a name='more'></a>Assim como mostra a imagem, existe uma variedade muito grande de tamanhos de tela entre os aparelhos. Não é tão simples quando escolher o tamanho indicado pela linha pontilhada sempre, uma vez que fazendo isso dois tamanhos de tela ficariam inviáveis no seu layout.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/_4ttj6YxZQtQ/S9YDev0FASI/AAAAAAAABag/iQH1RxYJzmo/s1600/screen+sizeee.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/_4ttj6YxZQtQ/S9YDev0FASI/AAAAAAAABag/iQH1RxYJzmo/s320/screen+sizeee.jpg" /></a></div><div style="text-align: center;"> (Update)</div><div style="text-align: center;">Aqui estão alguns exemplos de tamanhos de tela de alguns aparelhos:</div><p>A resposta correta para o tamanho a ser usado é um duro jogo entre a qualidade da experiência do usuário e a quantidade de dispositivos suportados. Esse é um jogo difícil de ser jogado e depende muito mais da estratégia do seu negocio do que qualquer outra coisa.</p><p>Para entender melhor esse jogo eu recomendo fortemente que você leia o livro do <a href="http://cesarscur.blogspot.com/2010/04/mobile-design-development.html">Brian Fling</a>, ele é muito esclarecedor nesse ponto e foi de onde saiu a imagem (<a href="http://www.tineye.com/search/c1bea1d045c075e66a946dfad21f913114e070c7">ou não</a>).</p><p>Escolher o tamanho correto da tela e a orientação (horizontal / vertical) não resolve muita coisa no seu projeto, acredite, mas é um bom ponto de partida para por a mão na massa. Desenvolver aplicações web para celular é bem diferente de desenvolver para desktop. No meu próximo post tentarei abordaras questões de layout e distinções de layout para desktop e moveis.</p><br />
[<a href="http://www.mobiledesign.org/">Mobile Design & Development</a>]Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com0tag:blogger.com,1999:blog-942231256726669006.post-39008116297100294132010-04-22T12:05:00.002-03:002010-04-22T15:23:55.168-03:00Beneficios Únicos dos Dispositivos Moveis<div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/_4ttj6YxZQtQ/S9Bz7B_-YRI/AAAAAAAABYc/fqzGS2S-jOk/s1600/7%C2%AA+midia+de+massa.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/_4ttj6YxZQtQ/S9Bz7B_-YRI/AAAAAAAABYc/fqzGS2S-jOk/s320/7%C2%AA+midia+de+massa.jpg" /></a></div><br />
<br />
Como eu prometi, a medida que iria lendo o livro do Brian Fling, <i>Mobile Design and Development</i>, aqui estão os motivos pelos quais os dispositivos moveis superam todas as outras mídias de massa.<br />
<br />
"Como se não fosse o bastante que celular pudesse fazer tudo o que os outros meios de comunicação podem fazer, Tomi Ahonen aponta que os móveis tem cinco benefícios exclusivos que nenhum dos outros tem:<span class="long_text" id="result_box"><span onmouseout="this.style.backgroundColor='#fff'" onmouseover="this.style.backgroundColor='#ebeff9'" style="background-color: white;" title="Ahonen points out, mobile has five unique benefits that none of the others do:*"><br />
</span><span onmouseout="this.style.backgroundColor='#fff'" onmouseover="this.style.backgroundColor='#ebeff9'" style="background-color: white;" title="“The first truly personal mass media”"><span style="font-size: large;"><i></i></span></span></span><br />
<a name='more'></a><br />
<span style="font-size: large;">A primeira mídia de massa verdadeiramente pessoal</span><br />
Por exemplo, nós geralmente não partilhamos os nossos dispositivos móveis com nossos cônjuges. Cada um dos os outros meios de comunicação são ou podem ser facilmente compartilhados, mesmo computador pode ser compartilhado em casa ou no trabalho. Os dispositivos móveis nos oferecer, pela primeira vez, um meio de interação com informações de uma maneira pessoal e íntima. <br />
<br />
<span style="font-size: large;">A primeira mídia de massa sempre ligada</span><br />
Muitos não percebem que os dispositivos móveis têm a capacidade de enviar e receber informações em todos os momentos, mesmo quando ocioso. A menos que seja desligado, o seu dispositivo móvel está conectado à rede. Embora possa soar meio Big Brother, este pode ser um enorme benefício para o usuário normal, permitindo o dispositivo prever as tarefas com base na sua localização e antecipar a informação que você precisa com base em seu posicionamento. <br />
<br />
<span style="font-size: large;">A primeira mídia de massa sempre conosco</span><br />
Quantos outros meios de comunicação você pode contar que levamos conosco em todos os tempos? Sete em cada dez pessoas dormem com seus telefones ao alcance das mãos. Um colega meu, fazendo uma pesquisa com usuários sobre como as pessoas usam dispositivos móveis, descobriu o lugar em nossos lares que mais freqüentemente usamos dispositivos móveis é no banheiro. Talvez precisemos nos separar de nossos telefones um pouco mais! <br />
<br />
<span style="font-size: large;">A única mídia de massa com um canal de pagamento embutido</span><br />
Cada telefone vendidos a partir de um operadoras tem um meio embutido de realizar compra de conteúdo, até bens e serviços conhecidos pela sigla engraçada de Bobo, "Billing on Behalf of" (Faturamento em favor de). Você paga por ele e é cobrado na sua conta de telefone. Quando você leva em conta a estatística que o numero de pessoas têm telefones é o dobro das que tem cartões de crédito, de repente, o potencial parece enorme. <br />
<br />
<span style="font-size: large;">No ponto para um impulso criativo </span><br />
Somos capazes de criar conteúdo e distribuí-lo no momento que da vontade. De tirar uma foto de algo interessante e fazer o upload para as redes sociais a fim de compartilhá-lo com nossos amigos para capturar um vídeo de um evento importante e partilhar uma experiência, os dispositivos móveis permitem-nos criar e publicar quase em tempo real. Informações e experiências podem agora ser partilhadas com o público ao redor do mundo a medida que elas acontecem e de múltiplos pontos de vista. É simplesmente diferente de qualquer outro meio que já vimos antes."<br />
<br />
<br />
[<a href="http://communities-dominate.blogs.com/brands/2007/02/mobile_the_7th_.html">Communities Dominate</a> via <a href="http://www.mobiledesign.org/">Mobile Design and Development</a>]Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com0tag:blogger.com,1999:blog-942231256726669006.post-40289571809969218382010-04-14T16:34:00.001-03:002010-04-16T15:48:18.214-03:00Nova cara do Jornal NH<div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/_4ttj6YxZQtQ/S8YUurZL66I/AAAAAAAABXs/ttqMHW6NCIQ/s1600/capa+nh.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://2.bp.blogspot.com/_4ttj6YxZQtQ/S8YUurZL66I/AAAAAAAABXs/ttqMHW6NCIQ/s320/capa+nh.jpg" width="233" /></a></div>Somente ontem eu notei que o jornal aqui da região tinha mudado a aparência do seu logotipo e o layout do jornal. Mas o que mais me surpreendeu não foi a nova capa, mas sim a nova contra-capa.<br />
<a name='more'></a><br />
Junto das mudanças de layout e logotipo um novo recurso foi adicionado na contra-capa do impresso. Sim, um QR Code que aponta para o site <a href="http://www.jornalnh.mobi/">www.jornalnh.mobi</a>. Escolha estranha para o link. É mais comum vermos <a href="http://m.gmail.com/">m.gmail.com</a>.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/_4ttj6YxZQtQ/S8YV-9fnXKI/AAAAAAAABX0/fEKO4Ji3bMg/s1600/contra+capa+nh.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="172" src="http://3.bp.blogspot.com/_4ttj6YxZQtQ/S8YV-9fnXKI/AAAAAAAABX0/fEKO4Ji3bMg/s320/contra+capa+nh.jpg" width="320" /></a></div><br />
Eu tenho que admitir que não esperava ver esse tipo de coisa tão cedo, se espalhando por todas as partes. Isso da uma impressão muito forte que as coisas vão mudar mais rápido do que as pessoas realmente conseguem assimilar e me deixa um pouco tonto até de pensar.<br />
<br />
Devaneios a parte, o link é um site, obviamente, para a 7ª midia em massa e tem as principais noticias do dia, inclusive a previsão do tempo para o dia, esportes, cinema e variedades.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"></div><div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/_4ttj6YxZQtQ/S8YXp5YCa2I/AAAAAAAABYE/EeC56kstZtU/s1600/qr+code+close.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/_4ttj6YxZQtQ/S8YXp5YCa2I/AAAAAAAABYE/EeC56kstZtU/s320/qr+code+close.jpg" /></a></div><br />
O mais interessante é que o site é desenvolvido em asp. Sim, o bom (ou nem tanto) e velho (bastante) ASP (notem a ausência do .net). Da pra ver até um erro rolando no link do cinema.Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com0tag:blogger.com,1999:blog-942231256726669006.post-59870485036315242332010-04-12T17:07:00.000-03:002010-04-12T17:09:36.301-03:00Mobile Design & Development<div class="separator" style="clear: both; text-align: center;"><a href="http://mobiledesign.org/images/book/book.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://mobiledesign.org/images/book/book.png" width="257" /></a></div><br />
Eu estava procurando por material para escrever sobre layout e design de interfaces quando esbarrei nesse livro. Já li as primeiras 40 paginas e dei uma olhada nas outras.<br />
O livro oferece um panorama bem amplo e proporciona um contexto historio da faze que os telefones se encontram hoje. Ele é um pouco tendencioso pela Apple, mas tudo bem.<br />
<br />
<a name='more'></a><br />
<br />
Mais adiante no livro eu vi, durante uma das espiadas que eu dei, que ele aprofunda dois temas diferentes de maneira bem satisfatória. Design e desenvolvimento estão bem detalhados. Acredito que deve agradar interessados de ambas as áreas.<br />
<br />
Contudo, é um livro em inglês. Ele esta disponível para compra na <a href="http://www.amazon.com/gp/product/0596155441?ie=UTF8&tag=flingmedia-20&linkCode=as2&camp=1789&creative=390957&creativeASIN=0596155441">amazon.com</a>, e tem um <a href="http://www.mobiledesign.org/">site próprio</a> que parece que vai (ou iria) ganhar algum conteúdo em breve. O peço não é caro, nem barato, mas nós sabemos que você pode conseguir a sua copia de outras maneiras.<br />
<br />
Quando eu terminar de ler posto algum conhecimento interesante que aprendi nele.Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com0tag:blogger.com,1999:blog-942231256726669006.post-63055679715385038092010-04-12T14:46:00.000-03:002010-04-12T17:09:22.003-03:00Identificando o dispositivo do cliente<div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/_4ttj6YxZQtQ/S8NV4xNvHzI/AAAAAAAABXI/wkG-VcEIqvU/s1600/php+code.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/_4ttj6YxZQtQ/S8NV4xNvHzI/AAAAAAAABXI/wkG-VcEIqvU/s320/php+code.jpg" /></a></div><br />
Bom, talvez não seja tão difícil identificar um dispositivo móvel acessando seu site. Desde que você use a classe IsMobile.<br />
<br />
<a name='more'></a>Entrei em contato com o pessoal da <a href="http://www.phpmobile.com.br/">phpmobile.com.br</a>, e eles foram gentis em me ceder o direito de publicar o a classe desenvolvida por eles nesse neste blog.<br />
<br />
Então, a classe IsMobile se dedica a identificas se o dispositivo acessando o site é um dispositivo movel com base no user agent do browser do dispositivo.Existem exemplos de como utilizar a ferramenta <a href="http://www.phpmobile.com.br/2010/01/23/como-utilizar-versao-0-2da-classe-ismobile/">nesse link</a>, assim como o link para download.<br />
<br />
Se você não desenvolve em php não tem problema, o código está bem estruturado e você não vais ter dificuldade em pegar a essência e reescrever o código em Java, Ruby ou na sua linguagem predileta.<br />
<br />
Porém, nem todos os problemas do mundo são resolvidos por essa ferramenta. A resolução de tela e a capacidade de processamento para java script pode variar muito de um aparelho para o outro. (tremenda falta de consideração com os programadores, por parte dos desenvolvedores dos mini browser. Essa informação poderia estar no user agent de maneira clara)<br />
<br />
Mas tá ai um ótimo ponto de partida para descobrir a solução para as outras incógnitas do mundo web.Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com0tag:blogger.com,1999:blog-942231256726669006.post-60257450806323592932010-04-09T17:26:00.003-03:002010-04-09T17:35:24.534-03:00QR Codes<div class="separator" style="clear: both; text-align: center;"></div><style>
<!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;
mso-font-charset:1;
mso-generic-font-family:roman;
mso-font-format:other;
mso-font-pitch:variable;
mso-font-signature:0 0 0 0 0 0;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;
mso-font-charset:0;
mso-generic-font-family:swiss;
mso-font-pitch:variable;
mso-font-signature:-520092929 1073786111 9 0 415 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-unhide:no;
mso-style-qformat:yes;
mso-style-parent:"";
margin-top:0cm;
margin-right:0cm;
margin-bottom:10.0pt;
margin-left:0cm;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-fareast-font-family:Calibri;
mso-fareast-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;
mso-fareast-language:EN-US;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
mso-themecolor:hyperlink;
text-decoration:underline;
text-underline:single;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-noshow:yes;
mso-style-priority:99;
color:purple;
mso-themecolor:followedhyperlink;
text-decoration:underline;
text-underline:single;}
.MsoChpDefault
{mso-style-type:export-only;
mso-default-props:yes;
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-fareast-font-family:Calibri;
mso-fareast-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;
mso-fareast-language:EN-US;}
.MsoPapDefault
{mso-style-type:export-only;
margin-bottom:10.0pt;
line-height:115%;}
@page Section1
{size:595.3pt 841.9pt;
margin:70.85pt 3.0cm 70.85pt 3.0cm;
mso-header-margin:35.4pt;
mso-footer-margin:35.4pt;
mso-paper-source:0;}
div.Section1
{page:Section1;}
-->
</style> <br />
<div class="MsoNormal"><div class="separator" style="clear: both; text-align: center;"><a href="http://chart.apis.google.com/chart?chs=200x200&cht=qr&chl=http://cesarscur.blogspot.com/&chld=L%7C1&choe=UTF-8" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://chart.apis.google.com/chart?chs=200x200&cht=qr&chl=http://cesarscur.blogspot.com/&chld=L%7C1&choe=UTF-8" /></a></div><br />
Códigos de barras podem parecer coisas antiquadas quando se tem um aparelho tão moderno quanto um smartphone. Mas na verdade esses códigos bidimensionais podem ser muito engenhoso e pra mim podem ser um pedacinho do futuro de copiar e colar.</div><div class="MsoNormal"></div><a name='more'></a><br />
<div class="MsoNormal">Imagine que você esta acessando um site no seu computador sobre um app para Android muito bacana. Você teria que digitar o endereço do site do app no celular para fazer o download no seu telefone. Mas com o QR Code você aponta a câmera do seu smartphone para a tela do PC e o site do app abre como mágica na tela do seu telefone. Isso funciona mais ou menos como no video desse app para android que lê códigos de barra (<a href="http://www.androidtapp.com/barcode-scanner/">barcode scanner</a>).</div><div class="MsoNormal" style="text-align: center;"><object height="344" width="425"><param name="movie" value="http://www.youtube.com/v/uIww6TA5f58&hl=pt_BR&fs=1&rel=0"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/uIww6TA5f58&hl=pt_BR&fs=1&rel=0" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object></div><div class="MsoNormal"></div><div class="MsoNormal" style="text-align: center;"><br />
</div><div class="MsoNormal" style="text-align: left;">Códigos QR são capazes de armazenar quantidades imensas de dados e não mais os 13 dígitos numéricos dos códigos de barras dos produtos do supermercado. QR Code foi especificamente desenvolvido para ser lido por câmeras VGA (como as dos 1ºs celulares) no Japão e por lá eles já tem uma centena de aplicações, umas até meio bizarras<span style="font-size: x-small;">.</span></div><div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/_4ttj6YxZQtQ/S7-EdyRf3oI/AAAAAAAABXA/860pUUUwgGk/s1600/kuyouno-mado.thumbnail.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="http://4.bp.blogspot.com/_4ttj6YxZQtQ/S7-EdyRf3oI/AAAAAAAABXA/860pUUUwgGk/s320/kuyouno-mado.thumbnail.JPG" width="240" /></a></div><div class="MsoNormal" style="text-align: center;"><span style="font-size: x-small;">(lapide usando QR Code para dar mais detalhes do falecido)</span> </div><div class="MsoNormal">Mas a parte mais interessante é: como eu crio os meus próprios códigos de barras bidimensionais? OK, umas das maneiras é usar um desses <a href="http://www.google.com.br/search?q=QR+Code+Generator&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:pt-BR:official&client=firefox-a">geradores de código QR</a> paraum codigo estatico para um link ou qualquer outra coisa que sua imaginação permitir.</div>A outra é usar essa API do Google que é usada pra gerar gráficos para criar os seus códigos dinamicamente. A API é bem simples da pra entender a funcionalidade no site <a href="http://code.google.com/intl/pt-BR/apis/chart/docs/gallery/qr_codes.html">Google Chart QR Code</a>. A aplicação a API é como o usado na imagem no inicio do post, algo em html do tipo:<br />
<br />
<span style="color: #073763;"><img border="0" src="http://chart.apis.google.com/chart?chs=200x200&cht=qr&chl=http://cesarscur.blogspot.com/&chld=L%7C1&choe=UTF-8" /></span><br />
<br />
<span style="color: black;">Onde o parametro </span><span style="color: #073763;"><span style="color: black;"><i>chl </i>da url é o conteudo (dado contido) no QR Code.</span></span><br />
<br />
Para quem achar interesante, no site da <a href="http://en.wikipedia.org/wiki/QR_Code">wikipedia</a> tem mais detalhes historicos e o link para para a desenvolvedora e toda a documentação do padrão.<span style="color: #073763;"><br />
</span>Cesar Scurhttp://www.blogger.com/profile/17024782792452008567noreply@blogger.com0