Back-End

7 fev, 2007

Sistema de Blog em ColdFusion – Parte 05

Publicidade

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: CharlieRed Hot Chili Peppers

Versão do ServidorCFMX7 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 . O uso do CFScript tem como vantagens a simplificação e aceleração de “setagem” de variáveis e construção de estruturas de controle de fluxo compacta.

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!