Mostrando postagens com marcador php. Mostrar todas as postagens
Mostrando postagens com marcador php. Mostrar todas as postagens

quinta-feira, 22 de março de 2012

Enviando email no PHP com a class Mail do Pear

Hoje quero apenas documentar um exemplo de utilização da classe Mail do PEAR para envio de emails em formato HTML com imagem anexada e associada no HTML.
Já havia trabalhado antes com esta biblioteca, mas eu não enviava emails em HTML e muito menos com imagem associada.
A primeira motivação para documentar este exemplo foi porque não encontrei bons exemplos da utilização desta biblioteca em sites nacionais. Eu queria ter encontrado em sites nacionais para poder entender como trabalhar com texto com acentuação.

Para poder executar o código de exemplo certifique-se de instalar as bibliotecas Mail e Mail_mime do PEAR. (Não vou explicar aqui como usar o PEAR nem como instalar nem como baixar as bibliotecas dele).

O conceito chave aqui para enviar email com conteúdo HTML e com acentuação está relacionado com o encoding e charset do texto.
Não vou explicar este conceito aqui pois não é o intuito do documento. Mas basicamente, encoding é a representação interna dos dados e o charset é o conjunto de caracteres suportado.
A idéia é que se representarmos os dados com UTF-8 (usando o encoding UTF-8), teremos um charset bem maior do que usando a codificação ASCII.

Quando não utilizamos a codificação correta o que acontece é que acabam aparecendo caracteres especiais no meio do texto
certa vez um cliente chamou isso de "caracteres mastigados" ahhahahah...

Para resolver este problema, o bloco de código abaixo foi quem ajudou:


$enc = 'utf-8';
$mime = new Mail_mime(array(
'eol' => "\n",
'text_encoding' => $enc,
'html_encoding' => $enc,
'html_charset' => $enc,
'text_charset' => $enc
));


Bom, mas e para enviar o email como HTML? A saída está em usar a própria classe Mail_mime.
Esta classe fornece os métodos setTXTBody e setHTMLBody conforme o exemplo de utilização abaixo:


$mime->setTXTBody($text);
$mime->setHTMLBody($html);


Usando os métodos acima, basta criar um texto (por exemplo usando a variável $html) com conteúdo html mesmo, ou seja, abrir as tags e marcar o texto necessário.
Mas uma das coisas que achei interessante em enviar um email com conteúdo HTML foi utilizar imagens no HTML. Como associar um arquivo de imagem se você não sabe se a imagem existe no computador do cliente? Outra questão é que o HTML é carregado no client e a página não é acessada de um servidor meu! Então a idéia é anexar a imagem no email e referenciá-la dentro do HTML.


A imagem pode ser associada através do seguinte código:

$mime->addHTMLImage("arquivo.png", "application/octet-stream", "imagem", true, "minhaimagem");


Onde o primeiro argumento é o nome do arquivo no seu servidor, o segundo argumento é o mime-type da imagem, o terceiro é o nome do arquivo, o quarto indica se o nome "imagem" é um nome de arquivo ou não e o último parâmetro é um código para usar como referência no seu HTML.
Veja abaixo um exemplo de referência no HTML para esta imagem que foi anexada:





Bom, agora segue o código completo do exemplo:



require_once ("Mail.php");
require_once ("Mail/mime.php");

// aqui sao informados os dados do cabeçalho do SMTP
// temos 3 parametros: From, To e Subject onde
// From é o email do remetente, To é o destinatário
// e Subject é o assunto do email
$headers =
array(
'From' => 'meuemail@yahoo.com.br',
'To' => $email,
'Subject' => "bem vindo ao mundo do php"
);

// aqui temos os dados de autenticação da conta de email
// hoje a maioria dos servidores de email trabalham com
// autenticação via SMTP. Antigamente, muitos servidores
// famosos de email não possuiam autenticação, o que tornava
// fácil mandar email como se estivesse usando uma conta alheia.
$params =
array(
'auth' => true,
'host' => 'smtp.mail.yahoo.com.br',
'username' => 'meuemail@yahoo.com.br',
'password' => 'foobar'
);

