在我的php应用程序中,我正在聚合一些rss feed。我希望每24小时完成一次,我不想将其存储在数据库中。
我已经构建了一个单独的类来创建我的rss信息($ ActuList):
class ActualitesManager{
/**
* @var Singleton
* @access private
* @static
*/
private static $_instance = null;
public $ActuList = null;
private function __construct()
{
error_log("construct");
/* My stuff to create $ActuList */
}
public static function getInstance()
{
error_log("instance before : ". json_encode(self::$_instance) );
//if(is_null(self::$_instance)){
//if(!isset(self::$_instance)){
if (null === self::$_instance)
{
$object = __CLASS__;
self::$_instance = new $object;
}else
{
error_log("skip constructor");
}
error_log("instance after : ". json_encode(self::$_instance) );
return self::$_instance;
}
}
但每次调用getInstance()都会调用构造函数,因为它通常只应执行一次,然后给出已经实例化的$ _instance
我的调试总是给出:
instance before : null
instance after : {"ActuList":null}
并且永远不会显示"跳过构造函数"。
我错过了什么?
并以一般方式:这是正确的方法吗?解析rss feed非常耗时我不想为每个访问者完成这项任务:如何将结果保存在一个总是实例化的php类中?
感谢您的想法!
答案 0 :(得分:1)
我不希望每个访问者都完成这项任务:如何保持 导致一个总是实例化的php类
我专注于问题的那一部分,这让我觉得你很想念Singleton模式,对象和请求。
让我将您的样本更改为另一个可能您会更好理解的演示
<?php
class Singleton {
public $x = 1;
private static $_inst = null;
private function __construct() { }
/**
* @return Singleton
*/
public static function getInstace() {
if (self::$_inst == null) {
self::$_inst = new self();
}
return self::$_inst;
}
}
if (isset($_POST['y'])) {
Singleton::getInstace()->x++;
echo Singleton::getInstace()->x;
}
?>
<form action="" method="post">
<input type="submit" name="y"/>
</form>
我们有一个Singleton
类,其中包含可通过其实例访问的公共属性$x
。由于构造函数是私有的,因此只能从getInstance()
方法访问实例。 Singleton::getInstace()->x
将访问该媒体资源$x
。
在此代码中,如果单击该按钮,我们希望$x
属性增加1。
首次启动脚本时,该属性的值为1
。按下按钮后,它的值为1 + 1 = 2.现在,您希望2
的值以某种方式写入内存中,因此如果第三次单击该按钮,则应该显示3
。但是,遗憾的是,它不是真的,无论你多少次点击按钮,你总会收到2
的值,因为在第N次请求页面后,它会重新实现该类,并且它失去了所有的变化。
没有办法只在内存中保持所有客户端之间的持久性,因为它在使用后立即刷新。
我的建议是将更改保存到数据库中。
您还可以执行对象序列化,以便将更改保存到数据库中;
E.g:
serialize(Singleton::getInstance());
输出:
O:9:"Singleton":1:{s:1:"x";i:1;}
您可以将其存储在某个位置,即db col serialized
然后提取它并将其分配给变量:
$singleton = unserialize($row['serialized']);
执行更改:
$singleton->x++;
再次查看序列化更改:
O:9:"Singleton":1:{s:1:"x";i:2;}
将它们保存回来。
再次分配
$singleton = unserialize($row['serialized']);
$singleton->x++;
echo $singleton->x;
输出:3
这可能不是最有效的方法,但您不能依赖PHP对象来保存在内存中,如数据库。这就是数据库存在的原因,用户的所有信息等都没有存储在内存中保存的对象中。
如果要保存大量凭据,最好的设计决策是将每个字段保存到数据库而不是序列化对象,这样就可以将新实例设置为数据库中的值。这实际上是ORM的用途。将结果集绑定到对象。
两次考虑哪种方法可以满足您的需求,如果为每个用户重新安排一个对象/从数据库中提取成本很高,您应该考虑一种缓存方法,如果没有更改 - 没有数据库拉,从缓存中获取。答案 1 :(得分:0)
我想您正在尝试获取ActualitesManager的子类实例。
将getInstance的代码更改为以下内容:
foreach ( static::$instances as $instance )
{
if ( $instance instanceof static )
{
return $instance;
}
}
$instance = new static;
static::$instances[] = $instance;
return $instance;
我们将每个实例存储到一个数组中并循环它。在static中是指向扩展类的指针,它可以与 instanceof 一起使用。
使用“static”将使用当前的子类而不是父类。 “self”始终是指向包含此函数的类的指针。
由于您通过父级而不是类本身访问实例,因此您需要将其声明为“受保护”才能访问。
但是,你只有一个静态保护$ instance,因此它是一个数组。循环该数组并返回与当前类匹配的实例(如果找到)。否则,您创建它并返回新实例。
希望我能帮助解决您的问题:)