Aprendendo PHP, Parte 2: Fazer Upload dos Arquivos e Usar XML para Armazenar e Exibir Informações de Arquivo

Este tutorial é a Parte 2 de uma série "Aprendendo PHP" em três partes que ensina como usar PHP através da construção de uma aplicação simples de fluxo de trabalho. Faça este tutorial se tiver um entendimento básico de PHP e quiser aprender sobre como fazer upload de arquivos a partir do navegador, sessões ou usando PHP para processar XML.

Tyler Anderson, Engineer, Backstop Media

Tyler's photoTyler Anderson graduou-se em ciência da computação em 2004 e concluiu seu mestrado em engenharia elétrica e da computação em 2005 na Brigham Young University. Ele trabalhou para a Stexar Corp. como engenheiro de projetos, em pesquisa e desenvolvimento, de maio de 2005 a agosto de 2006. Desde sua descoberta pela Backstop Media LLC no início de 2005, ele tem escrito e codificado muitos artigos e tutoriais para a IBM developerWorks e DevX.com.



Nicholas Chase, Web Developer, Author, Consultant

Nicholas Chase esteve envolvido no desenvolvimento de Web sites para empresas como a Lucent Technologies, a Sun Microsystems, a Oracle e a Tampa Bay Buccaneers. Nick é professor de física do ensino médio, gerente de instalação de lixo radioativo de nível baixo, editor de revista on-line de ficção científica, engenheiro de multimídia, instrutor Oracle e o Executivo Chefe em Tecnologia de uma empresa de comunicações interativas. Ele é o autor de diversos livros, incluindo XML Primer Plus (Sams).



21/Jun/2005

Antes de Começar

Sobre Este Tutorial

Este tutorial ensina como usar PHP demonstrando a construção de uma aplicação de fluxo de trabalho baseada na Web. "Aprendendo PHP, Parte 1" cobriu o básico, como sintaxe, funções, trabalhar com envios de formulários HTML e bancos de dados e como criar um processo pelo qual um novo usuário pode se registrar para uma conta.

Neste tutorial, você irá possibilitar que usuários façam upload de arquivos para o sistema usando seus navegadores e irá usar XML para armazenar e exibir informações sobre cada arquivo.

Parte 3 verifica o uso de autenticação HTTP, assim como a proteção de arquivos, simplificando-os a partir de um diretório acessível não pela Web. Verá também como criar objetos e usar exceções.

Ao longo deste tutorial, o seguinte será examinado:

  • Criar e usar sessões e informações de sessões.
  • Fazer upload de arquivos a partir do navegador.
  • Criar XML usando o Document Object Model (DOM).
  • Manipular dados XML usando DOM.
  • Criar um manipulador de conteúdos Simple API for XML (SAX).
  • Ler dados XML usando SAX.

Quem Deve Fazer este Tutorial?

Este tutorial é a Parte 2 de uma série em três partes projetadas para ensinar os diversos aspectos de trabalhar com PHP enquanto se constrói uma aplicação de fluxo de trabalho. Faça este tutorial se tiver um entendimento básico de PHP e quiser aprender sobre como fazer upload de arquivos a partir do navegador, sessões ou usando PHP para processar XML.

Este tutorial supõe uma familiaridade básica com PHP no nível discutido na Parte 1 desta série. Isso inclui entendimento básico das estruturas de controle, como loops e instruções if-then, assim como de funções, e trabalhar com envios de formulários HTML e bancos de dados. A familiaridade com XML é útil, mas não necessária. (Mais informações sobre esses tópicos podem ser encontradas em Recursos.)

Pré-requisitos

Para acompanhar, é necessário ter um servidor da Web, PHP e um banco de dados instalado e disponível. A menos que vá usar uma conta de hosting externa, faça download e instale os seguintes pacotes:

Servidor da Web -- Independentemente de se está no Windows® ou Linux® (ou Mac OS X, se essa for a questão), tem a opção de usar o servidor da Web Apache. Sinta-se à vontade em escolher V1.3 ou V2.0, mas as instruções deste tutorial irão se concentrar na 2.0. Faça download do Apache. Se estiver no Windows, também pode usar Internet Information Services, que faz parte do Windows.

PHP -- É claro que também precisará de uma distribuição de PHP. PHP V4 e PHP V5 estão em uso enquanto este artigo é escrito, mas, devido às mudanças no PHP V5, vamos nos concentrar nessa versão. (A versão não é extremamente importante neste tutorial, mas faz diferença para a última parte desta série.) Faça download do PHP.

Banco de dados -- Parte deste projeto envolve salvar dados em um banco de dados, portanto, precisará de um desses também. Neste tutorial, vamos nos concentrar no MySQL, pois é tão comumente usado com PHP. Faça download do MySQL.


Introdução: Criando uma Sessão

O Processo de Login, Parte 1

A Parte 1 desta série examinou o trabalho com informações enviadas de um formulário HTML e a interação com um banco de dados, criando um sistema de registro para novos usuários. Os arquivos finais podem ser localizados em Recursos.

Uma coisa que não foi feita, no entanto, foi criar uma página através da qual o usuário poderia efetuar login no sistema. Isso será feito agora, com uma revisão resumida do que já foi coberto.

Primeiro, crie um novo arquivo em branco e salve-o como login.php no mesmo diretório que o registration.php. Inclua o seguinte código:

<?php
include("top.txt");
   require("scripts.txt");
?>

<h1>Please log in</h1>
<form action="login_action.php" method="post">
Username: <input type="text" name="username" /><br />
Password: <input type="password" name="password" /><br />
<input type="submit" value="Log In" />
</form>

<?php
   include("bottom.txt");
?>

Para revisar, quando o usuário envia o formulário, PHP criará uma array de informações, $_POST, com duas entradas: username e password. Essas informações serão verificadas com relação ao banco de dados. Quando essa página é inserida no navegador, servidor inclui os elementos da interface.

Figura 1. Página Login.php com Elementos da Interface
Página Login.php com Elementos da Interface

O Processo de Login, Parte 2

Crie outra nova página e salve-a como login_action.php. Inclua o seguinte código:

<?php
include("top.txt");
   require("scripts.txt");

   db_connect();

   $username = $_POST["username"];
   $password = $_POST["password"];
   $sql = "select * from users where username='".$username.
                            "' and password='".$password."'";

   $result = mysql_query($sql);
   $row = mysql_fetch_row($result);
   if ($row) {
      echo "You are logged in.  Thank you!";
   } else {
      echo "There is no user account with that username and password.";
   }

   mysql_close();

   include("bottom.txt");
?>