// criamos nossa mensagem em formato html
$html = "



Olá caro programalhão! vamos programar em php hoje!



";

// e criamos a mensagem em formato txt
$text = "Olá caro programalhão! vamos programar em php hoje!";

// agora vamos mandar o email de uma vez
$enc = 'utf-8';

// para enviar um texto em português com acentuação, é sempre bom usar o encoding utf-8
$mime = new Mail_mime(array(
'eol' => "\n",
'text_encoding' => $enc,
'html_encoding' => $enc,
'html_charset' => $enc,
'text_charset' => $enc
));

// definições para o conteúdo HTML
$mime->setTXTBody($text);
$mime->setHTMLBody($html);

// aqui está uma parte muito interessante que é onde anexamos uma imagem para ser referenciada na mensagem
// através do img src="cid:minhaimagem" - o tal cid é o código definido como último parametro do método addHTMLImage
$mime->addHTMLImage("arquivo.png", "application/octet-stream", "imagem", true, "minhaimagem");
$body = $mime->get();
$headers = $mime->headers($headers);

// enviando o email
$mail = Mail::factory('smtp', $params);
$result = $mail->send( $email, $headers, $body );

// verificando erros
if (PEAR::IsError($result))
{
log_fail("ERRO ao tentar enviar o email {$email} (" . $result->getMessage(). ")");
}


Referências:
http://pear.php.net/package/Mail
http://pear.php.net/package/Mail_Mime
http://en.wikipedia.org/wiki/UTF-8
http://en.wikipedia.org/wiki/Unicode
http://kore-nordmann.de/blog/0082_charset_versus_encoding.html

segunda-feira, 12 de março de 2012

trocando a permissão de arquivos e diretórios recursivamente no php

Hoje, vou postar aqui um código que no mínimo pode ser engraçado.
É interessante do ponto de vista das funções que são utilizadas no php para manipulação de arquivos e diretórios.

Tudo isso aconteceu porquê em um servidor que hospedo um site, alguns arquivos são gerados com o usuário do apache... o famoso www-data!

Por alguns arquivos serem gerados com www-data e com permissão de leitura e gravação apenas para o próprio www-data, eu não conseguia fazer nem um backup do meu projeto por causa destes arquivos os quais eu não possuia permissão com meu usuário.

Já estava ficando desesperado até que pensei o que era o mais óbvio! Basta criar um script e acessar pelo browser e o usuário www-data estará em ação =P
Então a solução foi executar este script que por sua vez altera a permissão dos arquivos e diretórios recursivamente (e apenas quando o arquivo estiver sob o poder do www-data!!!!).

Talvez alguém possa até passar por isso ou ter uma solução bem mais inteligente pois a minha acho que está bem estranha. Caso alguém estiver lendo este post e tiver alguma idéia que me ajude a fazer isso de forma melhor, por favor! não hesite em deixar um comentário...

Agora chega de lero lero e vamos ao código:


/** funcao que apenas faz a chamada recursiva.
* criei só para modularizar a chamada que é
* feita em 2 lugares diferentes */
private function recur($path) {
$dir = scandir($path);
for( $i=2; $i < count($dir); $i++) {
$this->salvaodia($path . '/' . $dir[$i]);
}
}

/**
* esta é a funçao que salvou o dia!
* portanto... para deixar o código um pouco mais divertido
* vou manter o nome salva o dia! afinal...
* essa funçaozinha merece o meu respeito */
private function salvaodia($path) {
// path eh o caminho raiz a partir do qual quero
// sair procurando e mudando permissao
$info = stat($path);
// se for o userdata(cada server tera um diferente =/ )
if ($info[4] == 43234) {
chmod($path, 0777); // nao façam isso fora de casa
if (is_dir($path)) {
$this->recur($path);
}
} else {
if (is_dir($path)) {
$this->recur($path);
}
}
}

/** e aqui fazendo a chamada da salvacao */
public function salvacao() {
$path = 'foo/bar/fubah';
$this->salvaodia($path);
echo 'salvou o dia';
exit();
}


