Posts Tagged ‘php’

Pegando a temperatura de qualquer cidade

julho 29th, 2010

Me surgiu um trabalho aqui pelo qual preciso exibir a temperatura atual da cidade, e como estava com insônia decidi brincar um pouco e criar uma solução para isso, fui para o google e pesquisei por “Previsão do Tempo“, me surgiram alguns resultados, porém, gostei mais do UOL.

Depois disso foi correr para a criação do script para ler o HTML e retornar um objeto contendo as informações da temperatura no momento, segue o código escrito em php:

function loadTemp($cidade='Palmas-TO'){
	// variavel para dados de retorno
	$ret = array('url' => "http://tempoagora.uol.com.br/previsaodotempo.html/brasil/$cidade/");
 
	// carrega o html do tempoagora
	$html = file_get_contents($ret['url']);
 
	// Pegamos apenas a parte que interessa do html
	$iniflag = '<!-- Insere dados Atuais de AeroPortos ou Est. Meteorologica -->';
	$fimflag = '<!-- FIM Insere dados Atuais de AeroPortos ou Est. Meteorologica -->';
	$ini = strrpos($html, $iniflag ) + strlen($iniflag);
	$fim = strpos($html, $fimflag, $ini);
	$html = substr($html, $ini, ($fim-$ini));
 
	// pegamos a url do icone
	preg_match('@<img src="/(imagens/icones/[a-zA-Z\-]+.gif)"@', $html, $mat);
	$ret['icone'] = 'http://tempoagora.uol.com.br/' . $mat[1];
 
	// Limpa o código html
	$content = strip_tags($html);
	$content = str_replace('&nbsp;', ' ', $content);
 
	// quebra o que sobrou em um vetor
	$content = explode("\n", $content);
 
	// limpa espaços e linhas em branco
	foreach ($content as $k => &$v){
		$v = trim($v);
		if ($v==='') unset($content[$k]);
	}
 
	// pega horário da verificação
	$lin = array_shift($content);
	preg_match('@[0-9]{1,2}:[0-9]{1,2}@', $lin, $mat);
	$ret['verificado']  = $mat[0];
 
	// pega insidência de nuvens
	$ret['nuvens'] = array_shift($content);
 
	// define nomes melhores para as próximas propriedades
	$keys = array('temperatura', 'sensacao', 'vento', 
			'pressao', 'umidade', 'visibilidade');
 
	// reseta as chaves do vetor
	$content = array_unique($content);
 
	// percorre chaves impares e aplica as propriedades definidas acima
	for ($x=1; $x<=11; $x=$x+2){
		$ret[array_shift($keys)] = $content[$x];
	}
 
	// retorna os dados como um objeto
	return (object)$ret;
}

Analisando o site deles, notei que a temperatura é atualizada de hora em hora, então a melhor forma de utilizar essa solução é utilizando o crontab, que executa a cada hora, eu escolhi executar no quinto minuto de cada hora cheia (5:05, 6:05, etc).

segue o código php que o crontab executa:

require 'loadTemp.php';
// define nome do arquivo de cache
$cache_file = sys_get_temp_dir() . '/temp';
 
// carrega a temperatura
$temp = loadTemp();
 
// salva em cache
file_put_contents($cache_file, serialize($temp));

E para exibir no sistema eu fiz uma funçãozinha:

function temp(){
	$cache_file = sys_get_temp_dir() . '/temp';
	// se o cache existe, retorna o objeto
	if (file_exists($cache_file)) 
		return unserialize(file_get_contents($cache_file));
 
	// senão cria o cache e retorna =)
	$temp = loadTemp();
	file_put_contents($cache_file, serialize($temp));
	return $temp;
}

depois, no local específico, ficou algo mais ou menos assim:

<?php $temp = temp() ?>
<img src="<?php echo $temp->icone ?>" alt="<?php echo $temp->nuvens ?>" />
<span><?php echo $temp->temperatura ?> (<a rel="external" href="<?php echo $temp->url ?>">saiba mais</a>)</span>