Após incluir os elementos da interface para a parte superior da página, abra uma conexão com o banco de dados usando a função db_connect() , que é definida no arquivo scripts.txt. Quando tiver uma conexão, use as informações enviadas para criar uma instrução SQL que procurar uma conta correspondente e execute-a com relação ao banco de dados.

Iniciando uma Sessão

Solicita-se que o usuário efetue login para que o site saiba qual usuário ele é. Dessa forma, o site sabe quais arquivos o usuário tem permissão de ver. É necessário fazer mais do que simplesmente efetuar login do usuário, no entanto. Como as coisas se encontram no momento, assim que sair desta página, as informações do usuário se vão.

O que deve fazer é criar uma sessão de forma que o servidor saiba quais pedidos agrupar. Também é possível associar informações -- como o nome de usuário -- à sessão.

Para começar. será necessário criar a sessão. A função session_start() verifica se existe uma sessão e, se não existir nenhuma sessão, a função inicia uma.

O uso de session_start() ou, na verdade, qualquer coisa feita para configurar as informações da sessão tem uma grande restrição. Deve ocorrer antes de qualquer conteúdo, inclusive os elementos da interface, ir para o navegador.

Portanto, vamos incluir, imediatamente, a sessão e reestruturar login_action.php:

<?php
   session_start();

   require("scripts.txt");

   db_connect();

   $username = $_POST["username"];
   $password = $_POST["password"];
   $sql = "select * from users where username='".$username.
                            "' and password='".$password."'";

   $loginOk = false;

   $result = mysql_query($sql);
   $row = mysql_fetch_row($result);
   if ($row) {
     $loginOk = true;
   }

   mysql_close();

   include("top.txt");

   if ($loginOk) {
      echo "You are logged in.  Thank you!";
   } else {
      echo "There is no user account with that username and password.";
   }

   include("bottom.txt");

?>

O que foi feito aqui foi reestruturar a página de forma que seja possível realizar todo seu trabalho de sessão antes de emitir a saída de qualquer coisa no navegador.

Preenchendo a Sessão

É claro que não há razão para criar uma sessão a menos que haja informações a serem passadas de pedido para pedido. Neste caso, é possível passar o nome de usuário e o endereço de e-mail, portanto, eles são incluídos na sessão:

<?php
   session_start();

   require("scripts.txt");

   db_connect();

   $username = $_POST["username"];
   $password = $_POST["password"];
   $sql = "select * from users where username='".$username.
                            "' and password='".$password."'";

   $result = mysql_query($sql);
   $row = mysql_fetch_row($result);
   $loginOk = false;
   if ($row) {

      $loginOk = true;
      $_SESSION["username"] = $row["username"];
      $_SESSION["email"] = $row["email"];
   }

   mysql_close();

   include("top.txt");

   if ($loginOk) {
      echo "You are logged in.  Thank you, ".$username."!";
   } else {
      echo "There is no user account with that username and password.";
   }

   include("bottom.txt");

?>

Como $_POST, $_SESSION é uma array associativa. Também é uma variável super global , que contém seu valor através de diversos pedidos. Dessa forma, é possível fazer referência a ela a partir de outra página.

Agora, se estiver usando uma versão de PHP posterior à V4.3.2, poderá ver uma mensagem indicando que seu script pode estar dependendo de um erro que possibilita configurar a variável $_SESSION no escopo global. Se esse for o caso, será necessário localizar seu arquivo php.ini e assegurar que as seguintes variáveis sejam configuradas:

session.bug_compat_42 = 1
session.bug_compat_warn = 0

Após alterar esses valores, será necessário parar e reiniciar seu servidor da Web para que as mudanças tenham efeito.

Usando uma Sessão Existente

A função session_start() é inteligente o suficiente para saber se há uma sessão existente, portanto, pode seguir em frente e incluí-la na inclusão para a parte superior do arquivo top.txt:

<?
   session_start();
?>
<html>
<head>
<title>Workflow System</title>
</head>
<body>
<table cellspacing="10">
<tr><td colspan="2"><h2>The Workflow System</h2></td></tr>
...

Quando PHP encontra a função session_start() , junta-se à sessão existente em andamento ou inicia uma nova, se necessário. Dessa forma, outras páginas têm acesso à array $_SESSION . Por exemplo, pode-se procurar o valor de $_SESSION["username"] na seção de navegação:

<tr>
   <td width="30%" valign="top">
      <h3>Navigation</h3>

<?php
   if (isset($_SESSION["username"]) || isset($username)){
?>
      <p>You are logged in as <b><?=$_SESSION["username"].$username?></b>.  You can
<a href="logout.php">logout</a> to login as a different user.</p>
<?php
   } else {
?>
      <p><a href="registration.php">Register</a></p>
      <p><a href="login.php">Login</a></p>
<?php
   }
?>
   </td>
   <td>
      <td>

Agora, deve estar pensando por que também está verificando a variável $username . A razão é esta: ao configurar a variável $_SESSION , as mudanças não são disponibilizadas até a próxima vez que session_start() for chamada. Portanto, na página login_action.php em si, ainda não estará disponível, mas $username estará, conforme mostrado na Figura 2.

Figura 2. Página Login_action.php com a Variável $username
Página Login_action.php com a Variável

Limpando Dados

Quando tiver concluído sua sessão, pode limpar seus dados ou encerrar a sessão de vez. Por exemplo, pode ser que queira efetuar logout de um usuário sem encerrar a sessão. Cria um novo arquivo chamado logout.php e inclua o seguinte código:

<?
   session_start();
   unset($_SESSION["username"]);
   unset($_SESSION["email"]);

   include("top.txt");
   echo "Thank you for using the Workflow System.  You may <a href=\"login.php\
">log in again</a>.";
   include("bottom.txt");
?>

Executar essa página apontando o navegador para http://localhost/logout.php mostra que os valores foram limpos, conforme mostrado na Figura 3.

Figura 3. Página com Valores Limpos
Página com Valores Limpos

Uma maneira mais simples de limpar os dados é encerrando a sessão:

<?
   session_start();
   session_destroy();

   include("top.txt");
   echo "Thank you for using the Workflow System.  You may <a
   href=\"login.php\">log in again</a>.";
   include("bottom.txt");
?>

Observe que será necessário usar session_start() para se juntar à sessão atual antes de poder destruí-la. Essa etapa limpa todos os valores associados à sessão.


Fazendo Upload dos Arquivos

Como Funciona o Upload

