Computação em nuvem com PHP, Parte 1: Usando Amazon S3 com o Zend Framework

Movendo dados para dentro e fora da nuvem com o Zend Framework

O Zend Framework contém diversas classes que tornam fácil usar serviços de armazenamento baseados em nuvem. Esse artigo ilustra como usar essas classes com o serviço de armazenamento em nuvem S3 do Amazon.

Doug Tidwell, developerWorks staff, IBM

Doug TidwellDoug Tidwell é um engenheiro de software sênior no grupo Emerging Technology da IBM. Ele foi um palestrante na primeira conferência sobre XML em 1997 e trabalhou com linguagem de marcações, serviços da Web e tecnologia SOA por vários anos. Seu trabalho como um evangelista de tecnologia é explicar os padrões e tecnologias por trás da computação em nuvem e ajudar clientes a integrá-los com suas arquiteturas e estratégias gerais de negócios. Ele é autor de vários artigos aqui no developerWorks e é o autor do livro sobre XSLT da O'Reilly (ISBN 0-596-52721-7), um presente inteligente para todas as ocasiões. Ele reside em Chapel Hill, N.C., com sua esposa, filha e cão.



02/Nov/2009

A computação em nuvem promete espaço em disco ilimitado para usuários e aplicativos. Em um mundo ideal, acessar tal armazenamento seria tão fácil quanto acessar um disco rígido local. Infelizmente, as APIs básicas da maioria dos serviços de armazenamento em nuvem obriga os programadores a pensar sobre protocolos e detalhes de configuração em vez de simplesmente trabalhar seus dados. Esse artigo observa as classes no Zend Framework que facilitam o uso do serviço de armazenamento S3 do Amazon como um disco rígido sem limites.

Formatos de ligação e computação em nuvem

Um grande desafio para construir aplicativos que funcionem na nuvem é a interface para os próprios serviços. A maioria dos serviços apresenta uma interface REST ou SOAP. (S3 tem os dois.) Uma importante vantagem de uma interface REST ou SOAP é não ser específica de linguagem. Isso significa que é possível invocar o serviço seja qual for a linguagem de programação. A desvantagem é que ao usar forças REST ou SOAP você pensa nos detalhes da solicitação em vez de pensar nos dados que está usando. Como exemplo, todas as solicitações para S3 devem incluir um token de autenticação composto de uma chave de acesso e um valor de assinatura Amazon. Isso significa que uma solicitação precisa incluir um valor como 0PN5J17HBGZHT7JJ3X82:frJIUN8DYpKDtOLCwo//yllqDzg=.

Obviamente, uma abordagem de alto nível que permite se concentrar nos dados em vez das assinaturas e outros detalhes é uma importante melhora de produtividade. É quando surge a classe Zend_Service_Amazon_S3. Essa classe permite se concentrar nos dados e não na mecânica dos cabeçalhos HTTP, envelopes SOAP e outros detalhes irrelevantes.


Iniciando

Se o Zend Framework ainda não foi instalado, faça o download e instale o pacote completo em zend.com/community/downloads. Isto vai instalar o Zend Framework, PHP, e o servidor da Web Apache na sua máquina. Quando a instalação estiver concluída vá para http://localhost/ZendServer/. Consulte a documentação de instalação do Zend Framework para todos os detalhes. Ao se conectar ao console ZendServer, já estará tudo pronto.

Para prosseguir com os exercícios, é necessário configurar uma conta no Amazon (consulte Resources para links de páginas de gerenciamento de conta). Com a conta configurada, será necessário gerenciar suas credenciais. O Amazon fornece uma chave de acesso e uma chave secreta. Suas páginas PHP precisam desses valores ao trabalhar com S3. Uma abordagem para gerenciar tal informação é simplesmente colocar os valores no seu código.

Listagem 1. Armazenando credenciais em seu código PHP
// Credentials for Amazon - Don't do this!