Minha forma de pagar por esse uso é manter um link para o Tempoagora, o que é bastante interessante, pois meu visitante pode querer obter mais informações

É isso ai, abraço a todos

Classe, WebService e RSS para rastreamento de encomendas nos Correios em PHP

abril 10th, 2010

Olá, depois de meses sem escrever estou voltando com uma classe muito útil e simples que nunca vi em lugar nenhum. É uma classe para rastrear encomendas nos correios que eu escrevi em PHP, que retorna um vetor com cada modificação de status lá.

Vamos direto ao ponto, confira o exemplo:

http://ferrari.eti.br/correios/samples/class.php

E para deixar a brincadeira mais divertida, fiz também um webservice com suporte a Json (padrão), phpserialize, XML e um modo dump, para visualização:

http://ferrari.eti.br/correios/webservice/?q=PB151832535BR
http://ferrari.eti.br/correios/webservice/?q=PB151832535BR&f=dump
http://ferrari.eti.br/correios/webservice/?q=PB151832535BR&f=serial
http://ferrari.eti.br/correios/webservice/?q=PB151832535BR&f=xml
e claro, para quem usa Ajax:
http://ferrari.eti.br/correios/webservice/?q=PB151832535BR&callback=minhaFuncJs

Disponibilizei tanto a classe quanto o código do webservice (que tem suporte a caching!) “de grátis” e com licença BSD no github:

http://github.com/caferrari/correios/

*UPDATE* Adicionado um gerador de RSS, assim é possível usar o proprio agregador para fazer o tracking!

http://ferrari.eti.br/correios/rss/?PB151832535BR

e em homenagem aos atendentes de telemarketing: Estarei esperando forks e colaborações para a classe, além de comentários!.

Até a próxima.

nginx – webserver, proxy reverso e perfeito!

outubro 15th, 2009

Nosso departamento é responsável por manter a identidade visual dos sites do Governo do Estado e ainda fazemos os sites dos orgãos que não possuem um.

No trabalho sempre tivemos um constante problema para hospedar nossos sites: hardware!. Contamos hoje com dois incríveis servidores IBM Pentium4 3Ghz com 2gb de memória e HDs scsi, um para hospedar mais de 40 sites e o outro onde fica postgres com os bancos de dados desses sites.

Ultimamente nosso problema tem crescido bastante, pois, a demanda por sites aumentou e ao mesmo tempo o número de visitas veio aumentando e, como não conseguimos de forma alguma (até agora) investimento em equipamento novo estavamos chegando em uma situação crítica, nosso servidor começava a sentar morrer com 200 conexões simultaneas!

Lembrei-me de um post do boo-box onde vi um servidor web chamado nginx (lê-se engineX) e decidi pesquisar mais e fazer testes em casa onde rodando um servidor e servindo uma página php com um usleep de meio segundo consegui mais de 2000 conexões simultaneas! uau!..

nginx_performance

Na segunda feira seguinte, sem pensar muito, fui para o nosso servidor de produção e apliquei a seguinte política de funcionamento:

  • nginx recebe todas as conexões pela porta 80
  • nginx faz proxy para o apache (que roda em outra porta) se a solicitação for para uma página php
  • nginx resolve sozinho usando php-cgi caso a requisição seja para:
    • uma fotografia
    • um arquivo
    • uma requisição para o webservice
    • um download do diário oficial
    • um banner do Governo
    • a barra padrão do Estado
    • ou um arquivo na nossa lib

Como resultado da experiência, nossos sites continuam morrendo, porém, aguentando 700 conexões simultaneas e esse valor só é alcançado quando tem muita pesquisa no banco de dados (Dias que sai algo sobre algum concurso público ou muita demissão no Diário Oficial) logo, fica claro, que o problema não é mais do webserver e sim do nosso servidor de Banco. Bom, o nosso webserver atualmente mal chega a 5% de uso, mesmo com as 700 conexões. Só espero conseguir uma maquina nova e mais eficiente para os nossos Bancos de Dados logo!.