Além das informações de texto, é possível usar formulários HTML para enviar documentos e é assim que se possibilita que usuários incluam arquivos no sistema. A seguir, veja como o processo funciona:

  1. Os usuários carregam um formulário que possibilita que eles escolham um arquivo para fazer upload.
  2. Os usuários enviam o formulário.
  3. O navegador envia o arquivo e as informações sobre ele para o servidor como parte do pedido.
  4. O servidor salva o arquivo em um local de armazenamento temporário.
  5. A página PHP que está processando o envio do formulário move o arquivo do armazenamento temporário para o permanente.

Vamos iniciar o processo criando o formulário em si.

O Formulário de Upload

O formulário que está sendo usado para fazer upload de arquivos é semelhante àqueles usados para as páginas de registro e de login, com duas exceções importantes:

<?php
   include("top.txt");
?>

<h3>Upload a file</h3>

<p>You can add files to the system for review by an administrator.
Click <b>Browse</b> to select the file you'd like to upload,
and then click <b>Upload</b>.</p>

<form action="uploadfile_action.php" method="POST"
enctype="multipart/form-data">
<input type="file" name="ufile" \>
<input type="submit" value="Upload" \>
</form>

<?php
   include("bottom.txt");
?>

O atributo enctype indica ao navegador que as informações que envia devem estar em um formato específico que possibilita diversas seções de informações, em vez de apenas uma lista de pares nome-valor.

A entrada do arquivo fornece uma caixa que possibilita que o usuário clique em Procurar... e escolha o arquivo, conforme mostrado na Figura 4.

Figura 4. Escolher um Arquivo para Upload
Escolher um Arquivo para Upload

Observe que foi incluído um link para esse arquivo, uploadfile.php para a página top.txt , para que apareça no navegador.

As Informações Transferidas por Upload

Ao fazer upload de um arquivo através do navegador, PHP recebe uma array de informações sobre ele. Essas informações podem ser localizadas na array $_FILE , baseada no nome do campo de entrada. Por exemplo, seu formulário possui uma entrada de arquivo com o nome ufile, de forma que todas as informações sobre esse arquivo estejam contidas na array $_FILE['ufile'].

Essa array permite que o usuário faça upload de diversos arquivos. Desde que cada arquivo tenha seu próprio nome, terá sua própria array.

Agora, observe que "$_FILE" está sendo chamada de uma array. Na Parte 1 desta série, havia uma situação na qual o valor de uma array era uma array quando foram passados diversos valores de formulário com o mesmo nome para a senha. Nesse caso, cada valor da array $_FILE é uma array associativa. Por exemplo, seu arquivo ufile tem as seguintes informações:

  • $_FILE['ufile']['name'] -- O nome do arquivo (por exemplo, uploadme.txt)
  • $_FILE['ufile']['type']: O tipo do arquivo (por exemplo, image/jpg)
  • $_FILE['ufile']['size'] -- O tamanho, em bytes, do arquivo que foi transferido por upload
  • $_FILE['ufile']['tmp_name'] -- O nome temporário e o local do arquivo transferido por upload no servidor
  • $_FILE['ufile']['error'] -- O código de erro, se houver algum, que resultou desse upload

Sabendo quais informações devem estar presentes, deve-se verificar se um arquivo foi realmente transferido por upload antes de executar qualquer processamento.

Verificar um Arquivo

Antes de executar qualquer ação referente ao arquivo, é necessário saber se um arquivo foi primeiramente transferido por upload. Cria a página de ação para esse formulário, uploadfile_action.php, e inclua o código a seguir:

<?php
   include("top.txt");

   if(isset($_FILES['ufile']['name'])){
       echo "Uploading: ".$_FILES['ufile']['name']."<br />";
   } else {
       echo "You need to select a file.  Please try again.";
   }

   include("bottom.txt");
?>

Em seguida, o arquivo será salvo.

Salvar o Arquivo

Antes de iniciar o processo de salvar o arquivo transferido por upload, é necessário decidir onde colocá-lo. Até o arquivo ter sido aprovado, não deve estar acessível a partir do Web site, portanto, crie um diretório que não esteja na raiz do documento principal.

Nesse caso, use /var/www/hidden/. Esse é o local para onde todos os seus arquivos irão, portanto, é uma boa ideia definir uma constante. Abra scripts.txt e inclua a seguinte definição:

...
  mysql_select_db($db);

}
   define(UPLOADEDFILES, "/var/www/hidden/");
?>

Agora, é possível usar essa definição na página de upload, desde que scripts.txt seja incluído nessa página, assim como:

<?php
   include("top.txt");
   include("scripts.txt");

   if(isset($_FILES['ufile']['name'])){
       echo "Uploading: ".$_FILES['ufile']['name']."<br>";

       $tmpName = $_FILES['ufile']['tmp_name'];
       $newName = UPLOADEDFILES . $_FILES['ufile']['name'];

       if(!is_uploaded_file($tmpName) ||
                            !move_uploaded_file($tmpName, $newName)){
            echo "FAILED TO UPLOAD " . $_FILES['ufile']['name'] .
                 "<br>Temporary Name: $tmpName <br>";
       } else {
            echo "File uploaded.  Thank you!";
       } 

   } else {
     echo "You need to select a file.  Please try again.";
  }
   include("bottom.txt");
?>

Primeiro, obtém-se o local atual do arquivo e seu nome temporário (tmp_name) e determina-se onde deve ser colocado usando a constante definida.

Em seguida, na instrução if-then, são feitas duas coisas. É verificado para assegurar se o arquivo que está tentando-se mover é realmente um arquivo que foi transferido por upload para o servidor, em vez de um arquivo, como /etc/passwd, que o usuário nos enganou para agir sobre o mesmo. Se a função is_uploaded_file() retornar false, então, seu oposto !is_uploaded_file(), é true e PHP segue em frente para exibir a mensagem de erro.

Se, por outro lado, esse teste retornar true, o que significa que é um arquivo transferido por upload, então poderá tentar movê-lo de seu local atual para um novo local. Se essa movimentação não funcionar, retorna false e, novamente, seu oposto é true, portanto, a mensagem de erro é exibida.

Ou seja, se não for um arquivo transferido por upload ou não for possível movê-lo, uma mensagem de erro será exibida. Caso contrário, a mensagem de êxito será exibida (consulte a Figura 5).

Figura 5. A Mensagem de Êxito
A Mensagem de Êxito

Agora, que você possui o arquivo, é necessário registrar suas informações para recuperação posterior.


Usando XML: DOM

O que É XML?

Hoje em dia, é difícil de realizar muita programação sem da de encontro com XML de alguma forma. Felizmente, não é um assunto difícil de entender. Na verdade, provavelmente, já vem lidando com um parente de XML: HTML. Considere esta página de HTML V4.01:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
            "http://www.w3.org/TR/html4/loose.dtd">
