SlideShare uma empresa Scribd logo
1 de 76
Baixar para ler offline
PHP ao Extremo
Quem sou eu???


• github.com/thiagophx
• @thiagophx
• thiagorigo.com
• phpml.org
Agenda


• pecl/operator
• pecl/runkit *
• SplTypes
• php5.3.99-dev
<?php

class CarrinhoCompras
{
    protected $produtos;

    public function __construct()
    {
        $this->produtos = array();
    }

    public function addProduto($produto)
    {
        $this->produtos[] = $produto;
    }
}

$obj1 = new CarrinhoCompras();
$obj1->addProduto(new StdClass());
$obj1->addProduto(new StdClass());

$obj2 = new CarrinhoCompras();
$obj2->addProduto(new StdClass());
$obj2->addProduto(new StdClass());

echo $obj1 + $obj2;
<?php

class CarrinhoCompras
{
    protected $produtos;

    public function __construct()
    {
        $this->produtos = array();
    }

    public function addProduto($produto)
    {
        $this->produtos[] = $produto;
    }
}

$obj1 = new CarrinhoCompras();
$obj1->addProduto(new StdClass());
$obj1->addProduto(new StdClass());

$obj2 = new CarrinhoCompras();
$obj2->addProduto(new StdClass());
$obj2->addProduto(new StdClass());

echo $obj1 + $obj2;

// Notice: Object of class CarrinhoCompras could not be converted to int...
<?php

class CarrinhoCompras
{
    protected $produtos;

    public function __construct()
    {
        $this->produtos = array();
    }

    public function addProduto($produto)
    {
        $this->produtos[] = $produto;
    }

    public function count()
    {
        return count($this->produtos);
    }
}

$obj1 = new CarrinhoCompras();
$obj1->addProduto(new StdClass());
$obj1->addProduto(new StdClass());

$obj2 = new CarrinhoCompras();
$obj2->addProduto(new StdClass());
$obj2->addProduto(new StdClass());

echo $obj1->count() + $obj2->count();
<?php

class CarrinhoCompras implements Countable
{
    protected $produtos;

    public function __construct()
    {
        $this->produtos = array();
    }

    public function addProduto($produto)
    {
        $this->produtos[] = $produto;
    }

    public function count()
    {
        return count($this->produtos);
    }
}

$obj1 = new CarrinhoCompras();
$obj1->addProduto(new StdClass());
$obj1->addProduto(new StdClass());

$obj2 = new CarrinhoCompras();
$obj2->addProduto(new StdClass());
$obj2->addProduto(new StdClass());

echo count($obj1) + count($obj2);
Porque isso funciona?

     <?php

     $d1 = new DateTime();
     $d2 = new DateTime('1991-10-21');

     var_dump($d1 > $d2);
<?php

class CarrinhoCompras
{
    protected $produtos;

    public function __construct()
    {
        $this->produtos = array();
    }

    public function addProduto($produto)
    {
        $this->produtos[] = $produto;
    }
}

$obj1 = new CarrinhoCompras();
$obj1->addProduto(new StdClass());
$obj1->addProduto(new StdClass());

$obj2 = new CarrinhoCompras();
$obj2->addProduto(new StdClass());
$obj2->addProduto(new StdClass());
$obj2->addProduto(new StdClass());

var_dump($obj1 > $obj2);
Sobrecarga de operador
sudo pecl install -f operator
<?php

class CarrinhoCompras
{
    protected $produtos;

    public function __construct()
    {
        $this->produtos = array();
    }

    public function addProduto($produto)
    {
        $this->produtos[] = $produto;
    }

    public function __add(CarrinhoCompras $carrinho = null)
    {
        return count($this->produtos) + ($carrinho ? $carrinho->__add() : 0);
    }
}

$obj1 = new CarrinhoCompras();
$obj1->addProduto(new StdClass());
$obj1->addProduto(new StdClass());

$obj2 = new CarrinhoCompras();
$obj2->addProduto(new StdClass());
$obj2->addProduto(new StdClass());

echo $obj1 + $obj2;
<?php

interface Summable
{
    public function __add(Summable $value = null);
}

class CarrinhoCompras implements Summable
{
    protected $produtos;

    public function __construct()
    {
        $this->produtos = array();
    }

    public function addProduto($produto)
    {
        $this->produtos[] = $produto;
    }

    public function __add(Summable $value = null)
    {
        return count($this->produtos) + ($value ? $value->__add() : 0);
    }
}

$obj1 = new CarrinhoCompras();
$obj1->addProduto(new StdClass());
$obj1->addProduto(new StdClass());

$obj2 = new CarrinhoCompras();
$obj2->addProduto(new StdClass());
$obj2->addProduto(new StdClass());

echo $obj1 + $obj2;
<?php

class CarrinhoCompras
{
    protected $produtos;

    public function __construct()
    {
        $this->produtos = array();
    }

    public function addProduto($produto)
    {
        $this->produtos[] = $produto;
    }

    public function __add(CarrinhoCompras $carrinho = null)
    {
        return count($this->produtos) + ($carrinho ? $carrinho->__add() : 0);
    }
}

$obj1 = new CarrinhoCompras();
$obj1->addProduto(new StdClass());

$obj2 = new CarrinhoCompras();
$obj2->addProduto(new StdClass());

$obj3 = new CarrinhoCompras();
$obj3->addProduto(new StdClass());

var_dump($obj1 + $obj2 + $obj3);

// ???
<?php

class CarrinhoCompras
{
    protected $produtos;

    public function __construct()
    {
        $this->produtos = array();
    }

    public function addProduto($produto)
    {
        $this->produtos[] = $produto;
    }

    public function __add(CarrinhoCompras $carrinho = null)
    {
        return count($this->produtos) + ($carrinho ? $carrinho->__add() : 0);
    }
}

$obj1 = new CarrinhoCompras();
$obj1->addProduto(new StdClass());

$obj2 = new CarrinhoCompras();
$obj2->addProduto(new StdClass());

$obj3 = new CarrinhoCompras();
$obj3->addProduto(new StdClass());

var_dump($obj1 + $obj2 + $obj3);

// Notice:   Object of class CarrinhoCompras could not be converted to int...
<?php

class CarrinhoCompras
{
    protected $produtos;

    public function __construct()
    {
        $this->produtos = array();
    }

