Herberth Amaral

Software development adventures

Archive for the ‘PHP’ Category

[Dica] Valide e-mail, IP e URLs no PHP sem regex

with 4 comments

Eu vejo muita gente utilizando regex (expressão regular) para validar vários tipos de dados, incluindo emails, tipos (boolean, string e int), sanitizar dados (remover caracteres inválidos, por exemplo) no PHP. Este tipo de coisa é um saco para quem não saca muito de regex, mas é possível fazer todas estas validações sem o uso de regex utilizando as funções da família filter:

if(filter_var('bob@example.com', FILTER_VALIDATE_EMAIL) )
{
   echo 'Yay!';
}

vários outros filtros que você pode experimentar com esta função super útil e nunca mais precisar lembrar daquela regex chata de email :-)

Happy coding!

[Update]

Esqueci de mencionar: Estas funções estão disponíveis a partir do PHP 5.2.0. Valeu, Almir Mendes!

Written by Herberth Amaral

August 13th, 2010 at 1:21 pm

Posted in PHP

Tagged with ,

Quando uma deficiência pode se tornar uma feature numa linguagem de programação

without comments

Estava lendo um antigo post do Obie Fernandez onde ele lista várias razões do porquê Java é uma porcaria (em tom de brincadeira, claro =). Numa das razões citadas por ele, há o seguinte trecho:

8 ) Java has good debugging support

Java has great and powerful debugging (which is very necessary since most Java code sucks so much ass). Ruby has ridiculously pitiful debugging support, which means our code actually needs to be well-tested and readable.

Traduzindo:

8 ) Java possui um bom suporte a debugging

Java possui um excelente e poderoso debugging (o que é necessário, já que boa parte de códigos em Java são muito ruins). Ruby tem um suporte a debugging lamentavelmente ridículo, o que significa que nosso código realmente precisa ser bem testado e legível.

Vendo por este lado, Ruby é uma excelente linguagem para quem sabe fazer direito e uma droga pra quem está acostumado com IDEs com Intellisense e checagem de erros pelo compilador.

Outras linguagens possuem problemas que são resolvidos facilmente com o uso de testes unitários. Um problema clássico que acontece com o PHP, o White Screen of Death (um erro que acontece com o script que nenhuma informação ou mensagem de erro é apresentada), pode ser resolvido com o uso de testes.

Alguns “problemas” advindos com linguagens dinâmicas é com a mudança de tipo de uma determinada variável, por exemplo:

class Op:
    x = 1    
    y = 3
    def soma(self):
        return self.x + self.y
op = Op()
op.y = "aha!"
op.soma() #Ooopss... TypeError

Este é um tipo de problema que vem com a checagem de tipo em tempo de execução, ao invés de ser feito em tempo de compilação. Muitas pessoas que não possuem a mesma visão do Obie, encaram isto como um problema.

Opinionated Software

Um trecho muito conhecido do Getting Real é o trecho que fala sobre opinionated software:

Your app should take sides

Some people argue software should be agnostic. They say it’s arrogant for developers to limit features or ignore feature requests. They say software should always be as flexible as possible.

We think that’s bullshit. The best software has a vision. The best software takes sides. When someone uses software, they’re not just looking for features, they’re looking for an approach. They’re looking for a vision. Decide what your vision is and run with it.

Traduzindo:

Seu aplicativo deve tomar partido

Algumas pessoas defendem que o software deve ser agnóstico. Dizem que é arrogante da parte dos desenvolvedores limitar a funcionalidade ou ignorar pedidos de novos recursos. Dizem que o software deve ser sempre o mais flexível possível.

Para nós isso é papo-furado. O melhor software traz consigo uma visão. O melhor software toma partido. Quando alguém usa um software, não está procurando apenas recursos, está procurando uma abordagem. Está procurando uma visão. Decida qual é sua visão e atenha-se a ela.

Esta mesma idéia permeia linguagens de programação. Você não achará um linguagem que sirva bem para todos os tipos de casos. Python, por exemplo, não é uma boa linguagem se você quiser usar threads pesadamente. Erlang, apesar de ser uma excelente escolha para programação distribuída e paralela, enfrenta um certo preconceito por ser funcional e não ter suporte à orientação a objetos. C#.NET é uma boa linguagem para criação de aplicativos comerciais, mas não é totalmente portável para todas as plataformas (o Mono mal suporta o .NET 3.5 e o framework já está na versão 4).

Conclusão: antes de reclamar de uma linguagem de programação, saiba que toda linguagem tem um approach, um foco e veja se esta “falha” pode ser algo útil… muitas vezes o é :-)

Written by Herberth Amaral

July 29th, 2010 at 10:34 am

Posted in JavaScript,PHP,Python,agile

Tagged with