<HTML>
<HEAD>
   <TITLE>Workflow System</TITLE>
</HEAD>
<BODY>
   <H1 align="center">Welcome to the Workflow System!</H1>
   We're glad you could make it.
   <P>
   Don't forget to log in!
</BODY>
</HTML>

Essa página tem muito em comum com XML. Inicialmente, é formada por elementos , como HEAD ou BODY, marcados por tags, como <BODY> para iniciar e </BODY> para terminar. Esses elementos podem conter outros elementos (como TITLE) ou texto (como Workflow System). Também podem ter atributos, como align="center".

Mas XML tem algumas restrições que não se aplicam a HTML. Por exemplo, XML deve ser bem formado, o que significa que para cada tag inicial (como <H1>), deve-se ter uma tag final (como </H1>. Isso significa que sua tag <P> deve ter uma tag final: </P>. (Como alternativa, é possível gravá-la como o elemento vazio do atalho: <P />.) Além disso, XML faz distinção entre maiúsculas e minúsculas, portanto, seria necessário fechar <P> com </P>, não com </p>.

Nesta seção, será criado um arquivo XML que registra informações sobre documentos transferidos por upload pelos usuários.

Como Armazenar Informações

Ao longo das duas próximas seções, você lidará com um arquivo XML que lista informações sobre documentos transferidos por upload pelos usuários. O arquivo listará cada documento, seu status, quem o transferiu por upload e informações sobre o próprio documento. O arquivo também listará informações estatísticas sobre o sistema geral.

O arquivo terá a seguinte aparência:

<?xml version="1.0"?>
<workflow>
   <statistics total="2" approved="1"/>
   <fileInfo status="approved" submittedBy="roadnick2">
      <approvedBy>tater</approvedBy>
      <fileName>timeone.jpg</fileName>
      <location>/var/www/hidden/</location>
      <fileType>image/jpeg</fileType>
      <size>2020</size>
   </fileInfo>
   <fileInfo status="pending" submittedBy="roadnick">
      <approvedBy/>
      <fileName>timeone.jpg</fileName>
      <location>/var/www/hidden/</location>
      <fileType>image/jpeg</fileType>
      <size>2020</size>
   </fileInfo>
</workflow>

Incluímos espaçamento aqui para tornar as coisas mais claras, mas essa é a estrutura geral do arquivo. Cada documento terá seu próprio elemento fileInfo , que inclui atributos sobre seu status e proprietário e contém informações sobre o próprio arquivo. O documento de estatísticas também lista informações sobre o próprio arquivo.

Para manipular essas informações, será usado o Document Object Model (DOM).

O que É DOM?

O Document Object Model (DOM) é uma maneira de representar dados XML como uma árvore hierárquica de informações. Veja, por exemplo, este elemento fileInfo :

   <fileInfo status="approved" submittedBy="roadnick2">
      <approvedBy>tater</approvedBy>
      <fileName>timeone.jpg</fileName>
      <location>/var/www/hidden/</location>
      <fileType>image/jpeg</fileType>
      <size>2020</size>
   </fileInfo>

Cada informação de um documento XML é representada como um tipo de nó. Por exemplo, aqui se vê um nó de elemento fileInfo ; um nó de atributo status e diversos nós de texto, incluindo tater, timeone.jpg e 2020. Até mesmo cada espaço em branco entre os elementos é considerado um nó de texto.

DOM organiza os nós em um relacionamento pai-filho. Por exemplo, o elemento approvedBy é um filho do elemento fileInfo e o texto tater é um filho do elemento approvedBy . Esse relacionamento significa que o elemento fileInfo possui 11 nós-filhos; cinco elementos e seis nós de texto de espaço em branco.

Diversas APIs existem para possibilitar o trabalho com objetos DOM. Versões anteriores do PHP implementavam uma estrutura semelhante ao DOM, mas a estrutura não se entrosava realmente bem com os métodos e definições do DOM real (mantidas pelo W3C). Portanto, o PHP V5 possui um novo conjunto de operações do DOM que são muito mais próximas do padrão.

Essa nova API será usada para criar e modificar as informações do documento.

Uma Palavra Rápida sobre Objetos

A Parte 3 desta série falará sobre objetos e programação orientada a objetos em PHP mais detalhadamente, mas a API DOM e a API SAX discutidas nas seções a seguir usam isso, portanto, antes de prosseguir, será necessário ter pelo menos um entendimento básico do que são objetos e como funcionam.

Pense em um objeto como uma coleta de funções; por exemplo, pode-se criar uma classe ou um modelo de objeto que tenha a seguinte aparência:

class Greeting{
    function getGreeting(){
       return "Hello!";
   };
   function getPersonalGreeting($name){
       return "Hello, ".$name."!";
   }; 
}

Ao criar um objeto, é possível então fazer referência às suas funções. Por exemplo:

$myObject = new Greeting();
$start = $myObject->getPersonalGreeting("Nick");

Neste caso, o objeto myObject é criado e pode ser referido com uma variável, exatamente como uma cadeia ou um número. Pode-se então fazer referência às suas funções usando a anotação -> . Além disso, é exatamente como chamar uma função regular.

Isso é tudo que se precisa saber sobre objetos por ora.

Preparando para Salvar as Informações

Agora, você está pronto para iniciar a criação do arquivo de informações do documento. Por fim, você irá criar uma função chamada save_document_info(), portanto, inicie incluindo uma chamada para essa função em uploadfile_action.php:

  if(!is_uploaded_file($tmpName) ||
     !move_uploaded_file($tmpName, $newName)){
    echo "FAILED TO UPLOAD " . $_FILES['ufile']['name'] .
         "<br>Temporary Name: $tmpName <br>";
  } else {

    save_document_info($_FILES['ufile']);

  } 
...

Você deseja passar informações somente sobre o arquivo que foi transferido por upload, portanto, as coisas podem ser facilitadas para save_document_info() passando somente as informações sobre o arquivo ufile, em vez de sobre todo a array $_FILES .

Agora chegou a hora de criar a função.


Funções

Criar o Documento DOM

Primeiro, cria-se um objeto Document DOM que pode ser usado para manipular os dados. Abra o arquivo scripts.txt e inclua o seguinte código:

...
   define(UPLOADEDFILES, "/var/www/hidden/");

   function save_document_info($fileInfo){

       $doc = new DOMDocument('1.0');

   }
?>

O processo real de criação de um objeto Document , neste caso chamado de $doc, é direto. A classe DOMDocument faz parte do núcleo do PHP V5. Esse objeto é usado para executar a maior parte de suas ações nos dados.

Criar um Elemento

Agora, que há um Document funcional, é possível usá-lo para criar o elemento principal ou raiz do documento:

...
function save_document_info($fileInfo){

   $doc = new DOMDocument('1.0');
   $root = $doc->createElement('workflow');
   $doc->appendChild($root);

}
...

Aqui, indica-se ao objeto $doc que deve criar um novo elemento e retorná-lo à variável $root . Indica-se então a Document que deve incluir esse elemento como seu filho.

Mas o que acontece se esse documento for salvo como um arquivo?

Salvar o Documento em um Arquivo

Uma vantagem de usar PHP para processar seu XML é que PHP fornece uma maneira fácil de salvar o conteúdo de um Document em um arquivo. (Acredite se quiser, mas nem sempre é tão fácil assim.) Para ver o que está realmente sendo gerado, inclua o código a seguir em save_document_info():

...
function save_document_info($fileInfo){

   $doc = new DOMDocument('1.0');
   $root = $doc->createElement('workflow');
   $doc->appendChild($root);

   $doc->save(UPLOADEDFILES."docinfo.xml");

}
...

A constante UPLOADEDFILES foi definida anteriormente, portanto, pode simplesmente seguir em frente e fazer referência a ela agora, colocando o novo arquivo no mesmo diretório. Se agora fizer upload de um arquivo através do navegador, o arquivo docinfo.xml deve ter a seguinte aparência:n

<?xml version="1.0"?>
<workflow/>

Não se preocupe com a primeira linha, é a declaração XML e é padrão, mas é opcional (na maioria dos casos).

Observe que seu elemento foi salvo, mas como não incluiu ainda no mesmo nenhum filho nem conteúdo realmente, é gravado como um elemento vazio.

Agora, vamos incluir um elemento mais complicado.

Criar Atributos

Inicie a inclusão de informações reais no arquivo. Um arquivo já foi criado para testar a etapa anterior, mas até salvar completamente as informações do primeiro arquivo, pode-se supor que ainda esteja criando o arquivo docinfo.xml.

Inicie criando o elemento statistics :

...
function save_document_info($fileInfo){

   $doc = new DOMDocument('1.0');
   $root = $doc->createElement('workflow');
   $doc->appendChild($root);

   $statistics = $doc->createElement("statistics");
   $statistics->setAttribute("total", "1");
   $statistics->setAttribute("approved", "0");
   $root->appendChild($statistics);

   $doc->save(UPLOADEDFILES."docinfo.xml");

}
...

Observe que Document será usado para criar o novo elemento, desta vez chamado de statistics. O Document age como uma "fábrica" para a maioria de seus objetos.

Quando tiver o objeto Element , $statistics, é possível usar suas funções integradas para configurar dois atributos: total e approved. Após fazer isso, deve incluir esse elemento como um filho de $root, em vez de um filho de $doc. Se salvar o arquivo, poderá ver a diferença:

<?xml version="1.0">
<workflow><statistics total="1" approved="0"/></workflow>

Perceberá duas coisas aqui. Primeiro, observe que o elemento statistics é filho do elemento workflow . Observe também que não há nenhum espaço em branco irrelevante aqui. O elemento statistics é o primeiro filho do workflow.

Agora, vamos dar uma olhada em incluir informações reais.

Criar o Elemento de Informações do Arquivo

Agora, é possível seguinte em frente e criar as informações reais do documento. O processo usa as técnicas que você acabou de aprender.

...
function save_document_info($fileInfo){

   $doc = new DOMDocument('1.0');
   $root = $doc->createElement('workflow');
   $doc->appendChild($root);

   $statistics = $doc->createElement("statistics");
   $statistics->setAttribute("total", "1");
   $statistics->setAttribute("approved", "0");
   $root->appendChild($statistics);

   $filename = $fileInfo['name'];
   $filetype = $fileInfo['type'];
   $filesize = $fileInfo['size'];

   $fileInfo = $doc->createElement("fileInfo");

   $fileInfo->setAttribute("status", "pending");
   $fileInfo->setAttribute("submittedBy", $_SESSION["username"]);

   $approvedBy = $doc->createElement("approvedBy");

   $fileName = $doc->createElement("fileName");
   $fileNameText = $doc->createTextNode($filename);
   $fileName->appendChild($fileNameText);

   $location = $doc->createElement("location");
   $locationText = $doc->createTextNode(UPLOADEDFILES);
   $location->appendChild($locationText);

   $type = $doc->createElement("fileType");
   $typeText = $doc->createTextNode($filetype);
   $type->appendChild($typeText);

   $size = $doc->createElement("size");
   $sizeText = $doc->createTextNode($filesize);
   $size->appendChild($sizeText);

   $fileInfo->appendChild($approvedBy);
   $fileInfo->appendChild($fileName);
   $fileInfo->appendChild($location);
   $fileInfo->appendChild($type);
   $fileInfo->appendChild($size);

   $root->appendChild($fileInfo);

   $doc->save(UPLOADEDFILES."docinfo.xml");

}
...

Apesar de haver muito código aqui, muito pouco é novo. Primeiro, extrai-se as informações reais sobre o arquivo das informações passadas para a função. Cria-se então o elemento fileInfo que conterá todas as informações que estão sendo incluídas. Configura-se os atributos status e submittedBy nesse elemento e verifica-se então a criação de seus elementos.

O elemento approvedBy é fácil. Ainda não foi aprovado, portanto, isso permanecerá vazio. O elemento fileName , por outro lado, é um pouco mais difícil, pois é necessário incluir um filho de texto no mesmo. Felizmente, isso também é bem direto. O elemento é criado, então, Document é usado para criar o novo nó de texto que tem como seu conteúdo o nome do arquivo. Pode-se então incluir esse nó de texto como filho do elemento fileName .

É possível progredir dessa forma, criando todos os elementos que, eventualmente, serão filhos de fileInfo. Após ter concluído, todos são anexados como filhos do elemento fileInfo . Por fim, o próprio elemento fileInfo é incluído no elemento-raiz, workflow.

Os resultados, com espaçamento incluído por questão de clareza, têm aparência semelhante ao seguinte:

<?xml version="1.0"?>
<workflow>
   <statistics total="1" approved="0"/>
   <fileInfo status="pending" submittedBy="roadnick">
      <approvedBy/>
      <fileName>signed.pem</fileName>
      <location>/var/www/hidden/</location>
      <fileType>application/octet-stream</fileType>
      <size>2754</size>
   </fileInfo>
</workflow>

É claro que não é possível continuar sobrescrevendo o arquivo de informações toda vez que alguém faz upload de um documento, portanto, em seguida, verá como é trabalhar com uma estrutura existente.

Inserindo um Documento Existente

Agora que já sabe como incluir informações no arquivo, é necessário verificar como trabalhar com o arquivo em uploads subsequentes. Primeiro, é necessário ver se o arquivo já existe, então agir conforme necessário:

...
function save_document_info($fileInfo){

   $xmlfile = UPLOADEDFILES."docinfo.xml";

   if(is_file($xmlfile)){
      $doc = DOMDocument::load($xmlfile);
      $workflowElements = $doc->getElementsByTagName("workflow");
      $root = $workflowElements->item(0);
   } else{

      $doc = new DOMDocument('1.0');
      $root = $doc->createElement('workflow');
      $doc->appendChild($root);

      $statistics = $doc->createElement("statistics");
      $statistics->setAttribute("total", "1");
      $statistics->setAttribute("approved", "0");
      $root->appendChild($statistics);
   }

   $filename = $fileInfo['name'];
   $filetype = $fileInfo['type'];
   $filesize = $fileInfo['size'];

   $fileInfo = $doc->createElement("fileInfo");
...
   $fileInfo->appendChild($size);

   $root->appendChild($fileInfo);

   $doc->save($xmlfile);

}

Iniciando na parte superior, cria-se uma varável para representar o local do arquivo, já que agora será feita referência a ele em mais de um local. Em seguida, verifica-se se esse arquivo já existe. Se existir, a função load() é chamada, em vez de cria-se um novo objeto.

Essa função estática -- sobre a qual falaremos mais na Parte 3 desta série; por ora, entenda que são funções que podem ser chamadas a partir da classe, em vez de a partir de um objeto -- retorna um objeto Document que já está preenchido com todos os elementos, texto, etc., representados no arquivo.

Quando tiver o objeto Document , o elemento workflow será necessário, pois, no final, será necessário incluir o novo elemento fileInfo no mesmo. Obtém-se o elemento workflow recuperando primeiro uma lista de todos os elementos do documento chamado workflow e então selecionando o primeiro da lista.

A partir de então, é possível simplesmente incluir o novo elemento fileInfo e ele aparecerá após o original. Novamente, com espaço incluído por questão de clareza:

<?xml version="1.0"?>
<workflow>
   <statistics total="1" approved="0"/>
   <fileInfo status="pending" submittedBy="roadnick">
      ...
   </fileInfo>
   <fileInfo status="pending" submittedBy="roadnick">
      <approvedBy/>
      <fileName>timeone.jpg</fileName>
      <location>/var/www/hidden/</location>
      <fileType>image/jpeg</fileType>
      <size>2020</size>
   </fileInfo>
</workflow>

E statistics? Obviamente, não estão mais corretos. Isso precisará ser resolvido.

Manipulando Dados Existentes

Além de incluir informações no documento, é possível alterar informações que já estão lá. Por exemplo, é possível atualizar o atributo total no elemento statistics :

...
   if(is_file($xmlfile)){
      $doc = DOMDocument::load($xmlfile);
      $workflowElements = $doc->getElementsByTagName("workflow");
      $root = $workflowElements->item(0);

      $statistics = $root->getElementsByTagName("statistics")->item(0);
      $total = $statistics->getAttribute("total");
      $statistics->setAttribute("total", $total + 1);

   } else{
...

Primeiramente, obtém-se uma referência ao elemento statistics existente da mesma forma que obteve-se do elemento workflow existente, apenas combina-se ambas as etapas em uma. Quando tiver uma referência para o elemento, é possível obter o valor atual do atributo total usando a função getAttribute() . Pode-se usar então esse valor para fornecer um valor atualizado para o atributo total usando setAttribute().

Os resultados são os que podem ser esperados, desta vez, sem espaços incluídos:

<?xml version="1.0"?>
<workflow><statistics total="2" approved="0"/><fileInfo status="pending"
submittedBy="roadnick">...

Agora que já sabe como usar o DOM para criar o arquivo, vamos dar uma olhada em como lê-lo novamente usando outra API XL, SAX.


Usando XML: SAX

O que é SAX?

Na seção anterior, você aprendeu sobre o DOM, que trata dados XML como uma série de objetos organizados em uma hierarquia. Desta forma, é conhecido como API baseada em objeto. Nesta seção, irá aprender sobre Simple API for XML, ou SAX, que é uma API baseada em eventos. Essa API será usada para exibir informações sobre os arquivos disponíveis para que um usuário específico veja.

SAX funciona usando um manipulador de conteúdos para monitorar um fluxo de eventos. Considere, por exemplo, este documento XML:

<workflow>
   <statistics total="3" approved="2" />
   <fileInfo submittedBy="roadnick" status="approved">
     <fileName>timeone.jpg</fileName>
   </fileInfo>
</workflow>

Ao analisar esse documento, um manipulador de conteúdos SAX veria os seguintes eventos:

Start document
Start element (workflow)
Characters (whitespace)
Start element (statistics)
End element (statistics)
Characters (whitespace)
Start element (fileInfo)
Characters (whitespace)
Start element (fileName)
Characters (timeone.jpg)
End element (fileName)
Characters (whitespace)
End element (fileInfo)
Characters (whitespace)
End element (workflow)
End document

Como o manipulador de conteúdos vê esses eventos, é possível designar a ele uma função a ser executada para cada um deles.

Criar o Manipulador de Conteúdos

A primeira etapa é criar o próprio manipulador de conteúdos. Neste caso, está lidando com uma classe chamada Content_Handler, mas em PHP, o nome é inteiramente arbitrário. Abra scripts.txt e inclua o seguinte:

class Content_Handler{
  function start_element($parser, $name, $attrs){

     echo "Start element: ".$name."<br />";

  }
  function end_element($parser, $name){

     echo "End element: ".$name."<br />";

  }
  function chars($parser, $chars){

     echo "Text: ".$chars."<br />";

  } 
}

Por ora, deseja-se que as funções emitam saída de apenas o suficiente para que se saiba que foram chamadas. Agora, é necessário indicar ao analisador onde localizar o manipulador de conteúdos.

Designar Manipuladores

Para que PHP analise o arquivo, precisa saber quais funções executar para quais eventos. Inclua a função display_files() , vista abaixo, no scripts.txt:

...
function display_files(){

   $handler = new Content_Handler();

   $doc_parser = xml_parser_create();

   xml_set_object($doc_parser, $handler);

   xml_set_element_handler($doc_parser,
                           "start_element",
                           "end_element");
   xml_set_character_data_handler($doc_parser, "chars");

   xml_parser_set_option($doc_parser,
                        XML_OPTION_CASE_FOLDING, 0);

}
...

Primeiro, crie um novo objeto Content_Handler , $handler. Em seguida, obtenha uma referência ara o analisador de XML que está integrado a PHP e use a função xml_set_object() para indicar onde localizar as funções que serão referidas em um momento.

Em seguida, indique ao analisador quais funções deseja usar ara manipular diversos eventos. Em algumas APIs, esses nomes de funções são configurados de forma rígida, mas em PHP, são arbitrários. Portanto, é necessário indicar especificamente ao PHP, que está usando a função xml_set_element_handler() , que deve manipular o evento "iniciar elemento" com a função start_element() .

Observe que poderia ter ignorado xml_set_object() e simplesmente usado:

   xml_set_element_handler($doc_parser,
                           "$handler->start_element",
                           "$handler->end_element");

Por fim, a opção de desdobramento de maiúsculas e minúsculas é desativada para que o analisador não converta todos os nomes de elementos para letras maiúsculas. Agora, está pronto para analisar o arquivo real.

Abrir e Analisar o Arquivo

Neste ponto, você está pronto para analisar o arquivo, mas nada irá acontecer até que faça duas coisas. A primeira é realmente incluir a análise do arquivo em display_files():

...
   xml_parser_set_option($doc_parser,
                        XML_OPTION_CASE_FOLDING, 0);

   $xmlfile = UPLOADEDFILES."docinfo.xml";

   $file_to_parse = fopen($xmlfile, "r");
   if (!$file_to_parse) die("Can't open XML file.");

   while($data = fread($file_to_parse, 4096)){
           xml_parse($doc_parser, $data, feof($file_to_parse));
   }
}
...

Para que o processo seja eficiente (e tenha maior capacidade de manutenção), usa-se também a constante UPLOADEDFILES aqui para especificar o local do arquivo de informações do documento. A partir de então, os recursos de gerenciamento de arquivos integrado de PHP são usados para criar um identificador de arquivos para esse arquivo, $file_to_parse, e, se isso não funcionar, é exibida uma mensagem para esse efeito.

Quando tiver a referência para o arquivo, é possível percorrer o mesmo em partes de até 4.096 bytes. Para cada parte, os dados são enviados ao analisador. O loop continua até chegar no final do arquivo e para.

A segunda coisa que precisa ser feita para que qualquer coisa ocorra é chamar display_files() a partir de uploadfile_action.php:

...
    echo "FAILED TO UPLOAD " . $_FILES['ufile']['name'] .
         "<br>Temporary Name: $tmpName <br>";
  } else {

    save_document_info($_FILES['ufile']);
    display_files();

  } 