    public function addProduto($produto)
    {
        $this->produtos[] = $produto;
    }

    public function __add($value = null)
    {
        if (is_int($value))
            return count($this->produtos) + $value;

        return count($this->produtos) + ($value ? $value->__add() : 0);
    }
}

$obj1 = new CarrinhoCompras();
$obj1->addProduto(new StdClass());

$obj2 = new CarrinhoCompras();
$obj2->addProduto(new StdClass());

$obj3 = new CarrinhoCompras();
$obj3->addProduto(new StdClass());

var_dump($obj1 + ($obj2 + $obj3));
Exemplo do mundo real
<?php

class ContaCorrente // Entity
{
    public function depositar(Dinheiro $valor)
    {
        $this->setSaldo($this->getSaldo() + $valor);
    }
}

class Dinheiro // ValueObject
{
    const BRL = 1;
    const AUD = 2;

    protected $tipoMoeda;

    public function getTipoMoeda() { ... }

    public function converte($tipoMoeda)
    {
        return $this->getValor() * $tipoMoeda;
    }

    public function __add($dinheiro)
    {
        return $this->getValor() + $dinheiro->convert($this->getTipoMoeda());
    }
}

$conta = new ContaCorrente(/* id */);
$valor = new Dinheiro(100);
$conta->depositar($valor);
Operadores disponíveis


   +, -, *, /, %, <<, >>, ., |, &, ^, ~, !, ++, --, +=, -=, *=,
/=, %=, <<=, >>=, .=, |=, &=, ^=, ~=, ==, !=, ===, !==, <, <=
Nada é perfeito...



• Só funciona no 5.2
Injeção de Dependência
Injeção de Dependência
 <?php

 // Zend Framework: A setter injection example
 $transport = new Zend_Mail_Transport_Smtp('smtp.gmail.com', array(
   'auth'     => 'login',
   'username' => 'foo',
   'password' => 'bar',
   'ssl'      => 'ssl',
   'port'     => 465,
 ));
  
 $mailer = new Zend_Mail();
 $mailer->setDefaultTransport($transport);
Container de Injeção de Dependência
Symfony
<?xml version="1.0" ?>
 
<container xmlns="http://symfony-project.org/2.0/container">
  <parameters>
    <parameter key="mailer.username">foo</parameter>
    <parameter key="mailer.password">bar</parameter>
    <parameter key="mailer.class">Zend_Mail</parameter>
  </parameters>
  <services>
    <service id="mail.transport" class="Zend_Mail_Transport_Smtp" shared="false">
      <argument>smtp.gmail.com</argument>
      <argument type="collection">
        <argument key="auth">login</argument>
        <argument key="username">%mailer.username%</argument>
        <argument key="password">%mailer.password%</argument>
        <argument key="ssl">ssl</argument>
        <argument key="port">465</argument>
      </argument>
    </service>
    <service id="mailer" class="%mailer.class%">
      <call method="setDefaultTransport">
        <argument type="service" id="mail.transport" />
      </call>
    </service>
  </services>
</container>
Symfony

<?php
require_once '/PATH/TO/sfServiceContainerAutoloader.php';
sfServiceContainerAutoloader::register();
 
$sc = new sfServiceContainerBuilder();
 
$loader = new sfServiceContainerLoaderFileXml($sc);
$loader->load('/somewhere/container.xml');
$sc->mailer;
Inversão de Controle
Você não chama, você é chamado!
<?php

class UserService
{
    protected $serviceLocator;

    public function __construct($serviceLocator)
    {
        $this->serviceLocator = $serviceLocator;
    }

    public function saveUser(array $data)
    {
        $validator = $this->serviceLocator->getService('validator');

        try {
            // Valida os dados
            $data = $validator->validate($data);

            $repository = new UserRepository();
            $user = new User();

            // Persiste os dados
            return $repository->save($data, $user);

        } catch (Exception $e) {
            $this->serviceLocator->getService('logger')->log($e);
        }

        return null;
    }
}
<?php

class UserService
{
    /**
     * @Dependency(validator)
     */
    protected $validator;

    /**
     * @Dependency(logger)
     */
    protected $logger;

    public function saveUser(array $data)
    {
        try {
            // Valida os dados
            $data = $this->validator->validate($data);

            $repository = new UserRepository();
            $user = new User();

            // Persiste os dados
            return $repository->save($data, $user);

        } catch (Exception $e) {
            $this->logger->log($e);
        }

        return null;
    }
}
runkit
https://github.com/zenovich/runkit/
<?php

class Container
{
    protected static $data = array('mailer' => 'mailer');

    public static function get($key)
    {
        if (!self::exists($key))
            throw new InvalidArgumentException('Invalid key!');

        return self::$data[$key];
    }

    public static function exists($key)
    {
        return array_key_exists($key, self::$data);
    }

    public static function notify($object)
    {
        $injector = new Injector($object, self::$data);
        return $injector->inject();
    }
}
<?php

class Watcher
{
    protected $dir;

    public function __construct($dir)
    {
        $this->dir = $dir;
    }

    public function watch()
    {
        foreach (glob($this->dir . DIRECTORY_SEPARATOR . '*.php') as $class) {
            require $class;
            runkit_method_add(pathinfo($class, PATHINFO_FILENAME),
            '__construct',
            '',
            'Container::notify($this);');
        }
    }
}
<?php

class Injector
{
    protected $object;

    public function __construct($object)
    {
        $this->object = $object;
    }

    public function inject()
    {
        $reflection = new ReflectionObject($this->object);
        $prop = $reflection->getProperty('mailer');

        if (!Container::exists('mailer'))
            return null;

        $prop->setAccessible(true);
        $prop->setValue($this->object, Container::get('mailer'));
        return true;
    }
}
<?php

class Controller
{
    protected $mailer;

    public function get()
    {
        var_dump($this->mailer);
    }
}
<?php

$w = new Watcher('path/to/my/folder');
$w->watch();

$c = new Controller();
$c->get();
// string(6) "mailer"
<?php

class UserService
{
    /**
     * @Dependency(validator)
     */
    protected $validator;

    /**
     * @Dependency(logger)
     */
    protected $logger;

    public function saveUser(array $data)
    {
        try {
            // Valida os dados
            $data = $this->validator->validate($data);

            $repository = new UserRepository();
            $user = new User();

            // Persiste os dados
            return $repository->save($data, $user);

        } catch (Exception $e) {
            $this->logger->log($e);
        }

        return null;
    }
}
<?php

