<?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);
<?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));
<?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;
}
}
<?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
$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)
<?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
$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());
<?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