...

Agora chegou a hora de ver o que ocorreu.

Os Resultados Mais Básicos

Neste ponto, se fizer upload de um arquivo, PHP salvará o arquivo, incluirá as informações sobre ele no arquivo docinfo.xml e chamará o analisador (e com ele, o objeto Content_Handler ) para analisar os dados. Quando esse processo ocorre, cada função é chamada para seu próprio evento específico e obtém-se resultados como estes:

Start element: workflow
Start element: statistics
End element: statistics
Start element: fileInfo
Start element: approvedBy
End element: approvedBy
Start element: fileName
Text: timeone.jpg
End element: fileName
Start element: location
Text: /var/www/hidden/
End element: location
Start element: fileType
Text: image/jpeg
End element: fileType
Start element: size
Text: 2020
End element: size
End element: fileInfo
Start element: fileInfo
Start element: approvedBy
End element: approvedBy
Start element: fileName
Text: timeone.jpg
End element: fileName
Start element: location
Text: /var/www/hidden/
End element: location
Start element: fileType
Text: image/jpeg
End element: fileType
Start element: size
Text: 2020
End element: size
End element: fileInfo
End element: workflow

Esses resultados são informais, é claro, mas não exatamente bonitos. Agora, vamos da uma olhada em como criar uma página que realmente exibe informações de forma útil.