Com o código acima podemos ver algumas funções interessantes para manipular os arquivos e diretórios que são elas:

stat: retorna um conjunto de informações sobre um arquivo/diretório
scandir: recupera a lista de arquivos dentro do diretório informado
chmod: muda a permissão do diretório segundo a configuração rwx-rwx-rwx onde (r=read, w=write, x=execute). Cada grupo de permissões dessas estão relacionadas ao dono, grupo e outros (UGO - user, group, owner).
is_dir: apenas indica se o arquivo corrente é um diretório.

Bom... isso salvou meu dia (isso às 12:36 AM)
talvez salve o de mais alguém.

Mais uma coisa!!! Gostaria de ver este código em outras linguagens...
agora estou sem tempo de testar em java e ruby... se alguém quiser postar algum exemplo é só avisar.

trocando a permissão de arquivos e diretórios recursivamente no php

Hoje, vou postar aqui um código que no mínimo pode ser engraçado.
É interessante do ponto de vista das funções que são utilizadas no php para manipulação de arquivos e diretórios.

Tudo isso aconteceu porquê em um servidor que hospedo um site, alguns arquivos são gerados com o usuário do apache... o famoso www-data!

Por alguns arquivos serem gerados com www-data e com permissão de leitura e gravação apenas para o próprio www-data, eu não conseguia fazer nem um backup do meu projeto por causa destes arquivos os quais eu não possuia permissão com meu usuário.

Já estava ficando desesperado até que pensei o que era o mais óbvio! Basta criar um script e acessar pelo browser e o usuário www-data estará em ação =P
Então a solução foi executar este script que por sua vez altera a permissão dos arquivos e diretórios recursivamente (e apenas quando o arquivo estiver sob o poder do www-data!!!!).

Talvez alguém possa até passar por isso ou ter uma solução bem mais inteligente pois a minha acho que está bem estranha. Caso alguém estiver lendo este post e tiver alguma idéia que me ajude a fazer isso de forma melhor, por favor! não hesite em deixar um comentário...

Agora chega de lero lero e vamos ao código:


/** funcao que apenas faz a chamada recursiva.
* criei só para modularizar a chamada que é
* feita em 2 lugares diferentes */
private function recur($path) {
$dir = scandir($path);
for( $i=2; $i < count($dir); $i++) {
$this->salvaodia($path . '/' . $dir[$i]);
}
}

/**
* esta é a funçao que salvou o dia!
* portanto... para deixar o código um pouco mais divertido
* vou manter o nome salva o dia! afinal...
* essa funçaozinha merece o meu respeito */
private function salvaodia($path) {
// path eh o caminho raiz a partir do qual quero
// sair procurando e mudando permissao
$info = stat($path);
// se for o userdata(cada server tera um diferente =/ )
if ($info[4] == 43234) {
chmod($path, 0777); // nao façam isso fora de casa
if (is_dir($path)) {
$this->recur($path);
}
} else {
if (is_dir($path)) {
$this->recur($path);
}
}
}

/** e aqui fazendo a chamada da salvacao */
public function salvacao() {
$path = 'foo/bar/fubah';
$this->salvaodia($path);
echo 'salvou o dia';
exit();
}


Com o código acima podemos ver algumas funções interessantes para manipular os arquivos e diretórios que são elas:

stat: retorna um conjunto de informações sobre um arquivo/diretório
scandir: recupera a lista de arquivos dentro do diretório informado
chmod: muda a permissão do diretório segundo a configuração rwx-rwx-rwx onde (r=read, w=write, x=execute). Cada grupo de permissões dessas estão relacionadas ao dono, grupo e outros (UGO - user, group, owner).
is_dir: apenas indica se o arquivo corrente é um diretório.

sábado, 10 de março de 2012

Criando XML com XDom + DOMDocument no PHP5

Neste post, teremos um exemplo bem básico para criar uma estrutura em HTML usando a extensão DOM do PHP5 para geração de XML. Esta geração do XML foi encapsulada em uma classe XDom que está disponível no github.

