Home

Advertisement

Customize

Mar. 13th, 2009

Open X Ad Server

One of the problems I was facing with Open X as an ad server was to be able to load a flash file inside a flash file...
Ok that sounded a bit confusing, I´ll clarify.

Let´s assume you have a flash site. You create two areas for publicity. All works great, until one day, you need to use an open ad server for doing that. Today, one of the best (I know of) is Open X.
Open X has one serious limitation (unless you get creative). It does not allow for data to be called from within a flash app.
Let´s go over the basic way of creating an ad space, then let´s try and find a solution for the problem.

Create a ZONE - a zone is nothing but an area of your page that will hold some kind of publicity. So let´s create a space of 150x150 on the top right of our page. Give that Zone a name such as 150x150_home_topRight. You can go more creative and call it "blueberries are better than bird poo", but I rekon the something closer to the first option will make more sense down the road.

Basically, in an HTML site, you´d add either a PHP script or a Javascript "script" that would identify this particular area as a Zone. The ad server does the rest. It will look for banners registered for that specific area, with filters and what not, then display those when you page is loaded.

The problem is there... you cannot add PHP or Javascript to your flash... so what do you do?

A simple work around I implemented was to cheat.


Create an area, and name it accordingly. Set it as a Text Ad.

Create a text banner for testing purposes... where the description is the name and full path of the SWF file you wish to load.

In general, open X has two methods of placing zones:
1) remote/javascript - used to place ads in external sites mainly
2) Local mode - using PHP to place the add on the page at render time.

For this application, use local mod - and get the invocation code which should be a PHP script

OK, so you have you PHP code.. but your site is in flash... what next? What´s so innovative?
Here comes the trick.

Create a new page on your site and call it zone1, or 150_150_home_tr or whatever makes sense to you...

Place the invocation code there.... test it. You should get a linked "name_of_swf_file_you_put_as_a_description" on the screen and that´s all.

So far so good... here comes the cheat.
I´ll post code for it tomorrow...

The content of the file is actually as follows:

Link - with click tag url
Text
HiddenDiv with invisible image

Use PHP ereg functions to extract the link and the text... add them as flash variables or a XML file, so that when you render your page you get either:

Flash Variables:
&CLKTAG=http://bla.bla.bla&swfFile=/swf/banner1.swf&image&imageURL=long_url

XML

http://bla.bla.bla
/swf/banner1.swf
long_url


Now you can use this to import the SWF file into you flash. Load the image into a hidden control (this will register views). Use the clickTag link in your loaded movie to register clicks.
There you go.. it´s not clean, far from being perfect... but it works.

Jan. 21st, 2009

Thinking about an API

APIs are in the spotlight for quite some time, no wonder actually, since they provide services that would be virutally impossible for the weekend developer to do. Take googleMaps or Twitter as examples. These are used in hundreds of sites, adding functionalities only dreamed of.
Working on a project myself, I have started to think about APIs and how I would go about producing one that would attend the public that visits my site. I will try and document my progress here as we go developing an API from scrach.

The first question
Will an API be usefull? Your site has a contact form that sends you an email... well then there is not much point in puting in all the effort to develop an API. What do I mean? Basically, if you provide no service, nothing that anybody else can use to their advantage, then what is really the point? The idea behind a public API is to allow users to build on top of your tools, to add functionality to their products by using a service you provide.

The second question
It has to be "WHY?". I mean, unless you know why you need an API, there is not much point in developing one. APIs can help spread the knowledge of your site a bit. People get to see, indirectly sometimes, your product in the miriad of sites available on the web, and you start to get known. Some people will try and use your tools in ways that you could have not conceived, giving you a new insight on your own business.

The third question
"What will I do?"
This will vary tremendously. Each project has specific features and limitations. You will have to work this out on your own. I have a video community, and I will be working on it over the course of this "API Brainstorm". Hopefully, you´ll get the ideas and port them to your own projects.
In the video site, some of the functionalities we´d like to implement are:
Playlists, in-line comments and friend sharing. There are a whole buch of other tools, but these will be the first ones we will think about.


Our platform
This will vary tremendously I know, and I will do my best to explain concepts as generically as I can before diving into realy life code.
Our site is being currently run on CodeIgniter with a MySQL backend. We are using quite a bit of client side jQuery which we intend to extend over to the API calls.

Well, as an intro, that´s that. I will start the next Post as we slowly progress in creating our very own, useful and user friendly API.

Oct. 29th, 2008

Codeigniter & cache

Codeigniter has a neat little caching feature that does basic caching of rendered pages. If you run a high load server this tends to be very helpful. Speeding up the delivery process by showing rendered HTML files reduces the overall load on your server, less DB hits, less processing power required to run scripts and so on. But, there are a few catches.
The inbuilt caching system will only work on views.
To make matters worse, it will render the first load of a page, after it expires, so if you have a site that has logged users, such as a "welcome back username", then this page will be stored as your home page. This does give the impression that the user is logged for all computers.