A Exibição Geral

Neste ponto, há saída e pode-se ver como o manipulador está sendo chamado, mas é necessário colocar essas informações em algum tipo de saída razoável. Por fim, deseja-se uma tabela de informações semelhante à Figura 6.

Figura 6. Tabela de Informações Legível
Tabela de Informações Legível

Essa tabela é convertida em uma página HTML:

...
Uploading: bespin-lunch-1.jpg<br />
<!-- At the start of the document -->
<h3>Available files</h3>
<table width='100%'>
<!-- At the start of the document -->
<!-- For each fileInfo element -->
   <tr><th>File Name</th>
   <th>Submitted By</th><th>Size</th>
       <th>Status</th></tr>
<!-- For each fileInfo element -->
   <tr><td>timeone.jpg</td>
   <td>roadnick</td><td>2020</td>
       <td>pending</td></tr>
   <tr><td>timetwo.jpg</td>
<td>roadnick</td><td>1416</td>
       <td>pending</td></tr>
   <tr><td>signupActivate.html</td><td>tater</td>
       <td>37594</td><td>approved</td></tr>
   <tr><td>signup.html</td><td>tater</td>
<td>32194</td>
       <td>approved</td></tr>
   <tr><td>bespin-lunch-1.jpg</td><td>roadnick</td>
       <td>29304</td><td>pending</td></tr>
