KISS - Keep it simple, stupid!

Redirecionamento de Erros: descubra os 404 e diminua a insatisfação do usuário

postado por Lucas Gameiro em 22/03/2010 16:55:43

Uma das coisas mais frustrantes da navegação na internet é quando você vê um link que te interessa e quando clica é redirecionado pra um erro.

O 404 é o mais comum deles, isso porque ele é muito fácil de acontecer. Se alguém citou uma página do seu site que não existe mais, ou algum erro no script constroi uma url errada dinamicamente o 404 é invevitável você não vai percebê-lo rapidamente.

O CakePHP através do método link do helper Html já previne alguns problemas porém ainda não é possível administrar os erros de maneira fácil.
Pensando nisso, eu desenvolvi um sistema para informar quando os 404 acontecem e criar redirecionamentos para que eles não se repitam. Isto não é difícil de ser feito já que o CakePHP tem boas maneiras de controlar este erro.

A primeira coisa a se fazer é criar a tabela onde ficaram armazenados estes erros.

CREATE TABLE `redirects` (
    `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `num_errors` int(10) UNSIGNED NOT NULL,
    `page_from` varchar(255) NOT NULL,
    `page_to` varchar(255),
    `num_redirects` int(10) UNSIGNED,
    PRIMARY KEY (`id`)
)

Após a tabela criamos o modelo com métodos para contar e manipular os erros e os redirecionamentos: (/models/redirect.php)

<?php
class Redirect extends AppModel {
    var $name = 'Redirect';  
    public function manageError($url){
        $redirects = $this->find(
            'first',
            array(
                'conditions' => array('Redirect.page_from' => $url)
            )
        );
        if(!$redirects){
            $redirects['Redirect']['num_errors'] = 0;
            $redirects['Redirect']['page_from'] = $url;
            $redirects['Redirect']['num_redirects'] = 0;
            $redirects['Redirect']['page_to'] = null;
        }
        $redirects['Redirect']['num_errors']++;
        $this->set(
            $redirects
        );
        return $this->save();
    }
    public function manageRedirect($urlfrom, $urlTo){
        $redirect = $this->find(
            'first',
            array(
                'conditions' => array(
                    'Redirect.page_from' => $urlfrom
                )
            )
        );
        $redirect['Redirect']['num_redirects']++;
        $this->set($redirect);
        return $this->save();
    }
}
?>

Com isso, já podemos criar o armazenamento, redirecionamento e contagem dos erros. Esta será feita escrevendo a classe AppError que é feita exatamente para manipular estes erros. (/app_error.php)

<?php
    class AppError extends ErrorHandler{
        var $Error;
        public function error404($params){
            $this->Redirect = ClassRegistry::init('Redirect');
            $page = $this->Redirect->find(
                'first',
                array(
                    'conditions' => array(
                        'page_from' => $params['url']
                    )
                )
            );
            if($page && $page['Redirect']['page_to']){
                $this->Redirect->manageRedirect(
                    $params['url'],
                    $page['Redirect']['page_to']
                );
                $Dispatcher = new Dispatcher();
                $Dispatcher->dispatch($page['Redirect']['page_to']);
            }
            else{
                $this->Redirect->manageError($params['url']);
                $this->controller->set('url', $params['url']);
                $this->_outputMessage('error404', $params);
            }
        }
    }
?>

Agora os erros já estão sendo contados e redirecionados porém sua administração tem que ser feita diretamente no banco de dados. É interessante portanto também criar métodos para gerenciar estes erros e redirecionamentos. ficamos então com o controller: (/controllers/redirects_controller.php)

<?php
class RedirectsController extends AppController {
	var $name = 'Redirects';
	var $helpers = array('Html', 'Form');
    var $paginate = array(
        'limit' => 25,
        'order' => array(
            'num_errors' => 'desc'
        )
    );
	function index() {
		$this->Redirect->recursive = 0;
		$this->set('redirects', $this->paginate());
	}
	function create_redirect($id = null) {
		if (!$id && empty($this->data)) {
			$this->Session->setFlash(__('Redirecionamento Inválido', true));
			$this->redirect(array('action'=>'index'));
		}
		if (!empty($this->data)) {
			if ($this->Redirect->save($this->data)) {
				$this->Session->setFlash(__('O Redirecionamento foi salvo.', true));
				$this->redirect(array('action'=>'index'));
			} else {
				$this->Session->setFlash(__('O Redirecionamento não pode ser salvo. Por favor, tente novamente.', true));
			}
		}
		if (empty($this->data)) {
			$this->data = $this->Redirect->read(null, $id);
		}
	}
	function delete($id = null) {
		if (!$id) {
			$this->Session->setFlash(__('Redirecionamento com id inválido', true));
			$this->redirect(array('action'=>'index'));
		}
		if ($this->Redirect->del($id)) {
			$this->Session->setFlash(__('Redirecionamento excluído', true));
			$this->redirect(array('action'=>'index'));
		}
	}
}
?>

Observem que este controller não está utilizando nenhum método de autenticação. Fica em aberto o método a ser utilizado sendo que todas as páginas devem ficar invisíveis ao usuário comum. As views necessárias para este controller são:
create_redirect (/views/redirects/create_redirect.ctp):

<div class="redirects form">
<?php echo $form->create('Redirect', array('action' => 'create_redirect'));?>
	<fieldset>
 		<legend><?php __('Criar Redirecionamento');?></legend>
	<?php
		echo $form->input('id');
		echo $form->input('page_from', array('label'=>'URL do 404', 'disabled' => true));
		echo $form->input('page_to', array('label' => 'Redirecionar para'));
	?>
	</fieldset>
<?php echo $form->end('Criar');?>
</div>
<div class="actions">
	<ul>
		<li>
			<?php
				echo $html->link(
					__('Excluir', true),
					array(
						'action' => 'delete',
						$form->value('Redirect.id')
					),
					null,
					sprintf(
						__('Você tem certeza que deseja excluir # %s?', true),
						$form->value('Redirect.id')
					)
				);
			?>
		</li>
		<li>
			<?php
				echo $html->link(
					__('Listar 404s', true),
					array('action' => 'index')
				);
			?>
		</li>
	</ul>
</div>

e index (/views/redirects/index.ctp):

<div class="redirects index">
<h2><?php __('Redirecionamentos');?></h2>
<table cellpadding="0" cellspacing="0">
<tr>
    <th><?php echo $paginator->sort('URL do 404', 'page_from');?></th>
	<th><?php echo $paginator->sort('número de erros', 'num_errors');?></th>
	<th><?php echo $paginator->sort('URL a redirecionar', 'page_to');?></th>
	<th><?php echo $paginator->sort('número de redirecionamentos', 'num_redirects');?></th>
	<th class="actions"><?php __('Ações');?></th>
</tr>
<?php
foreach ($redirects as $redirect):
?>
	<tr>
		<td>
			<?php echo $redirect['Redirect']['page_from']; ?>
		</td>
		<td>
			<?php echo $redirect['Redirect']['num_errors']; ?>
		</td>
		<td>
			<?php echo $redirect['Redirect']['page_to']; ?>
		</td>
		<td>
			<?php echo $redirect['Redirect']['num_redirects']; ?>
		</td>
		<td class="actions">
			<?php
				echo $html->link(
					__('Criar Redirecionamento', true),
					array(
						'action' => 'create_redirect',
						$redirect['Redirect']['id']
					)
				);
			?>
            <?php
				echo $html->link(
					__('Excluir', true),
					array(
						'action' => 'delete',
						$redirect['Redirect']['id']
					)
				);
			?>
		</td>
	</tr>
<?php endforeach; ?>
</table>
</div>
<div class="paging">
	<?php echo $paginator->prev('<< '.__('anterior', true), array(), null, array('class'=>'disabled'));?>
 | 	<?php echo $paginator->numbers();?>
	<?php echo $paginator->next(__('próxima', true).' >>', array(), null, array('class' => 'disabled'));?>
</div>

Pronto, agora temos uma ferramenta para gerenciar os erros 404 do site. Tomara que algum dia a frustração de pensar que um link solucionará meus problemas e tomar um 404 na lata diminua

Criei um projeto no github pra facilitar a baixar os arquivos. Está tudo neste link

Tags: , , , , ,
Topo

4 Comentários

Utilizando Migrations no CakePHP

postado por Lucas Gameiro em 15/07/2009 09:46:36

Atualmente, o pessoal aqui da souágil está se reunindo para discutir e apresentar alguns temas importantes para o desenvolvimento, o que chamamos de processo de melhoria contínua. São pequenas apresentações de no máximo 30 minutos. O primeiro encontro foi sobre Referências Circulares e Memory Leaks no DOM apresentação feita pelo Gabriel, garanto que vou cobrá-lo a postar algo sobre isso aqui. O segundo encontro foi ontem, dia 14, e o assunto foi o migrations do cakePHP feito por João José e Juan Basso do CakePHP Brasil.

Vou disponibilizar aqui a apresentação porém alerto que esta não explica o que é o migrations e nem o que faz. O intuito era mesmo ensinar a utilizar:

Obs.: Quem for de londrina e quiser participar dos encontros pode comentar este post ou enviar um email para contato [arroba] usosim.com.br

Tags: ,
Topo

4 Comentários

Vim com cara de TextMate

postado por Lucas Gameiro em 27/02/2009 16:10:43

Não quero mais IDEs pesadas. Meu PC não aguenta, ou escuto música ou programo. Estas são reclamações de muitos outros como eu, que tem um computador old school e não aguentam mais salvar o projeto e sair pra tomar um café enquanto o PDT não volta e o firefox está todo cinza.

Por isso comecei a utilizar o vim como editor para meus projetos. Após pesquisar bastante aprendi alguns macetes e plugins que me ajudaram a deixá-lo mais a cara de um editor funcional, como é o TextMate. Aí vão elas:

Eu recomendo fortemente o trabalho com utf-8 ao invés da iso8859-1 portanto, a primeia ação que deve ser tomada, é configurar o terminal para funcionar em utf-8. Caso tenha algumas dúvidas de codificação, como o que ocorreu na lista de discussão do cakephp estes dias, este link pode esclarecê-las.

Para realizar esta configuração, no linux basta você setar a variável LANG no arquivo /etc/profile.d/lang.sh, ficando:

export LANG=pt_BR.UTF-8

Já no windows basta inserir o comando abaixo no arquivo .vimrc*:

set enc=utf-8

Outra configuração que ajuda muito no trabalho em equipe é ter as identações feitas com espaços e não com tabs, para que diferentes editores não interpretem as tabulações diferentes e não acontecer de o git toda vez que alguém diferente abre o arquivo ache que o arquivo inteiro mudou. Para resolver este problema tanto no Windows quanto no Linux, basta inserir as seguintes linhas no arquivo .vimrc:

set expandtab
set tabstop=4
set smarttab
set shiftwidth=4

Explicando:

  • Expandtab: altera as tabulações para espaços;
  • Tabstop: Tabulações passam a ter 4 espaços;
  • Smarttab: Utiliza a tabulação inteligente. Para inicio de ifs e outros comandos;
  • Shiftwidth: Conserta a tabulação inteligente para 4 espaços.

Algo que também considero essencial é exibir o numero das linhas. Para encontrar erros, testes que falharam e etc.É impossível trabalhar sem. Para isso, mais uma vez no .vimrc:

set number

Os próximos passos envolvem a utilização de plugins que tornam a vida muito mais fácil. O primeiro deles é o NERDTree que transforma um pedaço do vim em uma árvore de diretórios que pode ser acessada com o mouse, ou com o teclado. Na sua pagina tem uma explicação de instalação e de manipulação.

Para tornar a sua utilização mais simples, criei alguns maps do vim que funcionam da seguinte maneira:

inserindo o código

map <C-Left> :tabprevious<cr>
map <C-Right> :tabnext<cr>
map <C-N>t :NERDTree<cr>

novamente no .vimrc, você conseguirá abrir o NERDTree apenas apertando as teclas Ctrl^N + T e trocar de abas apertando Crtl^seta pra direita ou Crtl^seta pra esquerda.

Outro plugin interessante é o snippetsEmu. que faz com que o vim tenha bundles parecidos com o TextMate. Também com tutorial de instalação, ele permite que se crie pedaços de código apenas com algumas letras e digitando a tecla TAB. Após a instalação, digite for e depois sucessivamente tecla TAB. Mágico não é?

Com estes passos, criando trechos de código com os snippetsEmu, e o autocomplete(Crtl^P) nativo do vim, a sua produtividade vai ser muito maior do que a daquele tempo de espera pro eclipse validar todos arquivos logo após algumas ações.

Comecei a construir alguns snippets do cakephp para o vim. Mas isso fica para um próximo post.

Para quem não quer ficar copiando e colando cada trecho de código, o meu arquivo .vimrc encontra-se neste link.

* – O arquivo .vimrc fica na pasta de instalação do vim no windows e deve ficar na sua home no linux. Se este arquivo não existir basta apenas criá-lo

Tags: , , , ,
Topo

3 Comentários

Desvendando mentiras sobre a XP

postado por Lucas Gameiro em 18/02/2009 12:23:38

A algum tempo estive pensando em escrever um pouco sobre o desenvolvimento de software e, recentemente estive refletindo bastante sobre tudo que ouvi no começo do aprendizado e o que me deparo constantemente. Pensei então em começar a escrever uma série de posts para passar algumas reflexões que fiz.Não consegui fazer isso. :(

No primeiro deles gostaria de falar de um dos principais erros que cometi logo no início do meu estudo. Desconfiar que aplicar uma metodologia de desenvolvimento poderia ser fácil. Meu erro foi achar que bastava escrever a receita de um bolo de cenoura junto com o cliente e depois seguir a receita vendo se todos estavam colocando os ingredientes certos.

Não demorou muito pra perceber que o cliente não quer necessariamente um bolo de cenoura, e na grande maioria ele nem sabe se quer realmente um bolo. E o pior, ninguém sabia ao certo, quanto tempo de forno era necessário pra assar aquele bolo que nunca tinhamos feito.

Foi então que, durante um evento conheci a Programação Extrema(XP), não deu outra, me apaixonei, ela respondia perfeitamente muitas de minhas dúvidas, e um amigo que já a estudava a algum tempo me serviu como grande fonte de ensino e expiração.

Antes de começar os estudos já cometi um grande erro que foi confundir metodologias ágeis com codifica-corrige. Este mito não deve ocorrer e é desvendado sem muito precisar ler sobre o que é XP. A XP que determina práticas de planejamento e gerenciamento do software, o que em muito difere do codifica-corrige que não deveria nem mesmo ser considerada uma metodologia.

Outro erro facilmente cometível é deixar o projeto correr julgando que com os cartões sendo feitos toda semana, o projeto vai tomar um rumo. O que o gerente precisa ter em mente é que nem sempre os desenvolvedores sabem o que realmente é necessário fazer com mais urgência, e que o cliente quer muita coisa que muitas vezes não precisa.

Para elucidar este fato existe uma metáfora de que se encaixa perfeitamente, a metáfora do cheff de cozinha, Nela, os desenvolvedores seriam os cozinheiros, que tem suas próprias preferências de temperos e sabem realmente como preparar o prato, o gerente seria o cheff que conversa com clientes e inventa os pratos, e o cliente seria o consumidor. Em um ambiente de criação, o cheff pergunta  ao consumidor o que ele gostaria, e este responde que gosta de jiló e de chocolate e quer comer isso no fim da noite porém, o cheff não vai atender cegamente o que o consumidor deseja, ele indica ao cliente comê-los separadamente primeiro o jiló e depois o chocolate sendo que muitas vezes o cheff mostra pro cliente que jiló não é realmente o que o cliente deseja e sugere algo que seria de muito mais gosto a ele.

O erro de deixar o projeto correr, é muitas vezes cometido por alguns que dizem implemetar XP mas não a implementam na realidade. Todo projeto precisa de um rumo, o que a XP realmente faz é dizer que se planejar é bom, vamos planejar toda semana, e este é um dos fatos que faz diferir de outras metodologias não-ágeis, as quais preferem realizar um enorme estudo de tudo o que deve ser realizado no projeto inteiro antes de começar a colocar a mão em código.

Tags: , , , ,
Topo

Sem comentários

Creative Commons License
Sou Ágil: KISS em http://kiss.souagil.com.br está licenciado sobre
Creative Commons Attribution-Share Alike 2.5 Brazil License.

souÁgil