$awsKey = "0123456789ABCDEFGHIJ"; $awsSecret = "0123456789abcdefghiABCDEFGHI1234567890AB";

Essa abordagem funciona, mas é preciso colocar esse código em cada arquivo PHP que precisa do código. Uma melhor abordagem é colocar esses valores em um arquivo .ini PHP, que se parece com a Listagem 2.

Listagem 2. Armazenando credenciais em um arquivo .ini PHP
; Configuration file to hold secret keys, account numbers and other useful
; strings for Amazon and other cloud accounts.

[amazon]
accessKey=0123456789ABCDEFGHIJ
secretKey=0123456789abcdefghiABCDEFGHI1234567890AB
ownerId=123456789012

[nirvanix]
username=jane_doe
password=XXXXXXXX
appKey=01234567-89ab-cdef-0123-456789abcdef

Uma classe simples PHP facilita trabalhar com os seguintes valores.

Listagem 3.Uma classe PHP simples para recuperar credenciais
<?php
// Simple class to retrieve credentials from an .ini file

class Credentials
{
  var $key_array;

  function Credentials() {
    $this->key_array = parse_ini_file("..\conf\cloud.ini", true);
  }

  function getCredential($group, $key) {
    return $this->key_array[$group][$key];
  }
}
?>

Essa classe usa a função PHP parse_ini_file() para ler valores no formato .ini file. O primeiro argumento para a função é o nome do arquivo, e o segundo argumento diz a PHP para analisar o arquivo como seções diferentes. Isso significa que a matriz $key_array é uma matriz 2-D. As chaves da matriz sãoamazon e nirvanix na primeira dimensão, e accessKey, secretKey, appKey, etc. na segunda. A classe Credentials fornece o método getCredential() para recuperar um valor do arquivo .ini file. Em vez de codificar permanentemente nossas credenciais em cada arquivo PHP, começaremos nossas amostras com linhas similares a estas:

Listagem 4. Criando e usando um objeto Credentials
<?php
require_once 'Credentials.php';

$creds = new Credentials;
$s3 = new Zend_Service_Amazon_S3($creds->getCredential('amazon', 'accessKey'),
                                 $creds->getCredential('amazon', 'secretKey'));

Vai levar um pouco mais de tempo para configurar seu código dessa maneira, mas depois de feito, suas credenciais são definidas uma vez, em um só lugar. Se for necessário mudar as credenciais, elas não precisam ser mudadas em cada arquivo PHP.

Algumas notas:

  • Observe que o arquivo .ini não está no root de documento do servidor da Web. Está no diretório conf , um diretório do mesmo nível do root de documento. Por motivos óbvios, não é preciso colocar o arquivo de credenciais em algum lugar que um usuário não autorizado possa ver.
  • Por outro lado, todos os arquivos PHP neste artigo estão armazenados no root de documento do s rvidor da Web.
  • lembre-se que comentários em um arquivo .ini começa com ponto e vírgula; comentários do tipo PHP não funcionarão.

A respeito da amostra de aplicativo

Um dos primeiros serviços a serem chamados de nuvem, o S3 do Amazon é um sistema de arquivo distribuído que fornece armazenagem on-line ilimitada. O modelo de dados S3 tem dois conceitos: o depósito e o objeto. Um depósito pode conter um número infinito de objetos, cada qual com seus dados e metadados. Um depósito não pode conter um outro depósito. Ao criar um depósito, o nome do depósito tem que ser único para todos os usuários do S3. Um objeto, depois de criado, somente pode ser substituído ou excluído; um objeto não pode ser modificado. Ao criar um objeto, é possível definir parâmetros de controle para ele. Por padrão, objetos são privados, mas se quiser podem ser compartilhados.

Nossa amostra de aplicativo é um gerenciador de arquivo baseado na Web para S3. Usando a classe Zend_Service_Amazon_S3 , serão criadas páginas PHP que permitem:

