Controle de cache com PHP

Para nunca fazer cache de uma página

$ts = gmdate("D, d M Y H:i:s") . " GMT";
header("Expires: $ts");
header("Last-Modified: $ts");
header("Pragma: no-cache");
header("Cache-Control: no-cache, must-revalidate");

Para fazer cache de 1 hora (3600 segundos)

$seconds_to_cache = 3600;
$ts = gmdate("D, d M Y H:i:s", time() + $seconds_to_cache) . " GMT";
header("Expires: $ts");
header("Pragma: cache");
header("Cache-Control: max-age=$seconds_to_cache");

 

Data em portugues no php

Normalmente eu fazia alguns malabarismos, como um array com os nomes dos meses em português, mas a gente acaba esquecendo que o php tem função nativa pra praticamente tudo.

Pesquisando um pouco, descobri que é só trocar o locale que a mágica acontece =)

setlocale(LC_ALL, 'pt_BR', 'pt_BR.iso-8859-1', 'pt_BR.utf-8', 'portuguese');
date_default_timezone_set('America/Sao_Paulo');
echo strftime("%A, %d de %B de %Y", strtotime('NOW'));

Referências:
http://br.php.net/strftime
http://br.php.net/setlocale
http://br.php.net/date_default_timezone_set

Imagem docker lemp/lnmp de fácil uso

Eu uso docker para ambiente de desenvolvimento, logo não preciso de tamanha complexidade com várias imagens dependentes montagem de diretórios cruzados etc.

Para esta finalidade basicamente preciso de um servidor lemp (ou lnmp), que é sigla para “Linux, (e)nginx, mysql e php” e um php myadmin.

Assim sendo criei uma imagem disponível publicamente no docker hub para quem precisa desta finalidade.

Para subir a aplicação com esta imagem, basta criar um docker-composer.yml na raiz de seu projeto com o conteúdo abaixo:

web:
 image: fbraz3/lnmp
 volumes:
 - ./:/app/public/
 ports:
 - "127.0.0.1:80:80"
 - "127.0.0.1:3306:3306"

E depois rodar o comando:

docker-compose up -d

A aplicação estará acessível em http://localhost/ e o PHPMyAdmin em http://localhost/pma/ simples assim.

Já está pré-configurado e com todos os grants necessários uma base de dados com o nome de “app” (sem as aspas) para uso na aplicação.

Como uso essa imagem nos meus projetos venho sempre aprimorando ela, então o changelog vai ficar sempre disponível em https://hub.docker.com/r/fbraz3/lnmp/

 

Instalar PHP5.3 no ubuntu 14.04

Esta dica teoricamente funciona também nas versões mais recentes do ubuntu.

Estes dias um antigo cliente meu entrou em contato solicitando a árdua tarefa de instalar o PHP  5.3 na última versão LTS do ubuntu (no momento em que escrevo é a 14.04).

Meu primeiro pensamento, foi baixar o tarball e compilar no servidor. Depois de mais de uma hora resolvendo dependências de bibliotecas, me deparo com erro na hora do make que eram basicamente questões relativas a versão de compilador, sendo praticamente impossível resolver (e olha que tentei).

Logo surgiu a ideia de buscar algum PPA que contenha esta versão, que também foi em vão, pois descobri que mesmo os repositórios que, em alguns artigos na internet diziam que continham esta versão do PHP, já haviam atualizado para as mais novas.

Quando tudo estava perdido, eis que surge uma ideia muito maluca. E se eu adicionasse os repositórios do ubuntu 12.04, deveria haver algum jeito de forçar o apt a utilizar pacotes de um determinado repositório.

Então, sem mais delongas, segue a receita de bolo:

Primeiro vamos criar um arquivo contendo os repositórios do ubuntu precise (12.04)

/etc/apt/sources.list.d/precise.list

deb http://mirror.rackspace.com/ubuntu/ precise main restricted
deb-src http://mirror.rackspace.com/ubuntu/ precise main restricted
deb http://mirror.rackspace.com/ubuntu/ precise-updates main restricted
deb-src http://mirror.rackspace.com/ubuntu/ precise-updates main restricted
deb http://mirror.rackspace.com/ubuntu/ precise universe
deb-src http://mirror.rackspace.com/ubuntu/ precise universe
deb http://mirror.rackspace.com/ubuntu/ precise-updates universe
deb-src http://mirror.rackspace.com/ubuntu/ precise-updates universe