There are quite a few workarounds for this, and most of them involve using plugins or libraries for CI.
I have found that using these, can be helpful, but I still think that they lack some functionalities I´d like to have for my own site.
I am an old-timer, so I am pretty used to the caching model from Smarty, which served me well in a number of occasions. After ggling around the web a bit, I found this link:
http://devcha.blogspot.com/2007/12/smarty-as-template-engine-in-code.html
which shows you how to integrate Smarty into your CI install. It works like a charm (even though I have done very limmited testing on it so far.

If you are in love with CI like I am, but you still miss having Smarty, this might just be the solution for your problems. Thanks Marinov for the work!

Aug. 26th, 2008

CodeIgniter - A neat trick

This one came out of a small IRC brainstorm the other day and it turned out to be quite a useful tip for all you codeIgniter developers. I'll lay down the ground work for you and you can take it from there.



There are many ways of using views in CI. Some people like to call them directly in their controllers, others prefer to attribute them to variables and centralize them in a single layout file. I am kind of in the first category.

I actually got the habbit of adding a function such as _buildPage() or something like that in my controller that allows me to re-use most of the layout stuff with a minimum of coding.



A typical controller would look something like this...

class Home extends Controller {
 function _buildPage($content,$data){
   $this->load->view('header',$data);
   $this->load->view($content,$data);
   $this->load->view('footer',$data);
 }
 function index(){
   // ... all the code required by index
   // call the display
   $this->_buildPage('index',$data);
 }
 function listing(){
   // ... all the code required by listing
   // call the display
   $this->_buildPage('listing',$data);
 }



This is fine for most cenarios, but sometimes, you need more mobility... let's assume that you have 20 controllers, and that suddenly, you need to add a "publicity" layout just below the header, and that this publicity layout is directly related to the controller action you are calling...

There you go, editing 20 php files, making modifications... needless to say, a boring job.



Here comes the neat trick.

Instead of placing the _buildPage in the controller, extend the basic controller object for CI. Create you different layout calls there... here's a sample of an extending controller and a class using it:



in you application/libraries folder, add a "MY_controller.php" file.

It's contents should read something like this:



php
// we create a new MY_class that extends the basic Controller class;
// MY_ is the default prefix for classes that should extend/override CI classes (it can be
// customized in the config file.
class MY_Controller extends Controller {
	// this is my _buildPage function that loads a specific view with all the extra views I may need.
	function _buildPage($view="",$data){
		$this-load->view('header',$data);
		$this->load->view($view,$data);
		$this->load->view('footer',$data);
	}
}
?>



The same example above, using the new controller class:



class Home extends MY_Controller {
 function index(){
   // ... all the code required by index
   // call the display
   $this->_buildPage('index',$data);
 }
 function listing(){
   // ... all the code required by listing
   // call the display
   $this->_buildPage('listing',$data);
 }




With minor tweaks, you can easily control all sorts of layouts. The best of all, it's all central in a single file.


Jul. 12th, 2008

Ruby on Rails - Maior tutorial grátuito já promovido

Inicia agora, no dia 15 de julho 2008, a maior aula grátis de Ruby on Rails.
São mais de 850 alunos vendo aulas on-line. O curso parece ser bem abrangente, promete ser no mínimo interessante.
O curso é em inglês.
Quem tiver afim:
http://rubyindia.wordpress.com/2008/07/07/free-and-biggest-ruby-on-rails-tutorials-with-850-members-starts-soon/

Vou tentar fazer o curso. Vamos ver no que dá.

Twitter sem CURL


Recentemente tive que desenvolver um pequeno aplicativo que interage com o twitter. Obviamente, a minha primeira opção foi fazer uma busca pra ver o que já existia de pronto para facilitar meu trabalho.
Achei várias classes e mini-tutoriais pela web.
O desenvolvimento foi rápido e simples. Na minha máquina, tudo funcionou certinho. Subi o protótipo em meu servidor e "plaft", nada funcionava, mensagens de erro invadiram minha telinha.
O problema acontece porque estou em um servidor compartilhado, e consequentemente existe uma restrição na configuração do PHP na vairável "openbase_dir". Quando ela está setada, o CURL não pode abrir URLs externas.
Solicitar que fosse mudada a configuração foi a primeira tentativa, e diga-se de passagem ainda estou esperando uma posição do Host. A opção foi pesquisar um jeito de interagir com o Twitter sem o uso do CURL.

Sai CURL, entra fsock



Criar uma interação com o twitter requer basicamente mandar e receber dados de uma URL com autenticação. Assim, depois de alguma pesquisa cheguei a um modelinho que resolve o meu problema, e espero eu, ajude vocês a dar seus primeiros passos no mundo de interação com o Twitter.

Fiz uma "mini classe" que serve de exemplo básico. Com ela é possível mandar mensagem pro twitter e receber a lista autenticada de um usuário. Ela está bem básica, apenas para mostrar como interagir com o twitter sem o CURL. Estou trabalhando para implementar todas as funcionalidades da API do Twitter nesta classe e aviso vocês quando estiver pronta.

Vamos ao código:



<?php
class TwitterAPI{
var $userName = "";
var $password = "";
function __construct(){

}
/*
* Faz Conversa
* Deveria ser privada, mas agora ajuda no desenvolvimento
* @var method - endereco da pagina na API
* @var userName - nome do usuario a ser autenticado
* @var password - senha do usuario
*/
function fazConversaGET($method, $userName='', $password=''){
$response="";
if ($userName=='' || $password==''){
$userName = $this->userName;
$password = $this->password;
}
$fp = fsockopen("twitter.com", 80, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
$out = "GET $method HTTP/1.1\r\n";
$out .= "Host: twitter.com\r\n";
$out .= "Authorization: Basic ".base64_encode ($userName.':'.$password)."\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp)) {
$response.= fgets($fp, 128);
}
fclose($fp);
}
return $response;
}
/*
* Buscar lista do usuario e amigos (autenticada)
* e retornar um objeto SimpleXML
*/
function getFriendList($userName='', $password='',$page=1){
// checa pra ver se foi setado um nome e usuario manualmente
// senao pega do objeto
if ($userName=='' || $password==''){
$userName = $this->userName;
$password = $this->password;
}
// API do twitter pede pra não exceder numero de paginas
// poderia ser usado o COUNT ao inves de page, mas se vc ler a DOC,
// eles pedem para usar o PAGE
if ($page>10)
$page = 10;

// BUSCA O XML
$response = $this->fazConversaGET('http://twitter.com/statuses/friends_timeline.xml?page='.$page,$userName,$password);

// O XML VEM COM RESPOSTAS DE HEADER - EU ACHO ONDE O XML INICIA E ARRANCO OS HEADERS
// DEVERIA TRATAR ISSO DEPOIS
$x = strpos($response,"<?xml");
if ($x>0){
$response = substr($response,$x);
if(class_exists('SimpleXMLElement')){
return new SimpleXMLElement($response);
}else{
return $response;
}
}else{
return false;
}
}
/*
* ENVIAR MENSAGEM PARA LISTA AUTENTICADA
*/
function sendMessage($userName='', $password='',$msg=''){
// ENCODA A MENSAGEM PRA APARECER CERTINHO
// DEVERIA TER MENOS NO MAX 140 CARACTERES
$msg = urlencode($msg);
$response="";
// NOTE QUE AQUI FAZEMOS UM POST
$out="POST http://twitter.com/statuses/update.json HTTP/1.1\r\n"
."Host: twitter.com\r\n"
."Authorization: Basic ".base64_encode ($userName.':'.$password)."\r\n"
."Content-type: application/x-www-form-urlencoded\r\n"
."Content-length: ".strlen ("status=$msg")."\r\n"
."Connection: Close\r\n\r\n"
."status=$msg";

$fp = fsockopen ('twitter.com', 80);
fwrite ($fp, $out);
while (!feof($fp)) {
$response.= fgets($fp, 128);
}
fclose ($fp);
return $response;
}
}

// EXEMPLO DE UTILIZAÇÃO DA CLASSE

// CRIA NOVO OBJETO
$tw = new TwitterAPI();

// BUSCA A PAGINA 1 EM XML DA SUA LISTA DE AMIGOS
$res = $tw-> getFriendList('SEU USUARIO', 'SUA SENHA');
echo "<pre> PAGINA 1: <BR>";
print_r($res);
echo "</pre>";

// BUSCA A PAGINA 2 EM XML DA SUA LISTA DE AMIGOS
$res = $tw-> getFriendList('SEU USUARIO', 'SUA SENHA', 2);
echo "<pre> PAGINA 2: <BR>";
print_r($res);
echo "</pre>";

// MANDA MENSAGEM AUTENTICADA COM SEU USUARIO
$res = $tw->sendMessage('SEU USUARIO','SUA SENHA','Isso veio de um PHP sem o CURL');
echo "<pre> PAGINA 2: <BR>";
print_r($res);
echo "</pre>";
?>




Jul. 8th, 2008

O Futuro do flash é C?

Pode soar estranho, mas um projeto velho de 2006 sob o codinome Tamarin está levando pessoas a crer que o futuro do flash pode estar no C e C++.
Para os mais apresados: o Tamarin permite rodar programas em C e C++ dentro do flash (por exemplo). Um dos showcases da tecnologia foi uma apresentação do Quake rodando dentro do Flash.
Além dos joguinhos, o Tamarin também permite que aplicativos que utilizem javascript pesado a rodar mais rápido, assim, um ganho de performance pesado para coisas como Ajax que dependem pesadamente em JS.
Quem quiser uma explicação mais detalhada:

http://www.toolness.com/wp/?p=52

e o Post lá de 2006 também encontrado no Post acmia:
http://hecker.org/mozilla/adobe-mozilla-and-tamarin

All around Google

Estou estudando algumas aplicações com o GoogleMaps. Nada muito rebuscado ou complicado. Pensei em fazer algumas coisas do tipo, lugares legais para se ir. Localização de restaurantes, bares, etc..
Coisa simples, um sisteminha besta de votação do pico. Serviços de utilidade publica mesmo. Só um brinquedo para testar a integração do Google aqui em Sampa e quem sabe no resto do Brasilzão.

Fui lá, criei minha API_KEY, fiz tudo como manda o "Manuel" e boas... tinha meu primeiro mapinha rodando sem crise, abrindo lá no meio dos EUA.
Primeira modificação... vamos abrir ele em Sampa. Consulta de CEP? Será que funciona? Fui lá, coloquei uma funçãozinha que usa o GeoCoder da Google, taquei um CEP, "XXXXX-XXX - São Paulo - SP", e boas... lá estava meu CEPzinho bonitinho. O mapa da minha região.

Brincando, se eu gastei mais do que 3 minutos fazendo isso foi muito. Foram uns 4 copy&pates da vida e boas, já tava funcionando lá.
Comecei a pesquisar mais um pouco, fiz questão de ver se já não tinha algo semi-pronto de colocar localidades no mapa, e presto! achei um link:

http://code.google.com/apis/maps/articles/communitymap.html

Bom, o curioso deste link é que ele explica como fazer exatamente o que eu quero fazer, porém, ao invés de usar um banco de dados, ele ensina a fazer isso usando o GoogleDocs - uma planilha do google docs para ser mais específico. O artigo é bem interessante. Ele usa o Zend Framework, e assim, não me serviu muito, mas me fez pensar em qual será o próximo grande brinquedo da Google? Será que logo eles vão fazer um GoogleDataBase? Onde você pode usar um banco hospedado na google?

Brincadeiras a parte... quando eu acertar a mão nesse lance de GoogleMaps eu faço um "hands on" pra vocês poderem sair brincando também.

Jul. 5th, 2008

Smarty e Caching - Parte 4

Até agora temos visto como funciona a parte de caching do Smarty com exemplos que parecem vir da documentação(muitos na verdade são bem parecidos). Ainda existem mais algumas coisas que não são tão obvias assim para se se estudar. Esse pedaço final do artigo visa explicar essas.

Se você navegar até os outros artigos, perceberá que até o momento trabalhamos somente com um template (arquivo.tpl). Uma das propriedades mais interessantes do cache do Smarty é a capacidade dele trabalhar de forma independente com vários arquivos.

Vamos voltar um pouco ao Smarty para ter certeza de que entendemos o que eu acabei de dizer:

O Smarty gerencia templates, assim, você pode separar seu template em blocos. Vamos dizer que você tenha a seguinte estrutura:

Cabeçalho, menu da esquerda, chamada de artigos, chamada de eventos, rodapé.

Embora sua página seja uma só, você pode monta-la a partir de vários bloquinhos no Smarty.

Você teria arquivos como:

cabecalho.tpl, menu.tpl, chamadaArtigos.tpl, chamadaEventos.tpl e rodapé.tpl.

Note que não estamos usando um index.tpl neste exemplo. Muita gente iria criar um index.tpl e incluir as diretrizes de include nele. No nosso caso todos controles de exibição são feitos no index.php usando o metodo display().

Voltando ao caching, como já deve ser imaginável, se você está controlando o display de cada área, você também pode controlar o cache de cada área de forma independente. Por exemplo, o cabecalho.tpl, rodarpá.tpl e menu.tpl podem ter um cache de longa duração, os eventos podem ser atualizados a cada hora e os artigos podem ser atualizados manualmente a cada vez que se insere um novo.

Desta forma, temos uma única página, que sozinha tem vários controles de cache diferentes.

Não vou mostrar o exemplo completo de um código como esse, porque ele vai bem além do escopo deste artigo, mas vamos mostrar algumas das partes relacionadas ao cache.


O site de artigos e eventos.


Temos nossos TPLs montados e funcionando. Por preferência pessoal, gosto de separar os arquivos que controlam cada TPL em arquivos independentes. Assim, para cada TPL tenho um arquivo PHP que faz todas as buscas de banco, controle de cache, etc...


Nosso index.php vai acabar ficando +- assim:

<?php
/* includes diversos para que tudo funcione direito
* incluindo o include do Smarty, banco, etc...
*/

include('cabecalho.php');
include('menu.php');
include('chamadaArtigo.php');
include('chamadaEventos.php');
include('rodape.php');

?>


Bem simples na verdade. A index essêncialmente se encarrega de chamar todos os objetos e métodos necessários para que tudo funcione corretamente (que eu geralmente separo em um único arquivo para que eu possa fazer somente um include na Index).

Cada arquivo controla sua própria exibição, por exemplo o cabecalho:

$Smarty->cache_lifetime = 3600;
if(!$smarty->is_cached('cabecalho.tpl')){
//...
}
$Smarty->display('cabecalho.tpl');


E assim por diante.

Um bloco um pouco diferente é o bloco de artigos. Você pode notar na descrição da funcionalidade acima que eu disse que o bloco deveria ser renovado somente quando um artigo novo é publicado. Assim, o controlador do template não tem controle sobre a renovação do artigo, não usamos o lifetime para determinar quando o template deve ser limpo.

O que de fato fazemos é, no admin, quando rodamos a rotina de publicar o artigo, forçamos a limpeza do cache desse bloco.

No arquivo de publicarMateria.php, colocaríamos além de todos os controles de insert em banco e etc..., também uma chamada de Smarty similar a essa:

$Smarty->clear_cache('chamadaArtigo.tpl');

(note que a página publicar matéria não precisa estar sendo controlada via Smarty para usar o objeto Smarty, basta que ele tenha uma referência ao objeto).


Bom, falamos muito sobre o cache, mas ainda não concluímos todas as coisas que existem. Como este artigo visa apenas melhorar o seu entendimento de como utilizar o cache do Smarty, não vou entrar em detalhes de tudo que é possível e nem de todas as outras funcionalidades associadas ao cache do Smarty. De uma forma geral, com o conhecimento que você adquiriu nesses artigos, você já tem a faca e o queijo na mão.

A regra básica de programação ainda permanece verdadeira, planeje suas ações. Desenhe, pense, estude , teste e só depois, faça.


Bom galera, qualquer coisa, só me mandar suas dúvidas ou sugestões. O LiveJournal não tem form de e-mail, então basta ir pro http://bugz.doutromundo.com e usar o de lá.


Jul. 2nd, 2008

Smarty e Caching - Parte 3


Antes de entrarmos de cabeça em uma das partes que eu acho mais interessante do Smarty Cache, uma coisa que deveria ter sido apresentada no último artigo era como limpar o cache.
Por falta de um lugar melhor, aqui vai.
<?
require('Smarty.class.php');
$Smarty = new Smarty;
$Smarty->caching = true;

// OPCAO 1 - Limpar todos o cache
$smarty->clear_all_cache();

// OPCAO 2 - Limpar somente o cache de um template
$smarty->clear_cache('aleatorio.tpl');
$smarty->display('index.tpl');
?>

Como você pode ver temos duas possibilidades, opção 1 permite limpar todos os caches do site em um único comando, e a opção 2 permite que você limpe o cache de um template individual.
Sugiro que você tome um certo cuidado ao utilizar o comando cleal_all_cache() pois em servidores com alta visitação, você repentinamente ter que gerar todos os arquivos de cache pode causar um impacto indesejado no site. Planeje suas mudanças de cache cuidadosamente. Mais nesse assunto depois.


Muitos caches, um template.

Uma das perguntas que eu mais ouvi ser feita (não somente com relação ao artigo mas nas empresas onde trabalhei com Smarty) foi em relação ao controle de de exibição do cache. Vou exemplificar usando o cenário similar ao explicado em um comentário no meu primeiro artigo:

Um template de Menu (menu.tpl) entra no cache. Quando o usuário está logado, o menu muda para não incluir os campos de login e senha, substituindo-os por um link de "logoff".
Uma típica solução para um cenário desses seria algo assim:
<?
// includes e instancia do Smarty

// Checa se o usuario está logado
$logadoID = isset($_SESSION['id_logado'])?$_SESSION['id_logado']:false;
if (!$logado){
    $Smarty->clear_cache('menu.tpl');
    $Smarty->assign('mostraLogin',true);
    $Smarty->assign('usuarioNome','Visitante');
}else{
    $Smarty->clear_cache('menu.tpl');
    $Smarty->assign('mostraLogin',false);
    $Smarty->assign('usuarioNome',$_SESSION['nome_logado']);
}
$Smarty->display('menu.tpl');
?>
(eu resumi um pouco os códigos, pois já presumo que você saiba fazer o include do Smarty, setar o cache=1 etc....)

O código acima deveria funcionar relativamente bem, porém, ele tem não tão obvio.
O menos obvio é que toda vez que rodamos esse PHP, checamos por uma sessão chamada "id_logado" e decidimos o que fazer a partir dela. Vamos fazer um simulado pra ver o que acontece:
1 - Visitante
  - entra ná pagina, ele não tem id_logado, limpa o cache, monta o menu, mostra o display
2 - Novo Visitante
 - entra ná pagina, ele tbm não tem "id", limpamos o cache, monta o menu, e mostra o display
3 - usuario logado - o usuario tá logado, limpamos o cahce, montamos o menu, e mostrams o display.

Bom sem continuar, vemos que de fato, embora estamos usando o cache, na realidade, estamos apenas gerando mais trabalho para o processador, sendo que toda vez estamos limpando o cache. Esquecemos de utilizar o is_cached para checar se o template está cacheado ou não. Então vamos lá:
<?
// includes e instancia do Smarty

// Checa se o usuario está logado
$logadoID = isset($_SESSION['id_logado'])?$_SESSION['id_logado']:false;
if (!$logado){
if (!$Smarty->is_cached('menu.tpl')){
$Smarty->clear_cache('menu.tpl');
$Smarty->assign('mostraLogin',true);
$Smarty->assign('usuarioNome','Visitante');
}
}else{
if (!$Smarty->is_cached('menu.tpl')){
$Smarty->clear_cache('menu.tpl');
$Smarty->assign('mostraLogin',false);
$Smarty->assign('usuarioNome',$_SESSION['nome_logado']);
}
}
$Smarty->display('menu.tpl');
?>
Agora geramos outro problema: De novo aos testes:
1 - visitante - não tem id, não tem cache, seta valores, mostra display
2 - visitante - nao tem id, o cache existe, mostra display
3 - visitante - nao tem id, o cache existe, mostra display
(legal com o visitante funcionou)
4 - usuario - tem ID, cache existe!, mostra display
...

Pronto como resolvemos isso? O Smarty guarda o primeiro cache, independente de termos logado ou não... assim todo mundo ve a página com o formulário de login.

Eu demorei, mas é importante que você entenda em detalhe a lógica por trás do Smarty para evitar problemas enquanto desenvolve. É muito comum você(eu ou qualquer um) fazer esse tipo de erro ao desenvolver, e por isso, fazer simulados com pequenos pedaços de código enquanto você desenvolve é importante.

Como resolvemos esse problema? Com cache dinâmico.

O cache dinâmico (por falta de melhor nome), permite você levar em consideração variáveis na hora de cachear seus arquivos. Vamos ao código, depois a explicação:

<?
// includes e instancia do Smarty

// Checa se o usuario está logado
$logadoID = isset($_SESSION['id_logado'])?$_SESSION['id_logado']:false;
if (!$logado){
if (!$Smarty->is_cached('menu.tpl',$logadoID)){
                // Não vamos limpar o cache pq não tem cache
//$Smarty->clear_cache('menu.tpl',$logadoID);
$Smarty->assign('mostraLogin',true);
$Smarty->assign('usuarioNome','Visitante');
}
}else{
if (!$Smarty->is_cached('menu.tpl',$logadoID)){
                // Não vamos limpar o cache pq não tem
//$Smarty->clear_cache('menu.tpl',$logadoID);
$Smarty->assign('mostraLogin',false);
$Smarty->assign('usuarioNome',$_SESSION['nome_logado']);
}
}
$Smarty->display('menu.tpl',$logadoID);
?>
Tá onde que mudamos? Eu adicionei a variável $logadoID como parâmetro dos metodos is_cached(), clear_cache() e display().
Agora vamos lá aos testes:

1 - visitante - não tem id, não tem cache menu.tpl0, seta valores, mostra display
2 - visitante - nao tem id, o cache menu.tpl0 existe, mostra display
3 - visitante - nao tem id, o cache menu.tpl0 existe, mostra display
4 - usuario 5 - tem ID = 5, o cache menu.tpl5 não existe, seta valores, mostra display
5 - usuario 5 - tem ID = 5, o cache menu.tpl5 existe, mostra display
6 - visitante - nao tem id, o cache menu.tpl0 existe, mostra display
7 - usuario 9 - tem ID = 9, o cache menu.tpl9 não existe, seta valores, mostra display
8 - usuario 5 - tem ID = 5, o cache menu.tpl5 existe, mostra display
8 - usuario 9 - tem ID = 9, o cache menu.tpl9 existe, mostra display

Pelos testes, parece que tudo funcionou!
Eu deixei a linha comentada do clear_cache porque é importante que você veja que no minuto que se usa o cache dinâmico, as funções que trabalham os templates precisam ter o "ID" associadas a elas.
Agora você deve estar perguntando porque eu demorei tanto para explicar algo que tão simples.
Usar o cache dinâmico em certos casos é imprescindível, você não tem como fazer algo assim sem ele, mas um "erro" muito comum dos desenvolvedores de Smarty é sair colocando ID em tudo que é cache.  È importante lembrar que todo cache é um arquivo em disco, e que usando o cache dinâmico, você aumenta o número de arquivos existente no seu HD.
Isso pode não parecer um problema muito sério, mas depois de algum tempo, e em um site grande, você pode ter literalmente milhões de arquivos cache. Se você cachear uma página que não muda com um ID, você acabará tendo centenas de milhares de cópias do mesmo arquivo, gastando espaço desnecessariamente.

O Cache dinâmico tem uma funcionalidade bem interessante. É possível apagar todos os caches com um ID=X. Usando o nosso exemplo acima, poderíamos apagar dodos os caches do usuário com ID=9.
Para tal, basta executar o comando:

$Smarty->clear_cache(null, $logadoID);

Bom é isso. No próximo artigo, eu explicarei como funciona o agrupamento de caches, e se der darei alguns casos de uso para vocês terem na cabeça na hora de sair desenvolvendo.

Jun. 30th, 2008

Smarty e Caching - Parte 2

Agora que aprendemos um pouco sobre o chaching de uma forma geral, vamos olhar mais a fundo o mundo dentro do Smarty.

Eu geralmente trabalho com um arquivo de configuração geral para o Smarty. Um “smarty.config.php” que eu deixo em algum lugar acessível e fácil. Não vou entrar no mérito de organização de arquivos ou nomenclaturas, padrões de código etc... é apenas uma dica para facilitar a vida.

Bom você já deve estar usando o Smarty e está interessado em habilitar o cache. Para isso, basta setar a variavel “caching” para 1 com a seguinte linha:

$Smarty->caching = 1;

Onde $Smarty é o objeto Smarty que você instanciou antes.

Essa variavelzinha avisa o Smarty que você quer guardar as versões rendidas dos TPLs que você tem.

Vamos ver o que isso significa na prática:

TPL – Arquivo template (aleatorio.tpl):

<html>

<head><title>Exemplo 1</title></head>

<body>

O n&uacute;mero escolhido &eacute; : {$aleatorio}

</body>

</html>


O arquivo PHP (aleatorio.php):

<?php

// incluir a class smarty

require('Smarty.class.php');

// criar nova instância

$Smarty = new Smarty;

// habilitar o cache

$Smarty->caching = 1;

// atribuir um numero aleatorio para variavel aleatorio

$Smarty->assign('aleatorio',rand(1,100));

$Smarty->display('aleatorio.tpl');

?>


Ao rodar essa página a primeira vez, teremos um resultado parecido com esse:

O número escolhido é: 45

Agora toda vez que você rodar sua página no browser, você terá o mesmo resultado (se não, verifique a configuração do seu Smarty, permissão de escrita nos diretórios, etc...)

Com esse simples exemplo, vemos a essência do funcionamento mais básico de cache no Smarty.

Vamos complicar as coisas um pouco. Vamos supor (só por conveniência) que este numero aleatório deve ser alterado a cada 5 minutos. Como que se faz isso?

Uma opção seria caçar o arquivo no cache e apagá-lo manualmente, mas imagino que isso seja um pouco trabalhoso demais.

A outra opção seria avisar o Smarty, que esse cache tem uma vida útil de 5 minutos.


O arquivo PHP (aleatorio5min.php):

<?php

// incluir a class smarty

require('Smarty.class.php');

$Smarty = new Smarty;

$Smarty->caching = 1;

// LINHA NOVA

$Smarty->cache_lifetime = 300;


$Smarty->assign('aleatorio',rand(1,100));

$Smarty->display('aleatorio.tpl');

?>


Agora atribuimos um valor ao atributo “cache_lifetime” (traduzindo: vida util do cache).

Esse parametro recebe um número de segundos que deve ser cacheada uma página.

Agora se rodarmos esse exemplo 4 vezes em intervalos de 4 minutos, teremos:


0:00 - O número escolhido é: 32

0:04 - O número escolhido é: 32

0:08 - O número escolhido é: 78

0:12 - O número escolhido é: 19


(lembrem-se – os números são aleatórios e provavelmente serão diferentes)


Vou entrar em lifetime com mais detalhes em um outro artigo mais avançado, aqui meramente demos uma illustrada na utilidade do conceito.


Importante para o desenvolvedor.


Um dos atributos importantes quando se está usando o Smarty e o Cache, é o atributo:

compile_check


Ele basicamente verifica todos os arquivos envolvidos no template em questão. Se algum deles sofrer alguma modificação, o template é recompilado do Zero.

Isso é importante quando se faz modificações nos templates (tpl). Muitas vezes você irá ter situações onde você faz uma modificação em seu TPL e ela não é refletida no ambiente. Cheque sempre se você tem esse atributo ligado.

Ele é setado usando a linha:


$Smarty->compile_check = true;


Controle de fluxo:


Se você já tem uma certa experiência em programação, você deve ter percebido que do ponto de vista do PHP, nada mudou (peguemos o arquivo aleatorio5min.php)


1. <?php

2. // incluir a class smarty

3. require('Smarty.class.php');

4. $Smarty = new Smarty;

5. $Smarty->caching = 1;

6. $Smarty->cache_lifetime = 300;

7. $Smarty->assign('aleatorio',rand(1,100));

8. $Smarty->display('aleatorio.tpl');

9. ?>


O fluxo permanece o mesmo com e sem o cache. Isso, consequentemente não alivia nosso servidor caso ao invés de buscarmos um numero aleatório, tivessmos fazendo uma conta num banco MySQL ou fazendo um parse de um arquivo XML ou CSV.

Assim, será necessário fazer algumas mudanças no código para usufruir completamente do controle de cache do Smarty.

O que precisamos é verificar se o arquivo tem um cache válido, se ele não o ter, precisamos executar as funções necessárias para popular o template. Caso ele já tenha um arquivo de cache, podemos simplesmente exibir o arquivo cacheado, sem ter que preparar todas as variáveis.


1. <?php

2. // incluir a class smarty

3. require('Smarty.class.php');

4. $Smarty = new Smarty;

5. $Smarty->caching = 1;

6. $Smarty->cache_lifetime = 300;

7. if (!$Smarty->is_cached('aleatorio.tpl')){

8. $Smarty->assign('aleatorio',rand(1,100));

9. }

10. $Smarty->display('aleatorio.tpl');

11. ?>


Como voce pode ver, incluimos uma nova chamada – is_cached('arquivo.tpl').

Essa chamada checa se o nosso cache é válido. Se ele não for (ela retornar false), executamos o nosso assign – no caso o gerador de números aleatórios.



Bom acho que já temos bastante para ir brincando.

Lembrem-se de algumas coisas para manter a vida fácil:


$Smarty->caching = 0; // não faz cache

$Smarty->is_cached('arquivo.tpl') – é importante para controlar o fluxo de dados no servidor


No próximo artigo, vamos ver em mais detalhes como cachear resultados dinâmicos. Isso é algo que já me perguntaram, mas o assunto é muito comprido para deixar em um só artigo.



Jun. 29th, 2008

Widgets 101 - O que é e onde errei

    Muitos ainda consideram os widgets brinquedos que nos deixam comprar "bebidas" para os amigos, ou jogar ovelhas um nos outros (usando exemplos do Facebook), ou acham que o widget se destina somente a ficar em segundo plano sentado na Área de Trabalho, atualizando dados sobre ações no mercado ou buscando fotos na HD do usuário.
    Aqui no Brasil os widgets ainda são pouco difundidos, parcialmente pela dificuldade de vendê-los aos clientes, e parcialmente devido ao limitado conhecimento da tecnologia por parte das equipes de marketing. Quem sabe esse documento ajude um pouco a mudar essa visão sobre o que são e como podem ser utilizados widgets em sua campanha.

Widgets 101 - As idéias erradas:

#1 - Os widgets são aplicativos de desktop
Embora o formato mais conhecido de widgets sejam aquelas aplicações que rodam em seu desktop, os widgets abrangem um mundo muito maior. Hoje, os widgets são elementos que podem ser adicionados em páginas web, desktops e até em telefones, mantendo a mesma funcionalidade e utilidade.

#2 - Os widgets são brinquedos
Embora no início de sua vida os widgets eram basicamente brinquedinhos firulentos para dar uma animada em uma aplicação, eles têm evoluído muito desde aqueles dias.  Hoje os widgets tem cada vez mais a função de complementar ações de um site, adicionar funcionalidade realmente útil ao usuário.
Estima-se que em 2008 sejam gastos US$40 milhões em desenvolvimento, criação e promoção de widgets nos Estados Unidos. (http://www.marketingcharts.com/interactive/widgets-to-wiggle-into-budgets-40mm-worth-in-2008-3877/)

#3 - Os widgets não são importantes
Os widgets podem ser utilizados para trazer informação de fora, e consequentemente de permitir que a informação seja transportada para outros sites de maneira rápida e simples. Isso ajuda a empresa trazer informações relevantes para seu ambiente, centralizando dados que possam ser úteis para seus usuários.
Além de úteis para a empresa, os widgets permitem que o usuário customize sua experiência com o site da empresa, para ver alguns exemplos disso já funcionando, basta ir para o igoogle.com e brincar um pouco. Já vemos esse tipo de coisa acontecer em sites como o da CNN.com, e logo, ele será um requisito esperado em qualquer site.

#4 - Widgets são ferramentas para redes sociais
Os widgets tem fortes conexões ao mercado de redes sociais, conteúdos criados ou moderados pelos usuários estão sendo cada vez mais aceitos e respeitados nos grandes portais. A importância da opinião do usuário está sendo valorizada. Seguindo essa tendência, logo, os widgets serão cada vez mais difundidos.

#5 - Os widgets são aplicativos sociais
O conceito de que um widget é uma mini aplicação por si só similar a um micro-site também afeta muito a decisão de fazer ou não um widget.  O fato de não saber ao certo como um widget pode ser utilizado (se ele vai ficar sentado ao lado de um widget de um concorrente ou até colocado em um site de um concorrente). Isso torna convencer alguns anunciantes um pouco difícil a princípio.
Os anunciantes podem usar os widgets para levar usuários para seus sites, onde lá podem usufruir de seus modelos de negócio padrão.

#6 - Os widgets não tem espaço para publicidade
Os modelos de publicidade convencional não contemplavam widgets. Pensar em um widget como uma página ou um "widget-banner" é errado. O widget é a publicidade, colocar conteúdo como vídeos, notícias relevantes e tantas outras coisas, podem trazer muito mais resultados do que se espera. Eles permitem, com um pouco de planejamento, estratégias bem mais dinâmicas e ricas.

#7 - Widgets vs Banners
Existe grande discussão sobre a diferença entre os valores de CPM de widgets e banners.  Primeiramente precisamos diferenciar entre widgets e banners, tendo em vista que um estará sempre colocado em um lugar fixo e em determinados sites, o widget pode ser difundido entre milhares de páginas na web. O banner, novamente, traz pessoas para seu ambiente, onde o widget pode ser fonte de milhões de interações entre usuários, e é claro, se a ferramenta for útil, sua taxa de conversão pode ser bem maior do que a de banners comuns.

#8 - Widgets são códigos isolados
Uma das funcionalidades que poucos sabem sobre o widget é o fato dele estar ciente de seu ambiente. Ou seja, é possível saber informações sobre seus usuários, e onde o widget está na web. Isso traz informações de grande valor para as equipes de marketing, trazendo um mapa demográfico de seus usuários.

#9 - Widgets não trazem usuários
Se você usa seu widget de forma correta, seu widget pode aumentar substancialmente o tráfego de usuários em seu site. Uma das principais razões por trás dessa alegação é o fato de que as principais ferramentas para medir tráfego não conseguem mensurar solicitações vindas de widgets. Os Analytics e Certificas, lêem interações no site por javascript, os widgets passam por trás disso, e consequentemente não são medidos. É preciso utilizar outras ferramentas para medir os acessos gerados por widgets. O mais simples é utilizar ferramentas que analisam Logs do servidor (WebTrends, awStats, etc...)

#10 - potencial viral baixo
Mais uma concepção errada é que os widgets não são muito virais. Isso é basicamente devido ao modelo do widget. Modelos que permitem grande interação por parte dos usuários ou promovem interação entre usuários tendem a ser bastante difundidos.  Widgets que basicamente são estáticos tendem a ser menos viralizados.


Bom, chegamos ao final do primeiro de uma série de artigos.
Espero que isso tenha lhe ajudado um pouco a ver os widgets de forma diferente.
No próximo artigo, vou olhar para alguns widgets e explicar um pouco suas funcionalidades.

Jun. 27th, 2008

Smarty e Caching

O Smarty é conhecido mais como um "Template engine" do que um "caching engine". Embora a documentação fale sobre o cache, ele é pouco utilizado pelas pessoas e tende-se a pensar nele mais como uma ferramenta de exibição do qualquer outra coisa.

Vamos do começo...

O que é esse tal de caching engine?

Quando você faz um código php simples, por exemplo:

pag: exemplo1.php
<?php
for ($i=0;$i<5;$i++){
    echo "$i - Linha repetida.<br />\r\n";
}
?>
Ao rodar ele, o resultado será:

0 - Linha repetida.<br />
1 - Linha repetida.<br />
2 - Linha repetida.<br />
3 - Linha repetida.<br />
4 - Linha repetida.<br />

Toda vez que você acessar a página exemplo1.php, o que acontece é:

1 - seu servidor HTTP pede para o PHP interpretar o código-fonte do exemplo1.php
2 - o PHP lê o arquivo e processa as instruções nele
3 - ele cospe o resultado de volta para o servidor web
4 - o servidor web manda pra você.

Tá, legal, e daí? Você pergunta?

Aqui que entra o Caching-engine.

Um Caching engine permite você fazer algo um pouco diferente:

Toda vez que você acessar a página exemplo1.php, o que acontece é:



1 - seu servidor HTTP pede para o PHP interpretar o código-fonte do exemplo1.php
2 - o PHP lê o arquivo e processa as instruções nele
3 - o Caching-Engine (CE) verifica se existe uma versão já pronta da página
3a - se não tiver, ele executa as operações do for
3b - tem, lê o arquivo do disco.
4 - ele cospe o resultado de volta para o servidor web
5 - o servidor web manda pra você.


OK, então um caching engine basicamente cria uma cópia rendida de um arquivo pronto. Parece ser balela inútil, principalmente com um exemplo tão tosco e simples como um "for".

Agora extrapolemos....

Imagine uma página que lê uma tabela de log do seu banco. Esses dados pegam o resultado estatístico a cada hora. Porque seu site tem muitas visitas, o LOG é bem extenso, e as queries demoram uns 2 segundos pra responder. Agora não só a query demora uns dois segundos pra responder, mas você ainda precisa fazer uma série de contas e cálculos complexos com os dados que são produzidos pela query.
Sua página agora demora uns 3 segundos pra responder, e nesse meio tempo, o processadordo servidor  fica próximos dos 75%.

Você pergunta "tá e?".

Agora lembre-se que seu servidor tem acessos pra caramba. Imagine 1000 usuários solicitando a mesma página em 1 minuto? O site trava, bomba, cai ou qualquer outra terminologia que você queira atribuir a esse acontecimento.

Se você utilizar um CE, o processamento ocorre somente uma vez, na primeira solicitação. Uma cópia do resultado é arquivado, e os outros 999 usuários vão estar vendo um HTML e não um PHP processado realtime.

Resultado? Seu site não cai, os outros serviços continuam livres para usar o processador.


Bom, agora que conhecemos um pouco sobre o que faz um CE(Caching Engine) próximo POST eu começo a mostrar isso aplicado ao Smarty
Blogged with the Flock Browser

Jun. 18th, 2008

gOS linux - easy and stable

I've been fooling around with gOS linux. Mostly because I wanted to change a bit the way I was working on Linux, but not have to go through the compex task of configuring thousands of little applications to make my desktop nicer.
I found gOS to be quite well resolved. A few quirks here and there, but in general, I am very leased so far. The interface is nice and very "OSX"ish, and we know that the guys at Apple are kind of specialists at making interfaces that work (at least that's my opinion).
I had one initial problem with the interface, which I already solved, but I'll place the problem and solution here in case anybody else has the same problem.
When installed, gOS was kind of slow and the kinky eye-candy such as wobbly windows, drop shadows and expose were not working. I configred them to certain actions but no luck. After some diggin about, I realized there was a Composite manager (xcompmgr) running as oposed to compiz. All I had to do was to open a shell and type "sudo apt-get remove xcompmgr" and that was that. After I restarted X, all my apps were working fine with all the eye-candy one may desire.

Being based on Ubuntu, which in turn is based on Debian, makes gOS very easy to maintain and update. Right now I couldn't be more pleased.



Blogged with the Flock Browser

Jun. 17th, 2008

Flock

Interessante o browser.
Bem integrado com coisas da internet.
Acho que vou começar a usar ele um pouco.
Blogged with the Flock Browser

Advertisement

Customize