Fazer parte dos grupos de computação em nuvem do My developerWorks

Discutir assuntos e compartilhar recursos com outros desenvolvedores sobre arquitetura, ferramentas e impressionantes aplicativos de computação em nuvem, reutilizáveis e customizáveis no My developerWorks Cloud Computing group e no My developerWorks Cloud Computing Central group.

Ainda não é um membro do My developerWorks? Join now!

  • Veja todos os depósitos na sua conta S3.
  • Crie um novo depósito
  • Veja todos os objetos em um depósito
  • Crie um novo objeto
  • Exclua um objeto
  • Exclua um depósito

O aplicativo foi gravado como dois arquivos PHP: s3.php e bucketlist.php. O arquivo s3.php exibe todos os depósitos na sua conta, permitindo criar novos depósitos e excluindo os existentes. O arquivo bucketlist.php exibe todos os objetos em um determinado depósito. o que permite criar novos objetos e excluir os antigos. O arquivo bucketlist.php também exibe metadados sobre cada objeto e fornece um link direto para o objeto no Amazon. (se você não tem permissão para acessar tal objeto, surgirá uma mensagem de erro, como é de se esperar)


Criando um objeto Zend_Service_Amazon_S3

Obviamente, o primeiro passo é criar um objeto Zend_Service_Amazon_S3. A função construtor adota dois parâmetros: chave de acesso Amazon e chave secreta. Use a classe Credentials discutida anteriormente.

Listagem 5. Criando um objeto Zend_Service_Amazon_S3 object
<?php
require_once 'Zend/Service/Amazon/S3.php';
require_once 'Credentials.php';

// Initialize our credentials and create an S3 object
$creds = new Credentials;
$s3 = new Zend_Service_Amazon_S3($creds->getCredential('amazon', 'accessKey'),
                                 $creds->getCredential('amazon', 'secretKey'));
                                 ?>

Os dois arquivos PHP começam com essas linhas. Ao considerar depósitos ou objetos, o objeto $s3 criado aqui fará a maior parte do trabalho.


Relacione todos os depósitos na sua conta S3.

Quando o usuário carrega s3.php, ele verá uma listagem de todos os depósitos na sua conta do Amazon. O layout da tela é claro.

Figura 1. Lista de depósitos em uma conta
Lista de depósitos em uma conta

O método getBuckets() devolve uma matriz de nomes de depósitos. Cada nome de depósito é formatado como um link; clicar nesse link leva o usuário à página bucketlist.php. Próximo a cada nome de depósito está u botão Excluir que permite ao usuário excluir totalmente o depósito. (O código para manipular a exclusão de um depósito será abordado mais tarde.) Vamos ver agora como são geradas as linhas de tabela

Listagem 6. Criando uma lista de depósitos
<p>Here are your buckets:</p>
<table border='1' cellpadding='5'>
  <?php

  // Create a table row for each bucket.
  $list = $s3->getBuckets();
  foreach($list as $bucket) {
    echo "<tr><td>&nbsp;<a href='bucketlist.php?bucketname=$bucket'>$bucket</a>";
    echo "</td><td>";

    $contents = $s3->getObjectsByBucket($bucket);
    if (count($contents)) {
      echo "<form action='$PHP_SELF' method='post' ";
      echo "onsubmit='return confirm(\"Bucket $bucket is not empty! Do you ";
      echo "really want to delete it?\");'>";
      echo "<input type='hidden' name='deleteeverything' value='1'/>";
    }
    else {
      echo "<form action='$PHP_SELF' method='post' ";
      echo "onsubmit='return confirm(\"Do you really want to delete ";
      echo "bucket $bucket?\");'>";
    }
    echo "<input type='hidden' name='buckettodelete' value='$bucket'/>";
    echo "<input type='submit' value='Delete'>";
    echo "</form></td></tr>";
  }
  ?>
  </table>

Observe que o link transfere o nome do depósito para o arquivo bucketlist.php.