class AnnotationParser
{
    protected $class;

    public function __construct(ReflectionClass $class)
    {
        $this->class = $class;
    }

    public function parseDependencies()
    {
        $dependencies = array();

        foreach ($this->class->getProperties() as $prop)
            if ($this->matchDependency($prop, $matches))
                $dependencies[] = array('property' => $prop, 'dependency' => $matches[1]);

        return $dependencies;
    }

    protected function matchDependency($prop, &$matches)
    {
        return (bool) preg_match('/@dependencys*(([a-zA-Z0-9_ ]*))/i',
            $prop->getDocComment(), $matches);
    }
}
<?php

class Injector
{
    protected $object;

    public function __construct($object)
    {
        $this->object = $object;
    }

    public function inject()
    {
        $annotationParser = new AnnotationParser(new ReflectionObject($this->object));
        $props = $annotationParser->parseDependencies();

        foreach ($props as $prop) {
            if (Container::exists($prop['dependency'])) {
                $prop['property']->setAccessible(true);
                $prop['property']->setValue($this->object,
                    Container::get($prop['dependency']));
            }

        }
    }
}
<?php

class Container
{
    protected static $data = array();

    public static function set($key, $value)
    {
        self::$data[$key] = $value;
    }

    public static function get($key)
    {
        if (!self::exists($key))
            throw new InvalidArgumentException('Invalid key!');

        return self::$data[$key];
    }

    public static function exists($key)
    {
        return array_key_exists($key, self::$data);
    }

    public static function notify($object)
    {
        $injector = new Injector($object, self::$data);
        return $injector->inject();
    }
}
<?php

class Validator
{
    public function validate()
    {
        // ...
    }
}

class Logger
{
    public function log()
    {
        // ...
    }
}

$w = new Watcher('path/to/my/folder');
$w->watch();

Container::set('validator', new Validator());
Container::set('logger', new Logger());

$c = new UserService();
$c->saveUser(array());
Melhorias


• Verificar existência de __construct
• Pegar os parametros do __construct
• Observar classes dentro de
  namespaces(recursivo)
Recursos


• function_add, *_remove, *_copy,
  *_redefine, *_rename
• method_add, *_remove, *_copy,
  *_redefine, *_rename
E agora???


• Tokenizer
• Mutagenesis (https://github.com/
  padraic/mutagenesis)
Variáveis Tipadas
PHP tem tipo???
<?php

$id = $_GET['id']; // int
$valor = $_GET['valor']; // float
<?php

$id = (int) $_GET['id']; // int
$valor = (float) $_GET['valor']; // float
<?php

$id = $_GET['id']; // int
$valor = $_GET['valor']; // float

function processa($id, $valor)
{
    // ...
}
<?php

$id = $_GET['id']; // int
$valor = $_GET['valor']; // float

function processa($id, $valor)
{
    $id = (int) $id;
    $valor = (float) $valor;

    echo $id, $valor;
}

processa($id, $valor);
<?php

$id = $_GET['id']; // int
$valor = $_GET['valor']; // float

function processa($id, $valor)
{
    if (!is_int($id))
        throw new InvalidArgumentException('Tipo inválido');

    if (!is_float($valor))
        throw new InvalidArgumentException('Tipo inválido');

    echo $id, $valor;
}

processa($id, $valor);
<?php

$id = $_GET['id']; // int
$valor = $_GET['valor']; // float

function processa(Integer $id, Float $valor)
{
    echo $id, $valor;
}

processa(new Integer($id), new Float($valor));
sudo pecl install spl_types
<?php

$id = $_GET['id']; // int
$valor = $_GET['valor']; // float

function processa(SplInt $id, SplFloat $valor)
{
    echo $id, $valor;
}

processa(new SplInt($id), new SplFloat($valor));
<?php

$int = new SplInt('10');
// ?
<?php

$int = new SplInt('10');
// UnexpectedValueException: Value not an integer
<?php

$int = new SplInt('10', false);
// Ok
<?php

$int = new SplInt('10');

if (!is_int('10'))
    throw new InvalidArgumentException('Tipo inválido');



$int1 = new SplInt('10', false);
$int2 = '10';

if (!is_int($int2))
    $int2 = (int) $int2;
<?php

$int = new SplInt(10);
$int = 10;

$int1 = new SplInt('10', false);
$int1 = '10';
<?php

$int = new SplInt(10);
$float = new SplFloat(10.7);

echo    $float   +   $int;
echo    $float   -   $int;
echo    $float   /   $int;
echo    $float   *   $int;
<?php

$id = $_GET['id']; // int
$valor = $_GET['valor']; // float

function processa(SplInt $id, SplFloat $valor)
{
    echo $id, $valor;
}

processa($id, $valor);
// Catchable fatal error: Argument 1 passed to processa() must be an instance of SplInt
// Catchable fatal error: Argument 2 passed to processa() must be an instance of SplFloat
<?php

class Month extends SplEnum
{
    const __default = self::January;

    const   January = 1;
    const   February = 2;
    const   March = 3;
    const   April = 4;
    const   May = 5;
    const   June = 6;
    const   July = 7;
    const   August = 8;
    const   September = 9;
    const   October = 10;
    const   November = 11;
    const   December = 12;
}
<?php

class Month extends SplEnum
{
    const __default = self::January;

    const   January = 1;
    const   February = 2;
    const   March = 3;
    const   April = 4;
    const   May = 5;
    const   June = 6;
    const   July = 7;
    const   August = 8;
    const   September = 9;
    const   October = 10;
    const   November = 11;
    const   December = 12;
}

function getMonth(Month $month)
{
    echo $month;
}

getMonth(new Month(Month::October));
<?php

class Month extends SplEnum
{
    const __default = self::January;

    const   January = 1;
    const   February = 2;
    const   March = 3;
    const   April = 4;
    const   May = 5;
    const   June = 6;
    const   July = 7;
    const   August = 8;
    const   September = 9;
    const   October = 10;
    const   November = 11;
    const   December = 12;
}

function getMonth(Month $month)
{
    echo $month;
}

getMonth(new Month(13));
// UnexpectedValueException: Value not a const in enum Month
<?php

class Month extends SplEnum
{
    const __default = self::January;

