Your SlideShare is downloading. ×
PHP ao Extremo
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Saving this for later?

Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime - even offline.

Text the download link to your phone

Standard text messaging rates apply

PHP ao Extremo

2,204
views

Published on

Published in: Technology, Art & Photos

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,204
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
10
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. 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. <?phpclass 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. <?phpclass 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. <?phpclass 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. <?phpclass 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. <?phpclass 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);
  • 10. Sobrecarga de operador
  • 11. sudo pecl install -f operator
  • 12. <?phpclass 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. <?phpinterface 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. <?phpclass 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. <?phpclass 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. <?phpclass 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));
  • 17. Exemplo do mundo real
  • 18. <?phpclass 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
  • 21. Injeção de Dependência
  • 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<?phprequire_once /PATH/TO/sfServiceContainerAutoloader.php;sfServiceContainerAutoloader::register(); $sc = new sfServiceContainerBuilder(); $loader = new sfServiceContainerLoaderFileXml($sc);$loader->load(/somewhere/container.xml);$sc->mailer;
  • 26. Inversão de Controle
  • 27. Você não chama, você é chamado!
  • 28. <?phpclass 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. <?phpclass 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; }}
  • 30. runkithttps://github.com/zenovich/runkit/
  • 31. <?phpclass 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. <?phpclass 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. <?phpclass 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. <?phpclass 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. <?phpclass 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. <?phpclass 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. <?phpclass 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. <?phpclass 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. <?phpclass 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)
  • 44. Variáveis Tipadas
  • 45. PHP tem tipo???
  • 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]; // floatfunction processa($id, $valor){ // ...}
  • 49. <?php$id = $_GET[id]; // int$valor = $_GET[valor]; // floatfunction processa($id, $valor){ $id = (int) $id; $valor = (float) $valor; echo $id, $valor;}processa($id, $valor);
  • 50. <?php$id = $_GET[id]; // int$valor = $_GET[valor]; // floatfunction 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]; // floatfunction 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]; // floatfunction 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]; // floatfunction 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. <?phpclass 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. <?phpclass 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. <?phpclass 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. <?phpclass 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());
  • 65. Scalar Type Hinting
  • 66. <?phpfunction foo(array $value){ // ...}
  • 67. <?phpfunction testInt(integer $value){ var_dump($value);}testInt(1);
  • 68. http://svn.php.net/viewvc?view=revision&revision=299534
  • 69. https://svn.php.net/repository/php/php-src/ branches/WITH_SCALAR_TYPES/
  • 70. http://ilia.ws/archives/207-Type-Hinting- Conclusion.html
  • 71. <?phpfunction 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. <?phpfunction testNumeric(numeric $value){ var_dump($value);}testNumeric(10);
  • 73. <?phpfunction testCast((int) $value){ var_dump($value);}testCast(10);
  • 74. <?phpfunction testScalar(scalar $value){ var_dump($value);}testScalar(10);
  • 75. <?phpfunction testBool(bool $value){ // ...}function testString(string $value){ // ...}function testFloat(float $value){ // ...}
  • 76. Perguntas???