Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 函数无限调用自身?_Php_Loops_Constructor_Infinity - Fatal编程技术网

Php 函数无限调用自身?

Php 函数无限调用自身?,php,loops,constructor,infinity,Php,Loops,Constructor,Infinity,我在用PHP类做一个小实验,遇到了这个奇怪的问题 如果$instance为null,则该类旨在为其$instance属性分配一个自身实例,但这种旨在防止无限自我繁殖的机制似乎失败了,结果是: 致命错误:已达到最大函数嵌套级别“100”,正在中止 为什么会发生这种情况?__构造只创建类的一个新实例,该实例为空,因此具有空的$instance,因此再次创建实例,使循环变为无限循环 非常感谢当您使用'new'关键字创建对象时,它会调用构造函数。如果在构造函数中使用new self,它将再次调用构造

我在用PHP类做一个小实验,遇到了这个奇怪的问题

如果$instance为null,则该类旨在为其$instance属性分配一个自身实例,但这种旨在防止无限自我繁殖的机制似乎失败了,结果是:

致命错误:已达到最大函数嵌套级别“100”,正在中止


为什么会发生这种情况?__构造只创建类的一个新实例,该实例为空,因此具有空的$instance,因此再次创建实例,使循环变为无限循环


非常感谢

当您使用'new'关键字创建对象时,它会调用构造函数。如果在构造函数中使用
new self
,它将再次调用构造。导致无限循环的

当您使用
new
时,会自动创建一个新实例,因此您不必存储类似
$this->instance
的内容。变量
$this
是您的实例

需要记住的重要一点是,类的每个实例都有自己的变量
$instance
。所以它在整个过程中都是空的

现在,如果要创建单例,实际上必须将构造函数设置为私有:

private function __construct() {}
然后我们需要
instance
作为静态变量:

static private $instance;
没有人可以使用new关键字创建新对象。因此,我们需要提供一个静态函数来创建实例:

static function newInstance() {
    if ( self::instance == null ) {
        self::instance = new self;
    }
    return self::instance;
}
现在,您可以使用以下方法获得新实例:

$x = SeemsLikeInfinity::newInstance();

现在只有一个SeemsLikeInfinity对象,您可以始终使用
SeemsLikeInfinity::newInstance()
访问它,因为param$实例始终为空。每次在类内创建新对象时。如果您想要实现单例,您应该将_构造更改为private,并使用一个静态方法仅创建一个对象

 class SeemsLikeInfinity {

   private static $instance;

   private function __construct() {
       // some action;
   }
   public static function generate_singleton(){
     if ( self::$instance == null ) {
         self::$instance = new self;
     }
     return self::$instance
   }
}

$singleton = SeemsLikeInfinity::generate_singleton();
// here you have singleton and you cant create more tha one object

您必须使用静态变量而不是
$this
的原因是
$this
仅与当前对象相关-每次创建一个新的
对象时,您都在为该对象创建一个新的
$this
,因此当您实例化该类

那么,在构造函数中发生了什么:

if ( $this->instance == null ) {
  $this->instance = new self;
}
。。。是一个新的
$this->instance
(无赋值)是在构建对象时创建的,因此新对象是使用一个新的
$this->instance
构建的,同样没有值,因此新对象是使用一个新的
$this->instance
构建的,同样没有值。。。等等,永远

但是,静态变量是相对于类本身的。。。您可以根据需要多次实例化该类,并且创建的每个对象都将从该类继承静态变量的最后一组值

您试图做的是创建一个单例,这样您就不会直接调用构造函数,而是通过静态
getInstance()
方法实例化并访问该类:

// I've made this a "final" class - you can't really
// extend Singletons without getting into a mess
final class SeemsLikeInfinity {

  // this needs to be a static variable as it'll
  // be checked from the static self::getInstance() method
  // it should also be private as you'll never call it from
  // outside the class
  private static $instance;

  // the constructor function should also be private
  // as it'll ONLY ever be called from the 
  // self::getInstance() method
  private function __construct() {
    // ... do stuff here to instantiate your class
  }

  // Singletons can't be cloned
  public function __clone() {
    throw new Exception("ERROR : you can't clone Singletons", E_USER_ERROR);
  }

  // this is the main getInstance() method called
  // to actually instantiate or call the class
  public static function getInstance() {
    if(!self::$instance) { self::$instance = new self(); }
    return self::$instance;
  }
}

// now, to instantiate or access your class you'd use getInstance()
// you'll no longer have permanently reiterating classes and you
// should be golden
$looping = SeemsLikeInfinity::getInstance();

顺便说一句,我发现单例的最佳用途是构建会话管理包装器,因为会话本质上只有一个实例。

谢谢,它试图实现单例模式,但我可能弄错了。我知道$this代表当前对象的实例,我试图创建一个可以使用$object->instance->doSomething()访问的对象,而该实例包含$object的实例。这也会导致
致命错误:在不在对象上下文中时使用$this
我相信…@CD001谢谢,需要将变量设为静态。我可能错了-但这将导致一个
致命错误:当不在对象上下文中时使用$this
// I've made this a "final" class - you can't really
// extend Singletons without getting into a mess
final class SeemsLikeInfinity {

  // this needs to be a static variable as it'll
  // be checked from the static self::getInstance() method
  // it should also be private as you'll never call it from
  // outside the class
  private static $instance;

  // the constructor function should also be private
  // as it'll ONLY ever be called from the 
  // self::getInstance() method
  private function __construct() {
    // ... do stuff here to instantiate your class
  }

  // Singletons can't be cloned
  public function __clone() {
    throw new Exception("ERROR : you can't clone Singletons", E_USER_ERROR);
  }

  // this is the main getInstance() method called
  // to actually instantiate or call the class
  public static function getInstance() {
    if(!self::$instance) { self::$instance = new self(); }
    return self::$instance;
  }
}

// now, to instantiate or access your class you'd use getInstance()
// you'll no longer have permanently reiterating classes and you
// should be golden
$looping = SeemsLikeInfinity::getInstance();