    const   January = 1;
    const   February = 2;
    const   March = 3;
    const   April = 4;
    const   May = 5;
    const   June = 6;
    const   July = 7;
    const   August = 8;
    const   September = 9;
    const   October = 10;
    const   November = 11;
    const   December = 12;
}

$month = new Month();
var_dump($month->getConstList());
Scalar Type Hinting
<?php

function foo(array $value)
{
    // ...
}
<?php

function testInt(integer $value)
{
    var_dump($value);
}

testInt(1);
http://svn.php.net/viewvc?
view=revision&revision=299534
https://svn.php.net/repository/php/php-src/
     branches/WITH_SCALAR_TYPES/
http://ilia.ws/archives/207-Type-Hinting-
              Conclusion.html
<?php

function testInt(integer $value)
{
    var_dump($value);
}

testInt('PHPubSP');
// Catchable fatal error: Argument 1 passed to testInt() must be of the type integer,
string given
<?php

function testNumeric(numeric $value)
{
    var_dump($value);
}

testNumeric('10');
<?php

function testCast((int) $value)
{
    var_dump($value);
}

testCast('10');
<?php

function testScalar(scalar $value)
{
    var_dump($value);
}

testScalar('10');
<?php

function testBool(bool $value)
{
    // ...
}

function testString(string $value)
{
    // ...
}

function testFloat(float $value)
{
    // ...
}
Perguntas???

Mais conteúdo relacionado

Mais procurados

Introdução ao Respect\Validation (1.0)
Introdução ao Respect\Validation (1.0)Introdução ao Respect\Validation (1.0)
Introdução ao Respect\Validation (1.0)Henrique Moody
 
Palestra Novidades da linguagem C# 6
Palestra Novidades da linguagem C# 6Palestra Novidades da linguagem C# 6
Palestra Novidades da linguagem C# 6Renato Haddad
 
Programando em python dicionarios
Programando em python   dicionariosProgramando em python   dicionarios
Programando em python dicionariossamuelthiago
 
modernizando a arquitertura de sua aplicação
modernizando a arquitertura  de sua aplicaçãomodernizando a arquitertura  de sua aplicação
modernizando a arquitertura de sua aplicaçãoAntonio Spinelli
 
Da Argila Ao Forte - Como desenvolver uma loja virtual
Da Argila Ao Forte - Como desenvolver uma loja virtualDa Argila Ao Forte - Como desenvolver uma loja virtual
Da Argila Ao Forte - Como desenvolver uma loja virtualMichael Castillo Granados
 
LabMM4 (T13 - 12/13) - Funções
LabMM4 (T13 - 12/13) - FunçõesLabMM4 (T13 - 12/13) - Funções
LabMM4 (T13 - 12/13) - FunçõesCarlos Santos
 
Criando APIs usando o micro-framework Respect
Criando APIs usando o micro-framework RespectCriando APIs usando o micro-framework Respect
Criando APIs usando o micro-framework RespectIvan Rosolen
 
Java 8 - Afinal onde usamos no dia a dia? TDC 2015 - Porto Alegre
Java 8 - Afinal onde usamos no dia a dia? TDC 2015 - Porto AlegreJava 8 - Afinal onde usamos no dia a dia? TDC 2015 - Porto Alegre
Java 8 - Afinal onde usamos no dia a dia? TDC 2015 - Porto AlegreFrederico Maia Arantes
 
Hooks, o condimento mágico e escondido do WordPress
Hooks, o condimento mágico e escondido do WordPressHooks, o condimento mágico e escondido do WordPress
Hooks, o condimento mágico e escondido do WordPressZé Fontainhas
 
Criando controle de acesso com php e my sql
Criando controle de acesso com php e my sqlCriando controle de acesso com php e my sql
Criando controle de acesso com php e my sqlPaulo Damas
 
Refactoring sem complicação!
Refactoring sem complicação!Refactoring sem complicação!
Refactoring sem complicação!Thamara Hessel
 
Orientação a Objetos em PHP
Orientação a Objetos em PHPOrientação a Objetos em PHP
Orientação a Objetos em PHPzehzinho
 

Mais procurados (20)

Introdução ao Respect\Validation (1.0)
Introdução ao Respect\Validation (1.0)Introdução ao Respect\Validation (1.0)
Introdução ao Respect\Validation (1.0)
 
Palestra Novidades da linguagem C# 6
Palestra Novidades da linguagem C# 6Palestra Novidades da linguagem C# 6
Palestra Novidades da linguagem C# 6
 
Programando em python dicionarios
Programando em python   dicionariosProgramando em python   dicionarios
Programando em python dicionarios
 
modernizando a arquitertura de sua aplicação
modernizando a arquitertura  de sua aplicaçãomodernizando a arquitertura  de sua aplicação
modernizando a arquitertura de sua aplicação
 
Da Argila Ao Forte - Como desenvolver uma loja virtual
Da Argila Ao Forte - Como desenvolver uma loja virtualDa Argila Ao Forte - Como desenvolver uma loja virtual
Da Argila Ao Forte - Como desenvolver uma loja virtual
 
Minicurso de jQuery
Minicurso de jQueryMinicurso de jQuery
Minicurso de jQuery
 
LabMM4 (T13 - 12/13) - Funções
LabMM4 (T13 - 12/13) - FunçõesLabMM4 (T13 - 12/13) - Funções
LabMM4 (T13 - 12/13) - Funções
 
Clean code
Clean codeClean code
Clean code
 
Criando APIs usando o micro-framework Respect
Criando APIs usando o micro-framework RespectCriando APIs usando o micro-framework Respect
Criando APIs usando o micro-framework Respect
 
SPL Datastructures
SPL DatastructuresSPL Datastructures
SPL Datastructures
 
Php curl - Coleta de dados na web
Php curl - Coleta de dados na webPhp curl - Coleta de dados na web
Php curl - Coleta de dados na web
 
Introdução ao MongoDB
Introdução ao MongoDBIntrodução ao MongoDB
Introdução ao MongoDB
 
Java 8 - Afinal onde usamos no dia a dia? TDC 2015 - Porto Alegre
Java 8 - Afinal onde usamos no dia a dia? TDC 2015 - Porto AlegreJava 8 - Afinal onde usamos no dia a dia? TDC 2015 - Porto Alegre
Java 8 - Afinal onde usamos no dia a dia? TDC 2015 - Porto Alegre
 