Update:
Fomos atendidos, estamos com um Xeon Quad Core com 4Gb de memória para o Banco de dados, e, associado com uma otimização do cache do webservice alcançamos mais de 1000 conexões simultâneas sem nenhuma degradação na performance. Detalhe que o webserver ainda é um P4 3ghz com 1gb de memória em que a utilização de processamento não passa de 5%.

Autenticação de Usuários no Vórtice PHP

outubro 9th, 2009

Nesse post vou explicar como adicionar autenticação de usuários no @vorticephp, como base para o sistema vamos utilizar o exemplo que já vem com o framework.

Script de BD:

CREATE TABLE IF NOT EXISTS orgaos (
id int(11) NOT NULL AUTO_INCREMENT,
sigla varchar(50) collate utf8_unicode_ci NOT NULL,
nome varchar(150) collate utf8_unicode_ci NOT NULL,
PRIMARY KEY  (id)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8
 
CREATE TABLE IF NOT EXISTS usuarios (
id int(10) UNSIGNED NOT NULL,
nome varchar(50) NOT NULL,
email varchar(60) NOT NULL,
senha char(32) NOT NULL,
PRIMARY KEY  (id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO usuarios (nome, email, senha) VALUES('Administrador', 'adm@ferrari.eti.br', md5('123'));

eu criei essa tabela com esse usuario e senha no database que já vem configurado no framework para vocês testarem localmente. Você pode configurar a conexão com o seu próprio banco de dados no arquivo app/app.php

Para iniciar vamos criar o objeto do usuário em: app/model/Usuario.php e codificar:

<?php
class Usuario{
	public function __construct($id=0, $nome='', $email='', $senha=''){
		$this->id = $id;
		$this->nome = $nome;
		$this->email = $email;
		$this->senha = $senha;
	}
}

agora que temos o objeto, vamos criar um DAO para realizar operações, crie o arquivo app/model/UsuarioDAO.php e segue o código:

<?php
class UsuarioDAO{
	public function getByEmail($email){
		$sql = "SELECT * FROM usuarios WHERE email='$email'";
		return Database::getInstance()->queryOne($sql);
	}
}

vamos para o controller de usuários, crie o arquivo app/controller/UsuarioController.php e segue o codigo inicial:

<?php
class UsuarioController extends Controller{
	public function login(){
 
	}
}

Dai a gente cria o nosso formulário de login, edite app/view/usuario/login.php:

<h2>Login</h2>
<fieldset>
	<form method="post">
		<p><label>E-mail:</label><input type="text" name="email" /></p>
		<p><label>Senha:</label><input type="password" name="senha" /></p>
		<p><input type="submit" value="Logar!" /></p>
	</form>
</fieldset>

Agora com o form criado, vamos editar a action login do controller Usuario, volte e edite o arquivo app/controller/UsuarioController.php:

<?php
class UsuarioController extends Controller{
	public function login(){
		// se um formulario foi postado
		if (post){
			// pega as variáveis do post
			$email = addslashes(p('email'));
			$senha = md5(p('senha'));
 
			// seleciona o usuario, armazena na variavel $u
			// e ainda verifica se o usuario existe
			if ($u = UsuarioDAO::getByEmail($email)){
				// verifica se a senha digitada combina com
				// a que está no BD
				if ($u->senha == $senha){
					// remove a senha do objeto
					$u->senha = null;
					// grava a session
					Session::set("u", $u);
					// Cria mensagem de sucesso e redireciona para o index
					Post::setSucesso("Olá {$u->nome}, você está logado", new Link(""));
				}else
					// Retorna erro
					Post::setErros("Senha incorreta!");
			}else
				// Retorna erro
				Post::setErros("e-mail não encontrado!");
		}
	}
}

Para ficar bonita a url vamos criar um route para esta action, edite o arquivo app/routes.php e adicione:

Route::add("^login$", "usuario:login");

Agora o formulário de login já está funcionando, vamos fazer o sistema obrigar o usuario estar logado para fazer qualquer coisa no sistema, para isso edite o arquivo app/controller/MasterController.php, como queremos que para todo o sistema sejá necessário o login, vamos adicionar um construtor nessa classe com o seguinte código:

function __construct(){
	// se a session "u" não existir, criar uma com um usuario vazio
	if (!Session::get("u")) Session::set("u", new Usuario());
 
	// Se a session u tiver um objeto vazio..
	// e o controller/action forem diferentes dos de login
	if (Session::get("u")->id == 0 && controller != 'usuario' && action != 'login'){
		// redireciona para a tela de login
		redirect(new Link("login"));
	}
}

Bom, com isso já deve estar tudo funcionando de forma eficiente e simples. Qualquer dúvida ou sugestão mande sem hexitar.

Vórtice PHP Framework – Introdução

setembro 21st, 2009

Assim como frameworks mais conhecidos, o Vórtice tem uma estrutura de pastas que visa organizar todo o sistema e facilitar na hora da reutilização de código. segue abaixo a estrutura:

1 - app
1.1 - classes
1.2 - controller
1.2 - model
1.3 - view
1.4 - error_docs
1.5 - i18n
1.6 - plugins
2 - core
3 - css
4 - js
5 - templates
5.1 - nome_do_seu_template
5.1.1 - css
5.1.2 - js

1 – App

Apesar do framework não exigir nenhuma configuração em ambientes Linux/Unix ele possui um arquivo config.php que é necessário ser usado em caso de instalação em um ambiente Windows para definir a pasta fisica e a pasta virtual do sistema. ainda na pasta app existem os arquivos app.php e funcoes.php, que podem ser utilizados para inicializar instâncias de bancos de dados, criar funções e fazer qualquer coisa que você venha a precisar globalmente no seu site. Aqui também existe o arquivo route.php onde você poderá criar rotas baseadas em expressões regulares, tem um exemplo comentado de como funciona no sistema de exemplo.

1.1 – classes

Essa é a pasta de helpers, coloque ai suas classes de Segurança, as que modificam o fluxo do framework e qualquer classe que você venha a precisar no seu sistema

1.2 – controller

Pasta onde ficam os controllers, o nome do arquivo deve ser: CarroController.php, contendo dentro uma classe CarroController extendondo a classe Controller do framework. cada metodo dessa classe será uma action.

1.2 – model

Modelos do sistema, cada model é constituido por dois arquivos: Carro.php e CarroDAO.php contendo cada um a respectiva classe dentro. A classe Carro guarda a classe de um unico objeto carro (pode extender a classe de framework DTO) e a classe CarroDAO (quepode extender a classe de framework DAO) contêm as operações relacionadas ao objeto Carro (insert, delete, list, etc)

1.3 – view

Views do sistemas, uma view é um arquivo .php que será colocado dentro do template após a execução (substituindo o comentario <!–conteudo–> dentro do framework). Cada view deve ser colocada em uma subpasta com o nome do controller que ela pertence: app/view/carro/listar.php e será carregada automaticamente após a action listar do controller carro.

1.4 – error_docs

Páginas de erro, no framework já vem dois modelos.

1.5 – i18n

Pasta onde ficam traduções do sistema (en.conf, pt.conf, jp.conf, etc). Futuramente eu escrevo um post só sobre isso.

1.6 – plugins

Nessa pasta ficam plugins, que são executados exclusivamente antes da página ser enviada ao navegador. Futuramente eu escrevo sobre ela também.

2 – core

Aqui fica o nucleo do framework, caso você tenha vários sistemas usando ele, é possível criar um link simbólico e usar apenas uma pasta para todos os sites.

3 – css

Arquivos CSS globais, que serão carregados para todos os templates

4 – js

Arquivos JS globais, assim como a pasta css

5 – templates

Templates do site, cada subpasta será um template e dentro será necessário um arquivo template.php com o html básico da página.

5.1.1 – css

Aqui ficam os arquivos CSS exclusivos desse template

5.1.2 – js

Arquivos JS exclusivos do template

Fica ai toda a estrutura, qualquer dúvida deixe um comentário.

Faça já o download e experimente: Projeto Vórtice PHP
Siga o vórtice no twitter: @vorticephp e acompanhe mais novidades seguindo @caferrari e @luanlmd