Agora o “pulo do gato”, fazer com que os pacotes do PHP e do Apache utilizem este repositório

/etc/apt/preferences.d/php_precise

Package: php5
Pin: release a=precise
Pin-Priority: 1001

Package: php*
Pin: release a=precise
Pin-Priority: 1001

Package: php-*
Pin: release a=precise
Pin-Priority: 1001

Package: libapache2-mod-php5
Pin: release a=precise
Pin-Priority: 1001

Package: php5
Pin: release a=precise-updates
Pin-Priority: 1001

Package: php*
Pin: release a=precise-updates
Pin-Priority: 1001

Package: php-*
Pin: release a=precise-updates
Pin-Priority: 1001

Package: libapache2-mod-php5
Pin: release a=precise-updates
Pin-Priority: 1001

Package: apache2-*
Pin: release a=precise
Pin-Priority: 1001

Package: apache2-*
Pin: release a=precise-updates
Pin-Priority: 1002

Package: apache2*
Pin: release a=precise
Pin-Priority: 1001

Package: apache2*
Pin: release a=precise-updates
Pin-Priority: 1002

OBS: Os pacotes do apache são necessários caso você vá utilizar mod_php, se for utilizar php-fpm ou php-cgi, basta retirar os grupos referentes ao apache no arquivo acima.

Agora basta instalar os software e “voilà”

apt-get update
apt-get install apache2 php5 libapache2-mod-php5

Todo esses procedimentos que citei (compilação, procura de ppa, testes), levaram horas do meu tempo livre, então se você estiver lendo isso e lhe for útil, um belo agradecimento seria um compartilhamento no facebook! 😉

Função para validar cartões de crédito com detecção automática da bandeira

Função para validar cartões de crédito, com suporte a validação de CVC.

O primeiro parâmetro é o número do cartão e o segundo o CVC (opcional), os dados serão sanitizados, sendo filtrado somente os números.

A saida é um array de três posições, a primeira retorna false (em caso de erro) ou a bandeira, a segunda se o número do cartão é válido e a terceira se o CVC é válido.

 

/**
 * @author Felipe Braz
 * @website https://braz.dev/blog
 * @param int $cartao
 * @param int $cvc
 * @return array
 */
function valida_cartao($cartao, $cvc=false){
	$cartao = preg_replace("/[^0-9]/", "", $cartao);
	if($cvc) $cvc = preg_replace("/[^0-9]/", "", $cvc);

	$cartoes = array(
			'visa'		 => array('len' => array(13,16),    'cvc' => 3),
			'mastercard' => array('len' => array(16),       'cvc' => 3),
			'diners'	 => array('len' => array(14,16),    'cvc' => 3),
			'elo'		 => array('len' => array(16),       'cvc' => 3),
			'amex'	 	 => array('len' => array(15),       'cvc' => 4),
			'discover'	 => array('len' => array(16),       'cvc' => 4),
			'aura'		 => array('len' => array(16),       'cvc' => 3),
			'jcb'		 => array('len' => array(16),       'cvc' => 3),
			'hipercard'  => array('len' => array(13,16,19), 'cvc' => 3),
	);

	
	switch($cartao){
		case (bool) preg_match('/^(636368|438935|504175|451416|636297)/', $cartao) :
			$bandeira = 'elo';			
		break;

		case (bool) preg_match('/^(606282)/', $cartao) :
			$bandeira = 'hipercard';			
		break;

		case (bool) preg_match('/^(5067|4576|4011)/', $cartao) :
			$bandeira = 'elo';			
		break;

		case (bool) preg_match('/^(3841)/', $cartao) :
			$bandeira = 'hipercard';			
		break;

		case (bool) preg_match('/^(6011)/', $cartao) :
			$bandeira = 'discover';			
		break;

		case (bool) preg_match('/^(622)/', $cartao) :
			$bandeira = 'discover';			
		break;

		case (bool) preg_match('/^(301|305)/', $cartao) :
			$bandeira = 'diners';			
		break;

		case (bool) preg_match('/^(34|37)/', $cartao) :
			$bandeira = 'amex';			
		break;

		case (bool) preg_match('/^(36,38)/', $cartao) :
			$bandeira = 'diners';			
		break;

		case (bool) preg_match('/^(64,65)/', $cartao) :
			$bandeira = 'discover';			
		break;

		case (bool) preg_match('/^(50)/', $cartao) :
			$bandeira = 'aura';			
		break;

		case (bool) preg_match('/^(35)/', $cartao) :
			$bandeira = 'jcb';			
		break;

		case (bool) preg_match('/^(60)/', $cartao) :
			$bandeira = 'hipercard';			
		break;

		case (bool) preg_match('/^(4)/', $cartao) :
			$bandeira = 'visa';			
		break;

		case (bool) preg_match('/^(5)/', $cartao) :
			$bandeira = 'mastercard';			
		break;
	}

	$dados_cartao = $cartoes[$bandeira];
	if(!is_array($dados_cartao)) return array(false, false, false);

	$valid     = true;
	$valid_cvc = false;

	if(!in_array(strlen($cartao), $dados_cartao['len'])) $valid = false;
	if($cvc AND strlen($cvc) <= $dados_cartao['cvc'] AND strlen($cvc) !=0) $valid_cvc = true;
	return array($bandeira, $valid, $valid_cvc);
}