Hooks, o condimento mágico e escondido do WordPress
Hooks, o condimento mágico e escondido do WordPressHooks, o condimento mágico e escondido do WordPress
Hooks, o condimento mágico e escondido do WordPress
 
Java script - funções
Java script - funçõesJava script - funções
Java script - funções
 
Escrevendo plugins JQuery
Escrevendo plugins JQueryEscrevendo plugins JQuery
Escrevendo plugins JQuery
 
Spring Capitulo 03
Spring Capitulo 03Spring Capitulo 03
Spring Capitulo 03
 
Criando controle de acesso com php e my sql
Criando controle de acesso com php e my sqlCriando controle de acesso com php e my sql
Criando controle de acesso com php e my sql
 
Refactoring sem complicação!
Refactoring sem complicação!Refactoring sem complicação!
Refactoring sem complicação!
 
Orientação a Objetos em PHP
Orientação a Objetos em PHPOrientação a Objetos em PHP
Orientação a Objetos em PHP
 

Semelhante a PHP ao Extremo

Clean Code e Object Calisthenics - Aplicados no PHP
Clean Code e Object Calisthenics - Aplicados no PHPClean Code e Object Calisthenics - Aplicados no PHP
Clean Code e Object Calisthenics - Aplicados no PHPRafael Neris
 
Ecommerce, mais simples do que parece
Ecommerce, mais simples do que pareceEcommerce, mais simples do que parece
Ecommerce, mais simples do que pareceImpacta Eventos
 
ZF Básico - 6. Autenticação
ZF Básico - 6. AutenticaçãoZF Básico - 6. Autenticação
ZF Básico - 6. AutenticaçãoMarcos Bezerra
 
Programação web ii aulas 06 e 07
Programação web ii   aulas 06 e 07Programação web ii   aulas 06 e 07
Programação web ii aulas 06 e 07Yuri Bispo
 
Como conectar programas em linguagem java a bases de dados
Como conectar programas em linguagem java  a bases de dadosComo conectar programas em linguagem java  a bases de dados
Como conectar programas em linguagem java a bases de dadosHenrique Fernandes
 
As novidades do PHP5 (2005)
As novidades do PHP5 (2005)As novidades do PHP5 (2005)
As novidades do PHP5 (2005)Pablo Dall'Oglio
 
Aula 12 Relatório - Tabelas
Aula 12   Relatório - TabelasAula 12   Relatório - Tabelas
Aula 12 Relatório - TabelasDalton Martins
 
Vraptor - Alta produtividade no Desenvolvimento Web em Java
Vraptor - Alta produtividade no Desenvolvimento Web em JavaVraptor - Alta produtividade no Desenvolvimento Web em Java
Vraptor - Alta produtividade no Desenvolvimento Web em JavaKaio Valente
 
PHP robusto com Zend Framework
PHP robusto com Zend FrameworkPHP robusto com Zend Framework
PHP robusto com Zend FrameworkJaime Neto
 
Symfony - Framework PHP de alta produtividade
Symfony - Framework PHP de alta produtividadeSymfony - Framework PHP de alta produtividade
Symfony - Framework PHP de alta produtividadeHugo Magalhães
 
Código legado - PHP Conference Brasil - 2014
Código legado - PHP Conference Brasil - 2014Código legado - PHP Conference Brasil - 2014
Código legado - PHP Conference Brasil - 2014Michael Castillo Granados
 
PHP: Linguagem + Mysql + MVC + AJAX
PHP: Linguagem + Mysql + MVC + AJAX PHP: Linguagem + Mysql + MVC + AJAX
PHP: Linguagem + Mysql + MVC + AJAX Sérgio Souza Costa
 
Play Framework - FLISOL
Play Framework - FLISOLPlay Framework - FLISOL
Play Framework - FLISOLgrupoweblovers
 
Refatoração de código com Capitão Nascimento versão completa
Refatoração de código com Capitão Nascimento versão completaRefatoração de código com Capitão Nascimento versão completa
Refatoração de código com Capitão Nascimento versão completaEduardo Bregaida
 

Semelhante a PHP ao Extremo (20)

Clean Code e Object Calisthenics - Aplicados no PHP
Clean Code e Object Calisthenics - Aplicados no PHPClean Code e Object Calisthenics - Aplicados no PHP
Clean Code e Object Calisthenics - Aplicados no PHP
 
Ecommerce, mais simples do que parece
Ecommerce, mais simples do que pareceEcommerce, mais simples do que parece
Ecommerce, mais simples do que parece
 
Ecommerce, mais simples do que parece
Ecommerce, mais simples do que pareceEcommerce, mais simples do que parece
Ecommerce, mais simples do que parece
 
Bread board
Bread boardBread board
Bread board
 
Aula5
Aula5Aula5
Aula5
 
Vraptor
VraptorVraptor
Vraptor
 
Curso de Introdução - PHP
Curso de Introdução - PHPCurso de Introdução - PHP
Curso de Introdução - PHP
 
ZF Básico - 6. Autenticação
ZF Básico - 6. AutenticaçãoZF Básico - 6. Autenticação
ZF Básico - 6. Autenticação
 
Programação web ii aulas 06 e 07
Programação web ii   aulas 06 e 07Programação web ii   aulas 06 e 07
Programação web ii aulas 06 e 07
 
Como conectar programas em linguagem java a bases de dados
Como conectar programas em linguagem java  a bases de dadosComo conectar programas em linguagem java  a bases de dados
Como conectar programas em linguagem java a bases de dados
 
As novidades do PHP5 (2005)
As novidades do PHP5 (2005)As novidades do PHP5 (2005)
As novidades do PHP5 (2005)
 
Aula 12 Relatório - Tabelas
Aula 12   Relatório - TabelasAula 12   Relatório - Tabelas
Aula 12 Relatório - Tabelas
 
Vraptor - Alta produtividade no Desenvolvimento Web em Java
Vraptor - Alta produtividade no Desenvolvimento Web em JavaVraptor - Alta produtividade no Desenvolvimento Web em Java
Vraptor - Alta produtividade no Desenvolvimento Web em Java
 
PHP robusto com Zend Framework
PHP robusto com Zend FrameworkPHP robusto com Zend Framework
PHP robusto com Zend Framework
 