<!-- At the end of the document -->
</table>
<!-- At the end of the document -->
</td>

Verificando os comentários, pode-se ver como é necessário dividir isso para os vários eventos. Vamos fazer isso então.

O Início e o Fim do Documento

Em algumas linguagens, é possível configurar uma função específica para manipular o início e o fim de um documento, mas PHP não torna isso tão simples assim. Esses eventos podem ser manipulados separadamente, mas, neste caso, também há a opção de simplesmente tratar do início e do fim do elemento workflow como o início e o fim do documento. Por exemplo, inclua o seguinte na definição de classe Content_Handler :

...
class Content_Handler{

  function start_element($parser, $name, $attrs){

     if ($name == "workflow"){
        echo "<h3>Available files</h3>";
        echo "<table width='100%'><tr>".
            "<th>File Name</th><th>Submitted By</th>".
            "<th>Size</th><th>Status</th></tr>";
     }

  }

  function end_element($parser, $name){

     if ($name == "workflow"){
        echo "</table>";
     }

  } 

  function chars($parser, $chars){
     //echo "Text: ".$chars."<br />";
  }
}
...

Quando o analisador envia o evento start element , chama a função start_element() e passa o analisador, o nome do elemento e quaisquer atributos para essa função. Essa saída pode ser usada para decidir se as informações devem ser exibidas.