Criando um novo depósito

Criar um novo depósito pode ser um problema devido às restrições que o Amazon impôs aos nomes de depósitos:

  • Devem ter entre 3 e 63 caracteres.
  • Apenas podem conter letras minúsculas, números, pontos e travessão. Versões anteriores do S3 permitiam o sublinhado em nomes de depósito. Ao acessar um antiga conta S# é possível ver alguns depósitos que quebram essa regra.
  • Devemos começar com um número ou letra.
  • não pode ser um endereço IP (10.14.14.107 não é permitido).
  • não pode terminar com um travessão
  • não pode conter travessões ao lado de pontos (doug-.tidwell não é permitido).

A classe Zend_Service_Amazon_S3 fornece um nome de método_validBucketName() que faz a mesma verificação do nome de depósito. Infelizmente, o código para este método não está em sincronia com as mais recentes convenções de nomes impostas pelo Amazon. É possível que um nome de depósito passe no teste _validBucketName() mas mesmo assim vai falhar quando a solicitação for para o Amazon.

O formulário para o novo nome de depósito é claro.

Listagem 7. O formulário para criar um novo depósito
<h2>Create a new bucket</h2>
<form action="<?= $PHP_SELF ?>" method="post">
  <p>Enter a name for your new bucket: 
    <br/><br/>
    <input type="text" name="newbucketname" size="63"/>
    <br/><br/>
    <i>A bucket name can contain only lowercase letters, 
    periods and dashes, <br/>it should start with a
    letter or digit, and it can't be an IP address.</i>
    <br/><br/>
    <input type="submit" value="Create bucket"/>
  </p>
  </form>

Observe que o formulário envia o novo nome depósito para si mesmo. Ao clicar o botão Criar depósito faz o arquivo PHP invocar a si mesmo com um novo nome de depósito.

Figura 2. Formulário para criar novo depósito
Formulário para criar novo depósito

O código PHP para criar o novo depósito verifica se o nome é válido. Se o nome passa no teste apresentado pela classe Zend_Service_Amazon_S3 , o código chama o método createBucket(). Um código de resposta nonzero significa que o depósito foi criado com sucesso; um zero significa que o depósito já existe. Qualquer erro mais sério é confundido com exceção e manipulado adequadamente.

Listagem 8. Criando um novo depósito
<?php

if (array_key_exists('newbucketname', $_POST) &&
    strlen($_POST['newbucketname']) > 0) {
  try {
    if ($s3->_validBucketName($_POST['newbucketname'])) {
      $responseCode = $s3->createBucket($_POST['newbucketname']);
      if ($responseCode)
        echo "The bucket ".$_POST['newbucketname']." was created successfully.";
      else
        echo "The bucket ".$_POST['newbucketname']." already exists.";
    }

    else
      echo "Sorry, but ".$_POST['newbucketname']." isn't a valid bucket name.";
  }

  catch (Zend_Service_Amazon_S3_Exception $s3e) {
    ...
  }

  catch (Zend_Uri_Exception $urie) {
    ...
  }
  }

Relacionando todos os objetos em um depósito

Clicar em um nome de depósito em s3.php leva ao arquivo bucketlist.php. Esse arquivo exibe todos os objetos em um depósito, junto com metadados sobre cada objeto e um link para o seu conteúdo.

Figura 3. Lista de objetos em um depósito
Lista de objetos em um depósito

Zend fornece o extremamente útil método getObjectsByBucket(). Dado um nome de depósito, getObjectsByBucket() retorna uma matriz de nomes de objeto. Para exibir os metadados,o código chama o método getInfo() para cada item no depósito. Chamar getInfo() é totalmente improdutivo; procure nunca fazer isso em um aplicativo de produção.

Listagem 9. Recuperando e exibindo metadados
$stuff = $s3->getObjectsByBucket($bucketName);
    
