ReflectionClass
在线手册:中文  英文

ReflectionClass::newInstanceWithoutConstructor

(PHP >= 5.4.0)

ReflectionClass::newInstanceWithoutConstructor创建一个新的类实例而不调用它的构造函数

说明

public object ReflectionClass::newInstanceWithoutConstructor ( void )

创建一个新的类的实例而不调用它的构造函数。

参数

返回值

错误/异常

如果这个类是一个不能不调用构造函数来实例化的内置类,将导致一个 ReflectionException

参见


ReflectionClass
在线手册:中文  英文

用户评论:

tom at r dot je (2013-06-11 09:53:00)

It should be made clear that from an OOP theory perspective the use of this method is very bad practice in the same manner as goto, eval and singletons. If you find a need to use it in production code you're almost certainly doing something wrong somewhere. It may occasionally be useful for debugging, but even then hints at poor initial code.
The problem? It breaks encapsulation. An object can exist in the application but may not be able to fulfill its responsibility because it's missing dependencies. The use of this method makes it possible for an incomplete object to exist in the system; the object can exist in a state that its author never intended. This is bad because it will cause unexpected things to happen! A fundamental principle in OOP is that objects are in complete control of their state, the use of this method prevents that guarantee.
n.b. The annotation based "dependency injection" listed below is not a solution or valid use-case for this either because it breaks encapsulation (Among other things!) and the class being constructed needs to know of the container by providing annotations.

me [ata] thomas-lauria.de (2012-04-28 06:51:07)

This new Feature enables Annotation based Dependency Injection:
<?php 

//dependency to inject
class dep {}

class 
{
  
/**
   * @inject
   * @var dep
   */
  
protected $foo;
}

class 
extends {
  
/**
   * @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

oliver at ananit dot de (2011-11-24 15:57:35)

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->null;
        
$this->null;
        
$this->"constructed";
        
$this->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 (2011-09-06 06:41:25)

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 ReflectionClassget_called_class() ) ;
            
$ctor $ref->getConstructor() ;

            
// Thanks PHP 5.4
            
$self $ref->newInstanceWithoutConstructor() ;

            
// The magic.
            
$ctor->setAccessibletrue ) ;
            
$instance $ctor->invokeArgs$selffunc_get_args() ) ;
        }

        return 
$instance ;
    }
}

?>

易百教程