Symfony - Framework PHP de alta produtividade
Symfony - Framework PHP de alta produtividadeSymfony - Framework PHP de alta produtividade
Symfony - Framework PHP de alta produtividade
 
Código legado - PHP Conference Brasil - 2014
Código legado - PHP Conference Brasil - 2014Código legado - PHP Conference Brasil - 2014
Código legado - PHP Conference Brasil - 2014
 
PHP: Linguagem + Mysql + MVC + AJAX
PHP: Linguagem + Mysql + MVC + AJAX PHP: Linguagem + Mysql + MVC + AJAX
PHP: Linguagem + Mysql + MVC + AJAX
 
Play Framework - FLISOL
Play Framework - FLISOLPlay Framework - FLISOL
Play Framework - FLISOL
 
PHP fora da Web
PHP fora da WebPHP fora da Web
PHP fora da Web
 
Refatoração de código com Capitão Nascimento versão completa
Refatoração de código com Capitão Nascimento versão completaRefatoração de código com Capitão Nascimento versão completa
Refatoração de código com Capitão Nascimento versão completa
 

PHP ao Extremo

  • 2. Quem sou eu??? • github.com/thiagophx • @thiagophx • thiagorigo.com • phpml.org
  • 3. Agenda • pecl/operator • pecl/runkit * • SplTypes • php5.3.99-dev
  • 4. <?php class CarrinhoCompras { protected $produtos; public function __construct() { $this->produtos = array(); } public function addProduto($produto) { $this->produtos[] = $produto; } } $obj1 = new CarrinhoCompras(); $obj1->addProduto(new StdClass()); $obj1->addProduto(new StdClass()); $obj2 = new CarrinhoCompras(); $obj2->addProduto(new StdClass()); $obj2->addProduto(new StdClass()); echo $obj1 + $obj2;
  • 5. <?php class CarrinhoCompras { protected $produtos; public function __construct() { $this->produtos = array(); } public function addProduto($produto) { $this->produtos[] = $produto; } } $obj1 = new CarrinhoCompras(); $obj1->addProduto(new StdClass()); $obj1->addProduto(new StdClass()); $obj2 = new CarrinhoCompras(); $obj2->addProduto(new StdClass()); $obj2->addProduto(new StdClass()); echo $obj1 + $obj2; // Notice: Object of class CarrinhoCompras could not be converted to int...
  • 6. <?php class CarrinhoCompras { protected $produtos; public function __construct() { $this->produtos = array(); } public function addProduto($produto) { $this->produtos[] = $produto; } public function count() { return count($this->produtos); } } $obj1 = new CarrinhoCompras(); $obj1->addProduto(new StdClass()); $obj1->addProduto(new StdClass()); $obj2 = new CarrinhoCompras(); $obj2->addProduto(new StdClass()); $obj2->addProduto(new StdClass()); echo $obj1->count() + $obj2->count();
  • 7. <?php class CarrinhoCompras implements Countable { protected $produtos; public function __construct() { $this->produtos = array(); } public function addProduto($produto) { $this->produtos[] = $produto; } public function count() { return count($this->produtos); } } $obj1 = new CarrinhoCompras(); $obj1->addProduto(new StdClass()); $obj1->addProduto(new StdClass()); $obj2 = new CarrinhoCompras(); $obj2->addProduto(new StdClass()); $obj2->addProduto(new StdClass()); echo count($obj1) + count($obj2);
  • 8. Porque isso funciona? <?php $d1 = new DateTime(); $d2 = new DateTime('1991-10-21'); var_dump($d1 > $d2);
  • 9. <?php class CarrinhoCompras { protected $produtos; public function __construct() { $this->produtos = array(); } public function addProduto($produto) { $this->produtos[] = $produto; } } $obj1 = new CarrinhoCompras(); $obj1->addProduto(new StdClass()); $obj1->addProduto(new StdClass()); $obj2 = new CarrinhoCompras(); $obj2->addProduto(new StdClass()); $obj2->addProduto(new StdClass()); $obj2->addProduto(new StdClass()); var_dump($obj1 > $obj2);
  • 11. sudo pecl install -f operator
  • 12. <?php class CarrinhoCompras { protected $produtos; public function __construct() { $this->produtos = array(); } public function addProduto($produto) { $this->produtos[] = $produto; } public function __add(CarrinhoCompras $carrinho = null) { return count($this->produtos) + ($carrinho ? $carrinho->__add() : 0); } } $obj1 = new CarrinhoCompras(); $obj1->addProduto(new StdClass()); $obj1->addProduto(new StdClass()); $obj2 = new CarrinhoCompras(); $obj2->addProduto(new StdClass()); $obj2->addProduto(new StdClass()); echo $obj1 + $obj2;
  • 13. <?php interface Summable { public function __add(Summable $value = null); } class CarrinhoCompras implements Summable { protected $produtos; public function __construct() { $this->produtos = array(); } public function addProduto($produto) { $this->produtos[] = $produto; } public function __add(Summable $value = null) { return count($this->produtos) + ($value ? $value->__add() : 0); } } $obj1 = new CarrinhoCompras(); $obj1->addProduto(new StdClass()); $obj1->addProduto(new StdClass()); $obj2 = new CarrinhoCompras(); $obj2->addProduto(new StdClass()); $obj2->addProduto(new StdClass()); echo $obj1 + $obj2;
  • 14. <?php class CarrinhoCompras { protected $produtos; public function __construct() { $this->produtos = array(); } public function addProduto($produto) { $this->produtos[] = $produto; } public function __add(CarrinhoCompras $carrinho = null) { return count($this->produtos) + ($carrinho ? $carrinho->__add() : 0); } } $obj1 = new CarrinhoCompras(); $obj1->addProduto(new StdClass()); $obj2 = new CarrinhoCompras(); $obj2->addProduto(new StdClass()); $obj3 = new CarrinhoCompras(); $obj3->addProduto(new StdClass()); var_dump($obj1 + $obj2 + $obj3); // ???
  • 15. <?php class CarrinhoCompras { protected $produtos; public function __construct() { $this->produtos = array(); } public function addProduto($produto) { $this->produtos[] = $produto; } public function __add(CarrinhoCompras $carrinho = null) { return count($this->produtos) + ($carrinho ? $carrinho->__add() : 0); } } $obj1 = new CarrinhoCompras(); $obj1->addProduto(new StdClass()); $obj2 = new CarrinhoCompras(); $obj2->addProduto(new StdClass()); $obj3 = new CarrinhoCompras(); $obj3->addProduto(new StdClass()); var_dump($obj1 + $obj2 + $obj3); // Notice: Object of class CarrinhoCompras could not be converted to int...
  • 16. <?php class CarrinhoCompras { protected $produtos; public function __construct() { $this->produtos = array(); } public function addProduto($produto) { $this->produtos[] = $produto; } public function __add($value = null) { if (is_int($value)) return count($this->produtos) + $value; return count($this->produtos) + ($value ? $value->__add() : 0); } } $obj1 = new CarrinhoCompras(); $obj1->addProduto(new StdClass()); $obj2 = new CarrinhoCompras(); $obj2->addProduto(new StdClass()); $obj3 = new CarrinhoCompras(); $obj3->addProduto(new StdClass()); var_dump($obj1 + ($obj2 + $obj3));
  • 18. <?php class ContaCorrente // Entity { public function depositar(Dinheiro $valor) { $this->setSaldo($this->getSaldo() + $valor); } } class Dinheiro // ValueObject { const BRL = 1; const AUD = 2; protected $tipoMoeda; public function getTipoMoeda() { ... } public function converte($tipoMoeda) { return $this->getValor() * $tipoMoeda; } public function __add($dinheiro) { return $this->getValor() + $dinheiro->convert($this->getTipoMoeda()); } } $conta = new ContaCorrente(/* id */); $valor = new Dinheiro(100); $conta->depositar($valor);
  • 19. Operadores disponíveis +, -, *, /, %, <<, >>, ., |, &, ^, ~, !, ++, --, +=, -=, *=, /=, %=, <<=, >>=, .=, |=, &=, ^=, ~=, ==, !=, ===, !==, <, <=
  • 20. Nada é perfeito... • Só funciona no 5.2
  • 22. Injeção de Dependência <?php // Zend Framework: A setter injection example $transport = new Zend_Mail_Transport_Smtp('smtp.gmail.com', array( 'auth' => 'login', 'username' => 'foo', 'password' => 'bar', 'ssl' => 'ssl', 'port' => 465, ));   $mailer = new Zend_Mail(); $mailer->setDefaultTransport($transport);
  • 23. Container de Injeção de Dependência
  • 24. Symfony <?xml version="1.0" ?>   <container xmlns="http://symfony-project.org/2.0/container"> <parameters> <parameter key="mailer.username">foo</parameter> <parameter key="mailer.password">bar</parameter> <parameter key="mailer.class">Zend_Mail</parameter> </parameters> <services> <service id="mail.transport" class="Zend_Mail_Transport_Smtp" shared="false"> <argument>smtp.gmail.com</argument> <argument type="collection"> <argument key="auth">login</argument> <argument key="username">%mailer.username%</argument> <argument key="password">%mailer.password%</argument> <argument key="ssl">ssl</argument> <argument key="port">465</argument> </argument> </service> <service id="mailer" class="%mailer.class%"> <call method="setDefaultTransport"> <argument type="service" id="mail.transport" /> </call> </service> </services> </container>
  • 25. Symfony <?php require_once '/PATH/TO/sfServiceContainerAutoloader.php'; sfServiceContainerAutoloader::register();   $sc = new sfServiceContainerBuilder();   $loader = new sfServiceContainerLoaderFileXml($sc); $loader->load('/somewhere/container.xml'); $sc->mailer;
  • 27. Você não chama, você é chamado!
  • 28. <?php class UserService { protected $serviceLocator; public function __construct($serviceLocator) { $this->serviceLocator = $serviceLocator; } public function saveUser(array $data) { $validator = $this->serviceLocator->getService('validator'); try { // Valida os dados $data = $validator->validate($data); $repository = new UserRepository(); $user = new User(); // Persiste os dados return $repository->save($data, $user); } catch (Exception $e) { $this->serviceLocator->getService('logger')->log($e); } return null; } }
  • 29. <?php class UserService { /** * @Dependency(validator) */ protected $validator; /** * @Dependency(logger) */ protected $logger; public function saveUser(array $data) { try { // Valida os dados $data = $this->validator->validate($data); $repository = new UserRepository(); $user = new User(); // Persiste os dados return $repository->save($data, $user); } catch (Exception $e) { $this->logger->log($e); } return null; } }
  • 31. <?php class Container { protected static $data = array('mailer' => 'mailer'); public static function get($key) { if (!self::exists($key)) throw new InvalidArgumentException('Invalid key!'); return self::$data[$key]; } public static function exists($key) { return array_key_exists($key, self::$data); } public static function notify($object) { $injector = new Injector($object, self::$data); return $injector->inject(); } }
  • 32. <?php class Watcher { protected $dir; public function __construct($dir) { $this->dir = $dir; } public function watch() { foreach (glob($this->dir . DIRECTORY_SEPARATOR . '*.php') as $class) { require $class; runkit_method_add(pathinfo($class, PATHINFO_FILENAME), '__construct', '', 'Container::notify($this);'); } } }
  • 33. <?php class Injector { protected $object; public function __construct($object) { $this->object = $object; } public function inject() { $reflection = new ReflectionObject($this->object); $prop = $reflection->getProperty('mailer'); if (!Container::exists('mailer')) return null; $prop->setAccessible(true); $prop->setValue($this->object, Container::get('mailer')); return true; } }
  • 34. <?php class Controller { protected $mailer; public function get() { var_dump($this->mailer); } }
  • 35. <?php $w = new Watcher('path/to/my/folder'); $w->watch(); $c = new Controller(); $c->get(); // string(6) "mailer"
  • 36. <?php class UserService { /** * @Dependency(validator) */ protected $validator; /** * @Dependency(logger) */ protected $logger; public function saveUser(array $data) { try { // Valida os dados $data = $this->validator->validate($data); $repository = new UserRepository(); $user = new User(); // Persiste os dados return $repository->save($data, $user); } catch (Exception $e) { $this->logger->log($e); } return null; } }
  • 37. <?php class AnnotationParser { protected $class; public function __construct(ReflectionClass $class) { $this->class = $class; } public function parseDependencies() { $dependencies = array(); foreach ($this->class->getProperties() as $prop) if ($this->matchDependency($prop, $matches)) $dependencies[] = array('property' => $prop, 'dependency' => $matches[1]); return $dependencies; } protected function matchDependency($prop, &$matches) { return (bool) preg_match('/@dependencys*(([a-zA-Z0-9_ ]*))/i', $prop->getDocComment(), $matches); } }
  • 38. <?php class Injector { protected $object; public function __construct($object) { $this->object = $object; } public function inject() { $annotationParser = new AnnotationParser(new ReflectionObject($this->object)); $props = $annotationParser->parseDependencies(); foreach ($props as $prop) { if (Container::exists($prop['dependency'])) { $prop['property']->setAccessible(true); $prop['property']->setValue($this->object, Container::get($prop['dependency'])); } } } }
  • 39. <?php class Container { protected static $data = array(); public static function set($key, $value) { self::$data[$key] = $value; } public static function get($key) { if (!self::exists($key)) throw new InvalidArgumentException('Invalid key!'); return self::$data[$key]; } public static function exists($key) { return array_key_exists($key, self::$data); } public static function notify($object) { $injector = new Injector($object, self::$data); return $injector->inject(); } }
  • 40. <?php class Validator { public function validate() { // ... } } class Logger { public function log() { // ... } } $w = new Watcher('path/to/my/folder'); $w->watch(); Container::set('validator', new Validator()); Container::set('logger', new Logger()); $c = new UserService(); $c->saveUser(array());
  • 41. Melhorias • Verificar existência de __construct • Pegar os parametros do __construct • Observar classes dentro de namespaces(recursivo)
  • 42. Recursos • function_add, *_remove, *_copy, *_redefine, *_rename • method_add, *_remove, *_copy, *_redefine, *_rename
  • 43. E agora??? • Tokenizer • Mutagenesis (https://github.com/ padraic/mutagenesis)
  • 46. <?php $id = $_GET['id']; // int $valor = $_GET['valor']; // float
  • 47. <?php $id = (int) $_GET['id']; // int $valor = (float) $_GET['valor']; // float
  • 48. <?php $id = $_GET['id']; // int $valor = $_GET['valor']; // float function processa($id, $valor) { // ... }
  • 49. <?php $id = $_GET['id']; // int $valor = $_GET['valor']; // float function processa($id, $valor) { $id = (int) $id; $valor = (float) $valor; echo $id, $valor; } processa($id, $valor);
  • 50. <?php $id = $_GET['id']; // int $valor = $_GET['valor']; // float function processa($id, $valor) { if (!is_int($id)) throw new InvalidArgumentException('Tipo inválido'); if (!is_float($valor)) throw new InvalidArgumentException('Tipo inválido'); echo $id, $valor; } processa($id, $valor);
  • 51. <?php $id = $_GET['id']; // int $valor = $_GET['valor']; // float function processa(Integer $id, Float $valor) { echo $id, $valor; } processa(new Integer($id), new Float($valor));
  • 52. sudo pecl install spl_types
  • 53. <?php $id = $_GET['id']; // int $valor = $_GET['valor']; // float function processa(SplInt $id, SplFloat $valor) { echo $id, $valor; } processa(new SplInt($id), new SplFloat($valor));
  • 54. <?php $int = new SplInt('10'); // ?
  • 55. <?php $int = new SplInt('10'); // UnexpectedValueException: Value not an integer
  • 56. <?php $int = new SplInt('10', false); // Ok
  • 57. <?php $int = new SplInt('10'); if (!is_int('10')) throw new InvalidArgumentException('Tipo inválido'); $int1 = new SplInt('10', false); $int2 = '10'; if (!is_int($int2)) $int2 = (int) $int2;
  • 58. <?php $int = new SplInt(10); $int = 10; $int1 = new SplInt('10', false); $int1 = '10';
  • 59. <?php $int = new SplInt(10); $float = new SplFloat(10.7); echo $float + $int; echo $float - $int; echo $float / $int; echo $float * $int;
  • 60. <?php $id = $_GET['id']; // int $valor = $_GET['valor']; // float function processa(SplInt $id, SplFloat $valor) { echo $id, $valor; } processa($id, $valor); // Catchable fatal error: Argument 1 passed to processa() must be an instance of SplInt // Catchable fatal error: Argument 2 passed to processa() must be an instance of SplFloat
  • 61. <?php class Month extends SplEnum { const __default = self::January; const January = 1; const February = 2; const March = 3; const April = 4; const May = 5; const June = 6; const July = 7; const August = 8; const September = 9; const October = 10; const November = 11; const December = 12; }
  • 62. <?php class Month extends SplEnum { const __default = self::January; const January = 1; const February = 2; const March = 3; const April = 4; const May = 5; const June = 6; const July = 7; const August = 8; const September = 9; const October = 10; const November = 11; const December = 12; } function getMonth(Month $month) { echo $month; } getMonth(new Month(Month::October));
  • 63. <?php class Month extends SplEnum { const __default = self::January; const January = 1; const February = 2; const March = 3; const April = 4; const May = 5; const June = 6; const July = 7; const August = 8; const September = 9; const October = 10; const November = 11; const December = 12; } function getMonth(Month $month) { echo $month; } getMonth(new Month(13)); // UnexpectedValueException: Value not a const in enum Month
  • 64. <?php class Month extends SplEnum { const __default = self::January; const January = 1; const February = 2; const March = 3; const April = 4; const May = 5; const June = 6; const July = 7; const August = 8; const September = 9; const October = 10; const November = 11; const December = 12; } $month = new Month(); var_dump($month->getConstList());
  • 67. <?php function testInt(integer $value) { var_dump($value); } testInt(1);
  • 69. https://svn.php.net/repository/php/php-src/ branches/WITH_SCALAR_TYPES/
  • 71. <?php function testInt(integer $value) { var_dump($value); } testInt('PHPubSP'); // Catchable fatal error: Argument 1 passed to testInt() must be of the type integer, string given
  • 72. <?php function testNumeric(numeric $value) { var_dump($value); } testNumeric('10');
  • 73. <?php function testCast((int) $value) { var_dump($value); } testCast('10');
  • 74. <?php function testScalar(scalar $value) { var_dump($value); } testScalar('10');
  • 75. <?php function testBool(bool $value) { // ... } function testString(string $value) { // ... } function testFloat(float $value) { // ... }