if (count($stuff)) { 
?>
  <table border='1' cellpadding='5'>
  ...
  <?php  
  foreach ($stuff as $name) {
  ?>
    <tr>
      <?php
        echo "<td>&nbsp;<a href='$s3_url/$bucketName/$name'>$name</a></td>";
        $metadata = $s3->getInfo($bucketName."/".$name);
      ?>
      <td style='text-align: right;'>&nbsp;
        <?= number_format($metadata['size']) ?></td>
      <td>&nbsp;<?= $metadata['type'] ?></td>
      <td>&nbsp;<?= date("j M Y - H:i", $metadata['mtime']) ?></td>
      <td>
      ?>

Criando um novo objeto

de longe, esta é a tarefa mais complicada do exemplo. Para criar um novo objeto, o nome do objeto deve seguir as regras impostas pelo Amazon, e os dados do objeto devem estar disponíveis, O formulário pede que o usuário selecione um arquivo, uma política de acesso e um nome opcional para o objeto.

Figura 4. Formulário para criar novo objeto
Formulário para criar novo objeto

O código adota o arquivo selecionado através do botão Navegar e combina o nome de objeto (se houver) e o nome de arquivo básico para criar o nome do novo objeto. Por exemplo, se o arquivo selecionado for c:\Documents and Settings\My Documents\My Pictures\doug.jpg e o nome de objeto dorpictures, o código PHP tentará criar um objeto chamado pictures/doug.jpg.

Para carregar um arquivo com êxito, o formulário HTML deve usar o método POST e deve definir seu atributo enctype para multipart/form-data.

Listagem 10. Formulário para criar um novo objeto
<h2>Add an object to this bucket</h2>
<form action='<?= $PHP_SELF ?>' method='POST' enctype='multipart/form-data'>
  <input type='hidden' name='bucketname' value='<?= $bucketName ?>'/>
  <input type='file' name='objecttoadd'/>
  <p>Enter text to be appended to the object name (optional): 
  <input type='text' name='objectname'/> 
  <br/><i>Example: pictures/2009</i>
  <br/><br/>Who can see this object:
  <input type='radio' name='permissions' value='private'>Just me</input> &nbsp;
  <input type='radio' name='permissions' value='public' checked>Anybody</input>
  <br/><br/>
  <input type='submit' value='Add this object'/>
  </p>
  </form>

O código para criar o novo objeto parece com o da Listagem 11.

Listagem 11. Criando um novo objeto
try {
    $baseFileName = basename($_FILES['objecttoadd']['name']);
    if (strlen($_POST['objectname'])) 
      $newFileName = $_POST['objectname']."/".$baseFileName;
    else
      $newFileName = $baseFileName;
    $escapedFileName = str_replace(array("\\", "_", ":"), "-", $newFileName);

    if ($_POST['permissions'] == 'private')
      $permissions = array(Zend_Service_Amazon_S3::S3_ACL_HEADER 
                           => Zend_Service_Amazon_S3::S3_ACL_PRIVATE);
    else
      $permissions = array(Zend_Service_Amazon_S3::S3_ACL_HEADER 
                           => Zend_Service_Amazon_S3::S3_ACL_PUBLIC_READ);
          
    $s3->putObject($bucketName."/".$escapedFileName, 
                   file_get_contents($_FILES['objecttoadd']['tmp_name']),
                   $permissions);
    echo "The object $escapedFileName was created successfully.";
  }

  catch (Zend_Service_Amazon_S3_Exception $s3e) {
    ...
  }

  catch (Zend_Http_Client_Exception $hce) {
    ...
    }

O código usa as funções PHP basename() e str_replace() para recuperar o nome de arquivo básico e substituir qualquer barra invertida, sublinhado ou pontos com travessão. O valor permissions do formulário é usado para determinar a política de acesso para o novo objeto. Se o usuário seleciona "Apenas eu," o objeto é marcado como privado; se não, ficará publicamente acessível. (S3 e Zend Framework suportam duas outras opções para política de acesso: uma é compartilhar o objeto apenas com determinados usuários S3 autenticados; a outra é compartilhar o objeto de tal forma que o cobre do solicitante do objeto a largura de banda necessária para entregar o objeto.)


Excluindo um objeto

Se o usuário clicar o botão Excluir próximo a um objeto, será solicitada a confirmação da escolha.

Figura 5. Excluindo um objeto
Excluindo um objeto

O botão Excluir e o texto da caixa de mensagem são gerados quando for criada a listagem do depósito. O código PHP para criar o botão Excluir parece o da Listagem 12.

Listagem 12. Formulário para confirmar exclusão de um objeto
<form action='<?= $PHP_SELF ?>' method='post'
  onsubmit='return confirm("Do you really want to delete this object?");'>
  <input type='hidden' name='objecttodelete' value='$name'/>
  <input type='hidden' name='bucketname' value='$bucketName'/>
  <input type='submit' value='Delete'/>
  </form>

Assim como todos os formulários para criar ou excluir depósitos ou objetos, a ação do formulário é invocar a si mesmo. A função JavaScript confirm() cancela a ação se o usuário clicar Cancelar. Imaginando que o usuário escolheu prosseguir com a exclusão do objeto, o código para realmente executar a exclusão é simples.

Listagem 13. Excluindo um objeto
try {
  $s3->removeObject($bucketName."/".$_POST['objecttodelete']);
}

catch (Zend_Service_Amazon_S3_Exception $s3e) {
  ...
  }

As recargas da página com uma exibição atualizada de qualquer coisa contida pelo depósito agora.

Nota: Amazon S3 é um sistema de arquivo distribuído projetado para lidar com múltiplas falhas e dispositivos individuais. Quando um objeto é adicionado ou excluído, algumas vezes ocorre um atraso de propagação conforme as mudanças são refletidas pelo sistema. Em alguns casos, a página recarregada mostrará o objeto excluído como ainda no depósito, em geral com um tamanho zero. Recarregar a pagina geralmente permite a S3 tempo suficiente para se ressincronizar.


Excluindo um depósito

A operação mais drástica suportada pelo nosso exemplo é excluir um depósito. Os nomes de depósitos são únicos por todo o S3, portanto há uma chance de usuário poder excluir um depósito e tentar recriá-lo mais tarde, apenas para descobrir que nesse meio tempo alguém criou um depósito com aquele nome. Para deixar o exemplo ainda mais convincente (ou perigoso), o código permite ao usuário excluir um depósito que não está vazio. O recurso de excluir um depósito não vazio não é fornecido no S3. Essa é uma função implementada aqui com a ajuda de um método de conveniência fornecido pelo Zend.

Se o usuário clicar o botão Excluir próximo a um depósito vazio, será solicitado a confirmar a escolha.

Figura 6. Excluindo um depósito vazio
Excluindo um depósito vazio

Se o usuário clicar o botão Excluir para um depósito que não está vazio, ele é recebido com uma mensagem ainda mais urgente.

Figura 7. Excluindo um depósito que não está vazio
Excluindo um depósito que não está vazio

Se um determinado depósito estiver vazio foi definido quando a lista de depósitos foi criada. Seguindo o código PHP que cria a lista de depósitos.

Listagem 14. Gerando mensagens de alertas para depósitos preenchidos
  $list = $s3->getBuckets();
  foreach($list as $bucket) {
    ...

    $contents = $s3->getObjectsByBucket($bucket);
    if (count($contents)) {
      echo "<form action='$PHP_SELF' method='post' ";
      echo "onsubmit='return confirm(\"Bucket $bucket is not empty! Do you ";
      echo "really want to delete it?\");'>";
      echo "<input type='hidden' name='deleteeverything' value='1'/>";
    }
    else {
      echo "<form action='$PHP_SELF' method='post' ";
      echo "onsubmit='return confirm(\"Do you really want to delete ";
      echo "bucket $bucket?\");'>";
    }
    echo "<input type='hidden' name='buckettodelete' value='$bucket'/>";
    echo "<input type='submit' value='Delete'>";
    echo "</form></td></tr>";
  }
  ?>
  </table>

Conforme o código PHP cria a tabela que relaciona todos os depósitos na conta do usuário, ele utiliza getObjectsByBucket() para obter uma matriz de todos os nomes de objeto em cada depósito. Se a matriz não estiver vazia, o código gera uma mensagem severa de confirmação.

Para fazer o trabalho real de excluir o sito, o código atravessa várias etapas. Primeiro, verifica se o nome do depósito é válido. Se for, verifica o conteúdo do depósito para ver se está vazio. Se estiver, o depósito é excluído. Se não, o código examina o parâmetro deleteeverything. Se este parâmetro estiver definido como verdadeiro, o código exclui o depósito mesmo de qualquer maneira.+ O código usa o método cleanBucket() fornecido por Zend Framework. O método cleanBucket() obtém uma lista de todos os objetos em um depósito, e então exclui um por um até que o depósito esteja vazio. Quando o depósito está finalmente vazio, então é excluído.

Listagem 15. Excluindo um depósito
try {
  if ($s3->_validBucketName($_POST['buckettodelete'])) {
    $stuff = $s3->getObjectsByBucket($_POST['buckettodelete']);
    if (!count($stuff)) 
      $responseCode = $s3->removeBucket($_POST['buckettodelete']);
    else 
      if (array_key_exists('deleteeverything', $_POST)) {
        $s3->cleanBucket($_POST['buckettodelete']);
        $responseCode = $s3->removeBucket($_POST['buckettodelete']);
      }
      ...

Resumo

Este artigo apresentou um navegador de depósito construído na classe Zend_Service_Amazon_S3. Objetos armazenados na nuvem podem ser visualizados, excluídos ou substituídos, e novos objetos podem ser facilmente carregados. E o que é melhor, sem a necessidade de chamadas REST ou SOAP . Um programador usando o Zend Framework não precisa calcular assinaturas ou considerar códigos de resposta HTTP; eles simplesmente trabalham com seus dados. Os artigos seguintes desta série demonstram outras classes Zend que simplifica a computação em nuvem.

Recursos

Aprender

Obter produtos e tecnologias

Discutir

Comentários

developerWorks: Conecte-se

Los campos obligatorios están marcados con un asterisco (*).


Precisa de um ID IBM?
Esqueceu seu ID IBM?


Esqueceu sua senha?
Alterar sua senha

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


A primeira vez que você entrar no developerWorks, um perfil é criado para você. Informações no seu perfil (seu nome, país / região, e nome da empresa) é apresentado ao público e vai acompanhar qualquer conteúdo que você postar, a menos que você opte por esconder o nome da empresa. Você pode atualizar sua conta IBM a qualquer momento.

Todas as informações enviadas são seguras.

Elija su nombre para mostrar



Ao se conectar ao developerWorks pela primeira vez, é criado um perfil para você e é necessário selecionar um nome de exibição. O nome de exibição acompanhará o conteúdo que você postar no developerWorks.

Escolha um nome de exibição de 3 - 31 caracteres. Seu nome de exibição deve ser exclusivo na comunidade do developerWorks e não deve ser o seu endereço de email por motivo de privacidade.

Los campos obligatorios están marcados con un asterisco (*).

(Escolha um nome de exibição de 3 - 31 caracteres.)

Ao clicar em Enviar, você concorda com os termos e condições do developerWorks.

 


Todas as informações enviadas são seguras.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=80
Zone=Software livre, Cloud computing
ArticleID=439932
ArticleTitle=Computação em nuvem com PHP, Parte 1: Usando Amazon S3 com o Zend Framework
publish-date=11022009