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 — Crée une nouvelle instance de la classe sans invoquer le constructeur
Description
public object ReflectionClass::newInstanceWithoutConstructor
( void
)
Crée une nouvelle instance de la classe sans invoquer son constructeur.
Liste de paramètres
Valeurs de retour
Erreurs / Exceptions
A ReflectionException si la classe est une classe interne qui ne peut être instanciée sans invoquer son constructeur.
Voir aussi
- ReflectionClass::newInstance() - Créer une nouvelle instance de la classe en utilisant les arguments fournis
- ReflectionClass::newInstanceArgs() - Créer une nouvelle instance en utilisant les arguments fournis
me [ata] thomas-lauria.de ¶
1 year ago
alejosimon at gmail ¶
1 year ago
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 ;
}
}
?>
oliver at ananit dot de ¶
1 year ago
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
