This new Feature enables Annotation based Dependency Injection:
<?php
//dependency to inject
class dep {}
class a {
/**
* @inject
* @var dep
*/
protected $foo;
}
class b extends a {
/**
* @inject
* @var dep
*/
protected $bar;
public function __construct() {
echo "CONSTRUCTOR CALLED\n";
}
}
$ref = new ReflectionClass('b');
$inst = $ref->newInstanceWithoutConstructor();
$list = $ref->getProperties();
foreach($list as $prop){
/* @var $prop ReflectionProperty */
$prop->getDocComment(); //grep for @inject and the @vars class name
$prop->setAccessible(true);
$prop->setValue($inst, new dep());
}
if($const = $ref->getConstructor()) {
$constName = $const->getName();
$inst->{$constName}(); //use call_user_func_array($function, $param_arr); for arguments
}
print_r($inst);
print_r($inst->foo); //property still not accessable
The Output:
CONSTRUCTOR CALLED
b Object
(
[bar:protected] => dep Object
(
)
[foo:protected] => dep Object
(
)
)
PHP Fatal error: Cannot access protected property b::$foo in diTest.php on line 42
ReflectionClass::newInstanceWithoutConstructor
(PHP >= 5.4.0)
ReflectionClass::newInstanceWithoutConstructor — Crea una nueva clase sin invocar al constructor
Descripción
public object ReflectionClass::newInstanceWithoutConstructor
( void
)
Crea una nueva instancia de la clase sin llegar a invocar al constructor.
Parámetros
Valores devueltos
Errores/Excepciones
Lanza ReflectionException si se tratara de una clase interna que no se pudiera instanciar sin invocar al constructor.
Ver también
- ReflectionClass::newInstance() - Crea una nueva instancia de clase a partir de la lista de parámetros dados
- ReflectionClass::newInstanceArgs() - Crea una nueva instancia de clase a partir del array de argumentos dados
me [ata] thomas-lauria.de
28-Apr-2012 06:51
oliver at ananit dot de
24-Nov-2011 03:57
If this method is not available in your version of PHP you can use a trick to create an instance without calling the constructor.
Use reflection to get the properties and default values of the class, and create a fake "serialized" string.
<?php
function createInstanceWithoutConstructor($class){
$reflector = new ReflectionClass($class);
$properties = $reflector->getProperties();
$defaults = $reflector->getDefaultProperties();
$serealized = "O:" . strlen($class) . ":\"$class\":".count($properties) .':{';
foreach ($properties as $property){
$name = $property->getName();
if($property->isProtected()){
$name = chr(0) . '*' .chr(0) .$name;
} elseif($property->isPrivate()){
$name = chr(0) . $class. chr(0).$name;
}
$serealized .= serialize($name);
if(array_key_exists($property->getName(),$defaults) ){
$serealized .= serialize($defaults[$property->getName()]);
} else {
$serealized .= serialize(null);
}
}
$serealized .="}";
return unserialize($serealized);
}
?>
Example:
<?php
class foo
{
public $a = 10;
protected $b = 2;
private $c = "default";
protected $d;
public function __construct(){
$this->a = null;
$this->b = null;
$this->c = "constructed";
$this->d = 42;
}
}
var_dump(createInstanceWithoutConstructor('foo'));
?>
Output:
object(foo)#6 (4) {
["a"]=>
int(10)
["b":protected]=>
int(2)
["c":"foo":private]=>
string(7) "default"
["d":protected]=>
NULL
}
I hope this can help someone.
Oliver Anan
alejosimon at gmail
06-Sep-2011 06:41
A good first use for this new method.
It implements a transparent parser constructor argument to achieve 99% reusable component.
<?php
use ReflectionClass ;
trait TSingleton
{
/**
* Constructor.
*/
protected function __construct() {}
/**
* Drop clone singleton objects.
*/
protected function __clone() {}
/**
* Gets only one instance.
*
* @params Optional multiple values as arguments for the constructor.
* @return Object instance from called class.
*/
public static function getInstance()
{
static $instance = null ;
if ( ! $instance )
{
$ref = new ReflectionClass( get_called_class() ) ;
$ctor = $ref->getConstructor() ;
// Thanks PHP 5.4
$self = $ref->newInstanceWithoutConstructor() ;
// The magic.
$ctor->setAccessible( true ) ;
$instance = $ctor->invokeArgs( $self, func_get_args() ) ;
}
return $instance ;
}
}
?>
