Olá a todos.
Estamos de volta com mais uma matéria de ColdFusion da série do sistema de blog e espero que esteja sendo proveitosa para vocês. Nesta seqüência vamos verificar a parte de inserção e atualização das informações através do administrativo. Também faremos a paginação de dados para as páginas do administrativo.
Let’s go!
Ouvindo: Charlie – Red Hot Chili Peppers
Versão do Servidor – CFMX7 Dev. Edition
Novamente, antes de começarmos a falar do código, disponibilizo para download o sistema para que possa ser analisado durante a matéria.
Esta é a última parte da série. Para encerrarmos este assuntos, foram implementadas duas ações no sistema:
01 – Atualização de informações:
De forma semelhante a que eram feitas as seleções, exclusões e inserções no banco de dados, iniciamos esta matéria utilizando o update através de uma cffunction. Assim como fiz na matéria anterior, irei usar um dos updates para servir de exemplo para a explicação do funcionamento do mesmo:
<cffunction name="updtPost" access="public" returntype="void">
<cfargument name="cod" type="numeric" default="0">
<cfargument name="usuario" type="numeric" default="0">
<cfargument name="titulo" type="string" default="">
<cfargument name="texto" type="string" default="">
<cfquery name="atualizaPost" datasource="bd_blog">
UPDATE
post
SET
usuario = #Arguments.usuario#,
titulo = '#Arguments.titulo#',
texto = '#Arguments.texto#',
dt_hr = #Now()#
WHERE
cod = #Arguments.cod#
</cfquery>
<cflocation url="posts.cfm">
</cffunction>
Relembrando o que já foi visto, a cffunction possui o nome de updtPost (caracterizada pelo atributo name), tem um acesso público (ou seja, pode ser acessada por qualquer página ou método do componente) e não retorna nenhum valor (void).
No exemplo, estamos mostrando a atualização de um post existente no blog, o qual é efetuado através da query de nome atualizaPost.
Para execução correta da SQL, a função recebe 4 argumentos:
cod: Argumento numérico que é responsável, na SQL, pela discriminação de qual post estamos nos referindo (WHERE cod = #Arguments.cod#)
usuario: Argumento também numérico que será armazenado no banco de dados como o número relacionado ao código do usuário responsável pela atualização.
titulo: Argumento do tipo string que será armazenado no banco de dados como o novo título do post.
texto: Argumento do tipo string que será armazenado no banco de dados como o novo texto que compõe o post.
O campo dt_hr receberá a data atual do sistema, isto é informado através da função Now().
A função é invocada nas linhas 2 – 4 da página posts_detail.cfm:
<cfif Cgi.REQUEST_METHOD IS "Post">
<cfinvoke component="admin" method="updtPost" usuario="#Form.usuario#" titulo="#Form.titulo#" texto="#Form.texto#" cod="#Form.cod#">
</cfif>
O código acima invoca, caso o formulário tenha sido enviado (condição caracterizada pelo cfif realizado na primeira linha do bloco acima), o método updtPost, passando os valores vindos do formulário para os argumentos que serão utilizados para montar aquela função.
Sem segredos não é?
O ColdFusion permite uma separação de código muito interessante, de forma clara e com um pequeno tempo de desenvolvimento.
Você irá notar que nos arquivos disponibilizados para download houveram outras modificações, mas nada que fuja ao que já foi explicado. Tudo é relacionado a cffunctions que executam queries. A parte mais “diferente” da história começa no próximo parágrafo.
02 – Paginação:
Paginação: esse assunto pode até causar um frio na espinha de muitos desenvolvedores web, mas para quem tem uma linguagem como o ColdFusion em mãos, tudo se torna (bem mais) simples. Programo também em ASP e posso garantir que, pelo menos em relação a esta linguagem, a paginação em ColdFusion é desenvolvida de forma mais rápida, mais limpa e de reuso mais fácil de ser implementado. Usarei como exemplo a página posts.cfm e o repositório de funções admin.cfc.
A função:
<cffunction name="paginacao" access="public" returntype="struct" output="true">
<cfargument name="qtd" type="numeric" default="0">
<cfargument name="linhas" type="numeric" default="1">
<cfargument name="pagina" type="numeric" default="0">
<cfscript>
paginar = Ceiling(Arguments.qtd/Arguments.linhas);
link = "Página(s) ";
for(i=1; i lte paginar; i = i+1)
link = link & " | <a href='" & Cgi.SCRIPT_NAME & "?pagina=" & i & "&linhas=" & linhas & "' class='obs_post'>" & i & "</a>";
ini = ((Arguments.pagina-1) * Arguments.linhas)+1;
paging = StructNew();
StructInsert(paging,"links",link);
StructInsert(paging,"inicio",ini);
</cfscript>
<cfreturn paging/>
</cffunction>
Vamos entender linha por linha desta função para que fique o mais claro possível para você, leitor. Inicialmente fazemos o que já é de costume: damos um nome para a função, definimos um tipo de acesso, um tipo de retorno e usamos ao atributo output com o valor true para que o código dentro da cffunction se comporte como dentro da cfoutput, substituindo-se os nomes de variáveis cercados por # pelos valores armazenados nas respectivas variáveis.
Para esta função, são necessários 3 argumentos:
qtd: Argumento numérico que receberá da página que invocar esta função a quantidade total de registros existentes na query executada (pela página .cfm).
linhas: Argumento numérico que receberá da página que invocar esta função a quantidade de registros que se deseja mostrar na página.
pagina: Argumento numérico que receberá da página que invocar esta função a página de registros na qual o usuário se encontra.
Para um melhor entendimento até este ponto, suponhamos que no banco de dados possuam 40 posts. O número 40 (total de registros retornados pela query) seria armazenado no argumento qtd.
Caso fosse necessária a exibição de 10 registros por página, então este número 10 ficaria armazenado no argumento linhas. Isso faria com que houvessem 4 páginas em nossa paginação, e o argumento pagina é responsável por armazenar a página atual na qual nos encontramos.
Daí em diante, todo o resto do processo foi montado em CFScript. O CFScript é uma linguagem dentro de outra linguagem (CFML), similar ao Javascript, porém rodando em server-side. Pode-se usar todas as funções e todas as variáveis disponíveis no ColdFusion, mas não se pode usar nenhuma outra tag CFML dentro do bloco
1º parte: Montagem dos links de paginação
paginar = Ceiling(Arguments.qtd/Arguments.linhas);
link = "Página(s) ";
for(i=1; i lte paginar; i = i+1)
link = link & " | <a href="" & Cgi.SCRIPT_NAME & "?pagina=" & i & "&linhas=" & linhas & "" class='obs_post'>" & i & "</a>";
Criamos a variável paginar, que recebe o valor do teto da divisão da quantidade de registros pela quantidade de registros a serem exibidos por página. Se temos, por exemplo, 22 registros para exibirmos em páginas de 10 registros, temos 22/10 = 2,2. O teto (Ceiling) é o arredondamento deste número para o inteiro imediatamente acima dele, no caso 3. Ou seja, teremos 3 páginas de resultados (a primeira com os registros de 1 a 10, a segunda de 11 a 20 e a terceira de 21 a 22).
Após isto, criamos a variável link, que receberá o código HTML para montagem dos links de acesso à paginação. É feito um loop para que sejam gerados links para cada uma das páginas de paginação (separados por | ).
Para a montagem deste link, capturamos o nome da página através da variável Cgi chamada Script_Name, e passamos como parâmetros de url o número da página atual (armazenado na variávei i) e a quantidade de linhas de registro a serem exibidos.
2º parte: Cálculo do registro inicial de exibição
ini = ((Arguments.pagina-1) * Arguments.linhas)+1;
A variável ini recebe o resultado da fórmula acima para indicar a partir de qual linha os registros serão exibidos. Usando o exemplo com 22 registros, caso estivéssemos na segunda página de uma paginação de 10 registros teríamos:
ini = ((2-1) * 10) + 1
ini = (1 * 10) + 1
ini = 10 + 1 = 11, ou seja, a segunda página exibe a partir do 11º registro
Quando chegarmos ao ponto da implementação deste código na página, você notará que quando entrar na página pela primeira vez, não haverá valor fornecido para a página da paginação na qual você se encontra, porém, note que quando foram criados, os argumentos pagina e linhas têm seus valores padrão (default, sendo 1 e 0, respectivamente).
Neste caso, teremos:
ini = ((1-1) * 0) + 1
ini = (0 * 0) + 1
ini = 0 + 1 = 1, ou seja, a segunda página exibe a partir do 1º registro
3º parte: Retornando os dados
Note que, desta vez, usamos um tipo nem tão comum assim de retorno: struct.
Structs (estrutura em inglês) nada mais são que variáveis que armazenam vários valores que podem ser organizados e acessados por chaves, como está no exemplo do código de paginação:
paging = StructNew();
StructInsert(paging,"links",link);
StructInsert(paging,"inicio",ini);
Configuramos a variável paging como uma nova estrutura e nela armazenamos os valores das variáveis link e ini, cada uma em uma chave (key) da estrutura paging. Para que uma variável se torne uma struct, usa-se a função StructNew(), e para criação de keys na struct, usa-se a função StructInsert(), onde devem ser informados os seguintes dados:
- Nome da struct na qual será criada a chave;
- Nome (entre aspas) da key que será criada nesta struct;
- Variável que terá seu valor armazenado nesta structkey.
Ao final usa-se a cfreturn para retornarmos a struct paging em resposta à invocação da função.
Implementação na página:
Iremos agora para a última parte: a implementação da paginação nas páginas que necessitarem ela.
Basicamente, precisamos definir duas variáveis que serão passadas para a função, e virão através de Url, para isto, foi acrescentado as páginas o seguinte bloco de código:
<cfif Not isDefined("Url.pagina")>
<cfparam name="pagina" default="1">
<cfelse>
<cfset pagina = "#Url.pagina#">
</cfif>
<cfif Not isDefined("Url.linhas")>
<cfparam name="linhas" default="5">
<cfelse>
<cfset linhas = "#Url.linhas#">
</cfif>
Nas linhas acima, informamos ao servidor que, se não estiver definida a variável de url chamada pagina, a variável pagina terá o valor default de 1, e caso a variável de url pagina exista terá seu valor atribuído à variável pagina (é bom lembrar que cada uma destas variáveis, embora possuam o mesmo nome, existem em escopos diferentes: uma pertence ao escopo Url e outra ao escopo Variables).
O mesmo procedimento foi feito para a variável linhas. É nesta variável que se especifica a quantidade de registros que se deseja visualizar por página. Em nosso exemplo está sendo utilizado um total de 5 registros por página. Caso o número de registros total da query seja inferior ao valor estipulado na variável linhas, haverá apenas uma página de registros. Então, sendo necessário, altere o valor do atributo default do cfparam para que possa testar a paginação.
Prosseguindo com a matéria, iremos analisar a linha que invoca esta função:
<cfinvoke
component="admin"
method="paginacao"
returnvariable="paging"
qtd="#posts.RecordCount#"
linhas="#linhas#"
pagina="#pagina#"
>
A sintaxe deste cfinvoke está diferente das anteriores (montadas em uma única linha) para melhor organização do código. O código para invocar a cffunction paginacao é a mesma para todas as páginas, a única diferença está no valor atribuído ao argumento qtd, onde o nome da query varia de página para página, então vamos estudar este código:
- component: nome do cfc em que reside a cffunction que iremos invocar.
- method: nome da cffunction que se deseja invocar.
- returnvariable: como a cffunction está configurada para retornar um valor do tipo struct, devemos ter uma variável nesta página que receba esta informação para podermos trabalhá-la aqui.
- qtd: Argumento da cffunction. Nele é armazenado o número do total de registros retornados pela query (no caso do exemplo acima, a query posts). O total de registros é extraído usando a propriedade RecordCount.
- linhas: Argumento da cffunction. Nele é enviado o número de registros que se deseja exibir por página, valor este armazenado na variável linhas.
- pagina: Argumento da cffunction. Recebe o número da página de registros na qual o usuário se encontra. O valor que este atributo recebe vem da variável pagina.
Agora precisamos fazer somente mais dois ajustes no código para que nossa página esteja completa.
Na linha onde é efetuada a saída dos dados com a tag cfoutput, devemos acrescentar dois atributos para que fique assim:
Com esta linha informamos que a saída de dados será efetuada com as informações existentes na query posts. O atributo startrow define a partir de qual registro da query os dados serão exibidos, e o atributo maxrows define a quantidade total de registros que serão exibidos na página. Logo após a saída dos dados vindos da query, acrescentamos o seguinte código:
<cfoutput>#paging.links#</cfoutput>
Esta linha escreve na página o conteúdo da chave (key) links da estrutura (struct) paging, retornada pela função, lembrando que esta chave contém o código HTML reponsável pelos links da paginação.
Agora é só curtir! Código completo, matéria finalizada… espero ter conseguido mostrar a vocês como o ColdFusion trabalha com simplicidade para solucionar problemas propostos aos desenvolvedores. Qualquer dúvida, crítica, elogio ou sugestão, basta mandar um email ou deixar um comentário aqui no iMasters.
Feliz 2007 a todos vocês e até a próxima gente! Fiquem com Deus!