Neste caso, obtém-se apenas uma única linha para a parte superior da tabela e a tag </table> para a parte inferior da tabela, como pode-se ver na Figura 7.

Figura 7. Exibir Informações do Elemento Inicial
Marcação de tabelas e linhas únicas

Exibir as linhas individuais, no entanto, não é nem de perto tão simples.

O Método start_element()

Um aspecto importante de uma API baseada em eventos é o fato de que a qualquer tempo, o analisador possui informações somente sobre esse evento específico. Isso significa que apesar de ser possível se deslocar para cima e para baixo na árvore quando está lidando com o DOM, ao usar SAX, não há como saber o que veio antes, a menos que tenha salvado isso explicitamente. Ou seja, ao chegar ao elemento fileName , não se sabe se o elemento fileInfo está disponível para exibição ou não, a menos que tenha feito uma observação explicitamente:

...
class Content_Handler{

  private $available = false;
  private $submittedBy = "";
  private $status = "";

  function start_element($parser, $name, $attrs){

  if ($name == "workflow"){
     echo "<h3>Available files</h3>";
     echo "<table width='100%'><tr>".
          "<th>File Name</th><th>Submitted By</th>".
          "<th>Size</th><th>Status</th></tr>";
     }

     if ($name == "fileInfo"){
        if ($attrs['status'] == "approved" ||
            $attrs['submittedBy'] == $_SESSION["username"]){
           $this->available = true;
        }
        if ($this->available){
           $this->submittedBy = $attrs['submittedBy'];
           $this->status = $attrs['status'];
        }
     }

  }

  function end_element($parser, $name){
...

Ao chegar ao início de um elemento fileInfo , deve-se verificar o atributo status e o elemento submittedBy para ver se um deles é a razão para mostrar o documento. Pode-se fazer isso usando a array $attrs .

Se o status for aprovado ou se o arquivo tiver sido enviado pelo usuário atual, deve-se observar que quaisquer dados que esteja entrando com esse elemento está disponível. Para fazer isso, criou-se uma variável chamada available na própria classe. (Não se preocupe com aquela coisa private ; discutiremos isso na Parte 3.) Como a variável faz parte desse objeto, é possível fazer referência a ela usando $this->available e esse valor permanecerá configurado ao prosseguir para o próximo evento.

Se as informações estiverem disponíveis, deve-se salvá-las para que possam ser exibidas quando chegar a hora. Para essa finalidade, elas são salvas nas variáveis submittedBy e status .

A mesma coisa precisa ser feita ao lidar com determinado texto.

O Método characters()

Algumas das informações que você deseja exibir são armazenadas como atributos do elemento fileInfo , mas algumas são armazenadas como nós de texto de outros elementos. Para salvar as informações, no entanto, é necessário saber quais elementos estão sendo processados:

class Content_Handler{

  private $available = false;
  private $submittedBy = "";
  private $status = "";

  private $currentElement = "";

  private $fileName = "";
  private $fileSize = "";

  function start_element($parser, $name, $attrs){
...
     $this->currentElement = $name;

  }

  function end_element($parser, $name){

     if ($name == "workflow"){
        echo "</table>";
     }

     $this->currentElement = "";

  } 

  function chars($parser, $chars){

     if ($this->available){
         if ($this->currentElement == "fileName"){
            $this->fileName = $this->fileName . $chars;
         }
         if ($this->currentElement == "size"){
            $this->fileSize = $this->fileSize . $chars;
         }
      }

  } 
}

Vamos iniciar na parte superior. Primeiro, crie uma variável para armazenar o nome do elemento atual e armazene-o toda vez que executar a função start_element() . Ele será limpo toda vez que a função end_element() for usada, mas é importante observar que apenas limpá-lo não o reverte para seu valor anterior. Não é como percorrer a árvore XML.

A parte importante é que é possível saber com qual elemento está se lidando ao chegar à função chars() , que é executada uma ou mais vezes para cada nó de texto. Toda vez que for executada, se o arquivo estiver disponível para exibição, estará verificando o elemento atual e incluindo os caracteres atuais nas variáveis apropriadas, se necessário.

O Método end_element()

Agora, que todas essas informações foram armazenadas, é necessário exibi-las para cada elemento fileInfo . A maneira mais fácil de exibi-las é emitir a saída ao chegar ao final de cada elemento fileInfo :

...
  function end_element($parser, $name){

     if ($name == "workflow"){
        echo "</table>";
     }

     if ($name == "fileInfo"){
        echo "<tr><td>".$this->fileName."</td>".
                 "<td>".$this->submittedBy."</td>".
                 "<td>".$this->fileSize."</td>".
                 "<td>".$this->status."</td></tr>";

        $this->fileName = "";
        $this->submittedBy = "";
        $this->fileSize = "";
        $this->status = "";

        $this->available = false;
     }

     $this->currentElement = "";

  } 
...

Quando a função end_element() é executada, primeiro, é exibida uma linha da tabela com as informações apropriadas. Quando isso estiver terminado, é necessário limpar todas as variáveis, incluindo a variável $available , de forma que esteja pronto para processar o próximo elemento fileInfo .

O resultado é uma tabela de informações, conforme mostrado na Figura 8.

Figura 8. Tabela Resultante de Informações
Tabela Resultante de Informações

Na Parte 3, você verá como aprimorar essa tabela com links e outras informações e funcionalidade.


Resumo

Neste tutorial, iniciou-se a criação do centro da aplicação do fluxo de trabalho: a capacidade do usuário de incluir arquivos. Você possibilitou que os usuários efetuassem login no sistema e criassem uma sessão que reconheça-os e faça upload de um arquivo. O arquivo foi salvo no servidor e XML foi usado para salvar informações sobre ele. Ao longo do caminho, os seguintes tópicos foram cobertos:

  • Criar uma sessão
  • Usar uma sessão existente
  • Fazer upload de um arquivo
  • Criar um arquivo XML usando o DOM
  • Carregar dados XML usando o DOM
  • Manipular dados XML usando o DOM
  • Criar um manipulador de conteúdos SAX
  • Analisar um arquivo XML usando SAX
  • Controlar dados XML usando SAX

Na Parte 3, a aplicação será concluída.

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
ArticleID=397415
ArticleTitle=Aprendendo PHP, Parte 2: Fazer Upload dos Arquivos e Usar XML para Armazenar e Exibir Informações de Arquivo
publish-date=06212005