Usando o SabreAMF com o CakePHP

with one comment

O AMF é um formato aberto de comunicação do Flash. É o formato preferido para tais aplicações por possuir diversas vantagens, sendo que a principal delas é a velocidade, já que o AMF não precisa ser deserializado como o XML e o JSON.

Por ser um formato aberto, ele pode ser implementado em qualquer linguagem. Há várias implementações para o PHP, sendo que as mais notáveis são o AMFPHP, Zend_AMF e o SabreAMF.

Neste tutorial, eu mostrarei como desenvolver aplicações em PHP com o framework CakePHP que se comunicam com o Flash (usando a plataforma Flex 3) através da biblioteca SabreAMF.

1- Baixando e instalando os componentes

1 – Baixe os CakePHP 1.2.5 no site do CakePHP e o SabreAMF no Google Code.

2- Instale o CakePHP de forma que ele fique disponível em http://localhost/cakeflex.

3 – Descompacte o SabreAmf em app/vendors/SabreAMF

2 – Colocando os dois para trabalhar

Para fazer com que o CakePHP trabalhe de forma transparente com o SabreAMF, é necessário criar um componente para o CakePHP.

Para tal, vamos criar o nosso componente: (salve-o em app/controllers/components/sabre_amf.php)

<?php

set_include_path(APP.'vendors' . PATH_SEPARATOR . get_include_path());
App::import('Vendor', 'SabreAMF_CallbackServer', array('file'=>'SabreAMF/CallbackServer.php'));

class SabreAmfComponent extends Object {

    function startup(&amp;$controller) {
        if ($controller->action == 'gateway') {
            global $_cakeController;
            $_cakeController = $controller;
            Configure::write('debug', 0);
            $controller->autoRender = false;
            $server = new SabreAMF_CallbackServer();
            $server->onInvokeService = array($this,'amfCallBack');
            $server->exec();
            exit;
        }
        else if(empty($controller->amfExclude) ||
                        !in_array($controller->action,$controller->amfExclude))
            exit();
    }

    function amfCallBack($service, $method, $data) {
        global $_cakeController;
        $res = null;
        if ($_cakeController) {
            if (strpos($method, "_") !== 0) {
                if (method_exists($_cakeController, $method)  and
                    !in_array($_cakeController->action,$_cakeController->amfExclude))
                    $res = call_user_func_array( array( $_cakeController, $method ), $data );
                else
                    $res = "Action nao encontrada.";
            } else
                $res = "Nome de metodo invalido.";
        }
        else
            $res = "Controller nao encontrado.";
        return $res;
    }
}
?>

O que nós fizemos acima foi redirecionar todas as chamadas à action ‘gateway’ do controller para nosso gateway do SabreAMF.

Agora, um exemplo de como utilizar isso em um controller:

<?php
// app/controllers/teste_amf_controller.php
class TesteAmfController extends AppController
{
    var $components = array('SabreAmf');

    function hello($nome){
        $ret = "Olá, ".$nome."! agora são: ".date("H:i:s")." horas";
        return  $ret;
    }
}
?>

Nosso server side não estaria completo sem o nosso model. No meu caso, como é só uma demonstração, eu não quero criar uma tabela no banco de dados. Portanto, eu crio o meu model dessa forma:

<?php
// app/models/teste_amf.php
class TesteAmf extends AppModel
{
    var $useTable = false;
}
?>

Para demonstrar nosso código funcionado, nada melhor que uma aplicação Flex. Segue abaixo, um exemplo de como a configuração criada acima pode ser usada no Flex:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">

	<mx:RemoteObject
		endpoint="http://localhost/cakeflex/teste_amf/gateway"
		id="rmoTeste"
		source=""
		destination="minhaApp"
		result="rmoTesteResult(event)"
		fault="rmoTesteFail(event)"
		showBusyCursor="true"
		/>

        <mx:Button label="Hello!" click="rmoTeste.hello('Herberth')" />
        <mx:Script>
		< ![CDATA[
			import mx.rpc.events.FaultEvent;
			import mx.rpc.events.ResultEvent;
			import mx.controls.Alert;

			public function rmoTesteResult(e:ResultEvent):void
			{
				Alert.show(e.result.toString());
			}

			public function rmoTesteFail(e:FaultEvent):void
			{
				Alert.show("Fail!");
			}
		]]>
	</mx:Script>
</mx:Application>

4 – Conclusão

O resultado final deve ficar parecido com isso:

hello_flex

É possível retornar tipos mais complexos para serem usados em tipos mais complexos (tipo AdvancedDataGrid), mas irei abordar tal aplicação mais futuramente.

5 – Referências

É isso aí pessoal. Até a próxima!

Written by Herberth Amaral

December 15th, 2009 at 7:25 pm