Sempre que preciso criar um XML através do PHP, uso a DOM extension que já fornece as classes DOMDocument, Element e todas mais que implementam a especificação DOM disponível no W3C .

Porém as vezes quando o XML possui elementos com muitos atributos (que pode ser o caso de algumas estruturas HTML), o código começa a ficar grande e na minha opinião um pouco poluído.

Para melhorar um pouco a situação nos meus projetos pessoais acabei criando uma classe bem simples, mas bem simples mesmo. Portanto caso alguém queira criticar a simplicidade da classe e tiver idéias para contribuir, fique à vontade pois o código está disponível no github: https://github.com/adolfoweloy/xdom

Bom, então vamos direto ao assunto, que é o código em si:


O código abaixo é a implementação da classe que encapsula um pouco a complexidade do DOMDocument (ainda encapsula muito pouco - praticamente o principal aqui é encapsular o modo de definir os atributos de um elemento xml).


<?php

/**
* XDom: a simple facade for DOMDocument class from PHP
* The intent of this is to allow someone to write less code when dealing with XML Creation.
* XDom isn't dealing with XML reading. You can improve it if you want.
*/
class XDom {
private $doc = null;

/**
* private constructor to force user to use createDocument static method
*/
private function __construct($doc) {
$this->doc = $doc;
}

/**
* create an instance of XDom agregating it with an instance of DOMDocument.
* @return XDom
*/
public static function createDocument() {
$doc = new DOMDocument('1.0');
$dom = new XDom($doc);
return $dom;
}

/**
* creates an element that may have attributes represented with an associative array.
* @param string $name the name of the element
* @param array $attributes associative array with attribute name and attribute value respectively
* @return Element
*/
public function createElement($name, $attributes = array()) {
$el = $this->doc->createElement($name);
foreach ($attributes as $attr_name => $attr_value) {
$el->setAttribute($attr_name, $attr_value);
}
return $el;
}

/**
* append the $el to the DOMDocument encapsulated by XDom.
* @param Element $el the element to be appended within the document.
* @return void
*/
public function appendToDocument($el) {
$this->doc->appendChild($el);
}

/**
* appends an element inside another element.
* @param Element $el element that will receive another element to append
* @param Element $element_to_append element to be inserted within the first Element
* @return void
*/
public function appendChildTo($el, $element_to_append) {
$el->appendChild($element_to_append);
}

/**
* returns xml as string (as an HTML)
* @return string
*/
public function saveHTML() {
return $this->doc->saveHTML();
}

/**
* returns xml as string
* @return string
*/
public function saveXML() {
return $this->doc->saveXML();
}

}


Agora um exemplo de utilização:


<?php
require_once('xdom.php');

$xdom = XDOM::createDocument();
$dive = $xdom->createElement('div',
array(
'id' => 'minhadiv',
'class' => 'divExterna'));

$divi = $xdom->createElement('div',
array(
'id' => 'divInterna',
'style' => 'border: 1px solid black'));

$xdom->appendToDocument($dive);
$xdom->appendChildTo($dive, $divi);

echo $xdom->saveHTML();


Bom, através deste post, temos uma pequena documentação quanto ao propósito da classe bem como o próprio código.

Talvez possa ajudar alguém, quem sabe?


Referências

quarta-feira, 14 de janeiro de 2009

Configurando PHP + Oracle

Este artigo mostra a configuração do PHP com Oracle, em uma máquina com sistema operacional
Linux - CentOS 64 bits com PHP 5.1.6 para conectar em um servidor Oracle 10g.
O PHP foi instalado via yum, ou seja, não foi compilado manualmente.

Para utilizar o Oracle no PHP, em primeiro lugar é necessário baixar o client do Oracle.
Você deve baixar a versão do instant-client correspondente ao seu sistema operacional no site da Oracle. Clique aqui para o baixar o instantclient.


Eu baixei os seguintes arquivos compactados "tar.gz" para o Linux64.

Instant Client Package - Basic
Instant Client Package - SQL*Plus
Instant Client Package - SDK