Ah, a minha esposa queria que eu botasse nesse post uma foto de gatinho, então lá vai:

Picture-86

Fonte: https://gist.github.com/erikhenrique/5931368

file_get_contents e scandir no php4

php
Pra quem precisa desenvolver mantendo compatibilidade com PHP4, aqui algumas funções que podem ser úteis. irei adicionando mais com o tempo.

if(!function_exists('scandir')) {
	function scandir($dir, $sortorder = 0) {
		if(!is_dir($dir)) return false;

		$dirlist = @opendir($dir);
		while(($file = readdir($dirlist)) !== false) {
			if(is_dir($file)) continue;
			$files[] = $file;
		}
		($sortorder == 0) ? asort($files) : rsort($files);
		return $files;
	}
}

if (!function_exists('file_put_contents')) {
	function file_put_contents($filename, $data, $append=false) {
		$mode = ($append == 'FILE_APPEND') ? 'a' : 'w';
		$f = @fopen($filename, $mode);
		if(!$f) return false;

		$bytes = fwrite($f, $data);
		fclose($f);
		return $bytes;
	}
}

E pra quem necessita de uma hospedagem de qualidade compatível com php4 ou várias versões do php5 (atualmente 5.2, 5.3 e 5.4), recomendo fortemente a kinghost.

 

Enviar email em html usando a função mail

Pra quem sempre se perde na hora de configurar os cabeçalhos:

function EnviaMail($from, $to, $assunto, $mensagem, $reply = ""){
	if($reply == "") $reply = $from;
	$mail_headers = implode("\n", array("From: $from", "Reply-To: $reply", "Subject: $assunto","Return-Path:  $from","MIME-Version: 1.0","X-Priority: 3","Content-Type: text/html; charset=ISO-8859-1"));
	mail ( $to,$assunto,$mensagem,$mail_headers );
}

Exemplo de uso:

$assunto = "teste de email";
$mensagem = "email em <b>html</b>";	
EnviaMail('[email protected]', '[email protected]', $asunto, $mensagem);

solução para cackephp corrompendo cookies com suhosin

O cackephp por padrão criptografa o valor dos cookies para segurança só que isso causa incompatibilidades com o suhosin.

Uma possível solução é desativar o suhosin, porém isso poderia abrir uma grande brecha de segurança, então o mlehor a fazer é desabilitar a criptografia do cookie.

Para isto é só setar o terceiro parâmetro como false no método Cookie->write

Exemplo:

$this->Cookie->write('carrinho', $dados_carrinho, false);

 

[magento] error parsing headers: duplicate header ‘Content-Type’

Um cliente usando api do magento em SOAP retornava o seguinte erro via php-fpm

[Thu Aug 02 17:50:57 2012] [error] [client xx.xxx.xxx.xxx] FastCGI: comm with server “/var/run/fastcgi/xxxx-fcgi” aborted: error parsing headers: duplicate header ‘Content-Type’

O erro com certeza estava na aplicação, seja em função de encoding ou por ser uma versão antiga do magento (1.4)

Resolvido erro inserindo a linha abaixo no arquivo app/code/core/Mage/Core/Controller/Response/Http.php

Mage::app()->getResponse()->setHeader("Content-Type", .text/html; charset=UTF-8.,true);