Páginas

domingo, 3 de fevereiro de 2013

Symfony2 + Ajax(JSON) + CEP + Controller (Update 06/06/13)

Olá Pesssoal,

Faz um tempinho desde minha ultima postagem, aqui vai mais uma, estou começando a Estudar o Symfony 2 (estou meio atrasado, é que tive estudando muito Android).

Bem aqui vai o desafio de hoje, tive que fazer uma consulta JSON para usar o RepublicaVirtual.com.br para a consulta de CEPs, porém eu não queria fazer com getScript, eu queria fazer uma requisição legal.

Considerações:


  1. Como eu ainda estou estudando eu não fiz meu próprio widget para buscar CEP, então o meu Twig é meio grotesco, mas quem sabe no futuro eu tenha meu próprio Widget para tratar os Ceps.
  2. O Método que optei a fazer é o mesmo que utilizo no Symfony 1.x, o que me possibilitou fazer consultas no meu banco interno indo até a Republica somente para novos CEPS.

TWIG: Ele é simples ele, incluindo um botão para chamar o findCEP(ids[],url), o qual forneço os Ids dos campos que o jQuery tem que popular após consultar o CEP. Note que a URL é um Controller, do Symfony2


{# /var/www/Projeto/src/Projeto/SiteBundle/Resources/views/Clientes/edit.html.twig #}
{% block javascript %}
  
{% endblock %}
{{ form_label(edit_form.cep,"Cep") }}
{{ form_errors(edit_form.cep) }} 
{{form_widget(edit_form.cep}}


{{ form_label(edit_form.rua,"Rua") }}
{{ form_errors(edit_form.rua) }} 
{{ form_widget(edit_form.rua}}
{{ form_label(edit_form.bairro,"Bairro") }}
{{ form_errors(edit_form.bairro) }} 
{{ form_widget(edit_form.bairro}}
{{ form_label(edit_form.cidade,"Estado") }}
{{ form_errors(edit_form.cidade) }} 
{{ form_widget(edit_form.cidade}}
{{ form_label(edit_form.estado,"Estado") }}
{{ form_errors(edit_form.estado) }} 
{{ form_widget(edit_form.estado}}
{{ form_label(edit_form.numero,"Numero") }}
{{ form_errors(edit_form.numero) }} 
{{ form_widget(edit_form.numero}}
{{ form_label(edit_form.complemento,"Complemento") }}
{{ form_errors(edit_form.complemento) }} 
{{ form_widget(edit_form.complemento}}

JS: Recebe os Ids, valida se o CEP não é grotesco, e chama o encapsulador do Symfony.
Note que não estou usando o "data: $(id).val()", isso se dá ao fato de quando eu passar um parâmetro como http://site.com.br/cep?cep=NUMERO o Symfony2 reclamar da rota então eu deixei simplismente funcionando com o http://site.com.br/cep/NUMERO, que não é dos piores métodos.

// /var/www/Projeto/src/web/js/cep.js
function findCEP(idcep,idrua,idbairro,idcidade,idestado,idnumero,url) {
  //Remove os espaços em braco
  if($.trim($('#'+idcep).val()) != ""){
    $("#ajax-loading").css('display','inline');
    $.ajax({
      url : url+"/"+$('#'+idcep).val().replace("-", ""),/* URL que será chamada */ 
      type:'GET',
      beforeSend: function(XMLHttpRequest) {
        $("#ajax-loading").css('display','inline');//Adiciona o Loading
      },
      dataType: 'json',
      failure: function(XMLHttpRequest, textStatus) {
        alert("Erro, Cep não encontrado"); //Avisa se não achar o CEP
      },
      complete: function(XMLHttpRequest, textStatus) {
        var data = $.parseJSON(XMLHttpRequest.responseText);
        if (data.resultado != 0)
        {
             //Preenche o fields utilizando JQuery.
             $('#'+idrua).val(unescape(data.logradouro));
             $('#'+idbairro).val(unescape(data.bairro));
             $('#'+idcidade).val(unescape(data.cidade));
             $('#'+idestado).val(unescape(data.uf));
             $('#'+idnumero).focus();
        }
        $("#ajax-loading").hide(); //Remove o Loading
      }
    }
  );   
  }
}

PHP Controller: Após isso eu peguei minha página de Controllers genéricos e preenchi com o necessário para fazer uma chamada ajax retornando um JSON, como podem ver é bem simples eu retorno um json do Republica Virtual, que vem em XML pois não tem o header apropriado então eu encodo com o json_encode() encapsulo como um Response() para que o Symfony2 não reclame que o retorno é nullo.

OBS: O Republica Virtual corrigiu o bug do json e tive que arrumar na aplicação e o Symfony2 não possui nenhum método próprio de fazer requisições externas então trabalhei com cUrl mesmo.

// /var/www/Projeto/src/Projeto/SiteBundle/Controller
     //...
  public function cepAction($cep){
    $reg = simplexml_load_file("http://cep.republicavirtual.com.br/web_cep.php?formato=json&cep=".$cep);
 
    $dados['resultado'] = (string) $reg->resultado;
    $dados['logradouro']     = (string) $reg->tipo_logradouro . ' ' . $reg->logradouro;
    $dados['bairro']  = (string) $reg->bairro;
    $dados['cidade']  = (string) $reg->cidade;
    $dados['uf']  = (string) $reg->uf;
 
    $response = new \Symfony\Component\HttpFoundation\Response(json_encode($dados));
    $response->headers->set('Content-Type', 'application/json');
    return $response;  

    //Solução em JSON
/*  $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, "http://cep.republicavirtual.com.br/web_cep.php?formato=json&cep=".$cep);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type: application/json')); // Assuming you're requesting JSON
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $dados = curl_exec($ch);
    curl_close($ch);
    $response = new \Symfony\Component\HttpFoundation\Response($dados);
    $response->headers->set('Content-Type', 'application/json'); 
    return $response;  */
    //...
  }

Routing Yml: Após tudo isso ainda falta uma parte crucial, a Routing utilizada para passar o parâmetro, uma simples rota que retorna o valor http://site.com.br/cep/NUMERO como um json, encapsulando a busca do Republica Virtual.

# /var/www/Projeto/src/Projeto/SiteBundle/Resources/config/rougint.yml
cep:
  pattern: /cep/{cep}
  defaults: { _controller: ProjetoSiteBundle:Page:cep, _format: json }
  requirements:
      _method: GET
Espero que tenham apreciado esse detalhe, espero postar essa semana um Validator de CPF/CNPJ para o Symfony2, basta incluir as classes dentro do seu projeto com crtl+C&V e tudo funciona perfeitamente.

Nenhum comentário:

Postar um comentário