Após baixar o instant client, é necessário baixar o módulo oci8 para o PHP disponível no Pecl.
Clique aqui para baixar o módulo oci8.

Baixe a última versão ( durante a criação deste artigo eu utilizei a versão oci8-1.3.4.tgz )


Instalando o Instant Client

Abaixo seguem os passos que segui para a instalação do mesmo, portanto, não é necessário utilizar
os mesmos diretórios que utilizei para instalação.

1 - copiar os arquivos do instant client para o diretório /opt/oracle ( caso o mesmo não existir, crie )
2 - descompactar os arquivos ( tar -xvzf arquivo-instant-client.tar.gz )
3 - todos os arquivos deverão ficar na pasta /opt/oracle/InstantClient_xx ( onde xx é a versão - eu usei a versão 10 )
4 - definir as seguintes variáveis de ambiente no arquivo /etc/profile:


# Oracle
export ORACLE_BASE=/opt/oracle/instantclient10_1
export ORACLE_HOME=/opt/oracle/instantclient10_1
export ORACLE_SID=prod
export ORACLE_TERM=xterm
export PATH=$HOME/bin:$ORACLE_HOME/bin:$PATH
export NLS_LANG=American_America.WE8ISO8859P1

# a última configuração foi utilizada pois meu Oracle Server está configurado
# com codificação de caracteres padrão ISO8861-2 ( Latin )


5 - carregar o arquivo através do comando abaixo:
[root@maquina]# source /etc/profile



Instalando o módulo oci8 para o PHP

1 - copiar o arquivo oci8-1.3.4.tgz para /usr/src
2 - descompactar o arquivo através do comando
[root@maquina]# tar -xvzf oci8-1.3.4.tgz
3 - após descompactar, será criado o diretório /usr/src/oci8-1.3.4
4 - execute os comandos abaixo:

[root@maquina]# cd /usr/src/oci8-1.3.4
[root@maquina]# phpize
[root@maquina]# ./configure --with-oci8=instantclient,/opt/oracle/instantclient10_1/
[root@maquina]# make

5 - caso tudo ocorrer bem, o diretório modules será criado
6 - copie o arquivo /usr/src/oci8-1.3.4/modules/oci8.so para o diretório de extensões configurado no
arquivo php.ini ( através da diretiva: extension_dir )
No meu caso o extension_dir está configurado para o diretório: /usr/lib64/php/modules/
7 - criar o arquivo oci8.ini dentro do diretório /etc/php.d e incluir o seguinte conteúdo no arquivo:


extension=oci8.so


Pronto! está configurado o PHP com Oracle!

terça-feira, 13 de janeiro de 2009

LOB Oracle + PHP

Este blog iniciou com foco em JAVA, mas como não programo apenas em JAVA, e acabo encontrando problemas em outras plataformas e linguagens, vai se tornar mais comum posts relacionados ao PHP como o de hoje.
Neste post vou apenas colocar um exemplo de utilização de campo CLOB com ORACLE + PHP.

Abaixo, segue um insert em uma tabela com campo do tipo CLOB:


...

$sql = "UPDATE TABELA
SET CAMPO_DO_TIPO_CLOB = EMPTY_CLOB()
WHERE codigo = :par_codigo
RETURNING CAMPO_DO_TIPO_CLOB INTO :MYCLOB";
$res = @ociparse( $this->con, $sql );

// fazer os binds
$clob = oci_new_descriptor($this->con, OCI_D_LOB );
oci_bind_by_name( $res, ":MYCLOB", $clob, -1, SQLT_CLOB );
oci_bind_by_name( $res, ":par_codigo", $this->codigo, -1, SQLT_INT );

$exec = @ociexecute( $res, OCI_DEFAULT );

$exec_lob = $clob->save( utf8_decode( $this->corpo_de_email ) );

if ( !$res || !$exec || !$exec_lob )
throw new Exception( "Erro salvando os dados do email." );

$clob->free();
oci_free_statement( $res );



Espero em breve, após explorar mais sobre o assunto, criar uma documentação prática e simples para isso.