加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

PHP – 使用静态属性序列化类

发布时间:2020-12-13 21:46:57 所属栏目:PHP教程 来源:网络整理
导读:当用户登录我的站点时,我创建了一个User类的实例,获取一些与用户相关的数据并将该对象存储在SESSION中. 我从数据库中获取的一些数据应该在整个会话期间保持不变,并且我希望可以从其他对象访问数据.当使用另一个对象中的值时,我更喜欢将User :: $static_value
当用户登录我的站点时,我创建了一个User类的实例,获取一些与用户相关的数据并将该对象存储在SESSION中.

我从数据库中获取的一些数据应该在整个会话期间保持不变,并且我希望可以从其他对象访问数据.当使用另一个对象中的值时,我更喜欢将User :: $static_value_in_class用于$_SESSION [‘static_value_in_session’],但我愿意接受说服.

问题是,当我将User实例序列化为SESSION,然后加载不同的页面时,不会记住这些值.

类定义:

class User {
    public $name;
    public static $allowed_actions;
    public function __construct($username,$password) {
        // Validate credentials,etc.
        self::$allowed_actions = get_allowed_actions_for_this_user($this);
    }   
}
class Blog {
    public static function write($text) {
        if (in_array(USER_MAY_WRITE_BLOG,User::$allowed_actions)) {
            // Write blog entry
        }
    }
}

login.php中:

$user = new User($_POST['username'],$_POST['password']);
if (successful_login($user)) {
    $_SESSION['user'] = $user;
    header('Location: index.php');
}

index.php文件:

if (!isset($_SESSION['user'])) {
    header('Location: login.php');
}
Blog::write("I'm in index.php! Hooray!")
// Won't work,because Blog requires User::$allowed_actions

我应该实现Serializable并编写我自己的serialize()和unserialize()版本来包含静态数据吗?

我应该咬我的嘴唇并从Blog类中访问$_SESSION变量吗?

我是否需要将有效的User实例发送到Blog write()方法?

或许互联网有更好的想法……

编辑:编写我的真实用例(不是完整的代码,但足以获得要点).

我的网站使用共享预算帐户处理用户组.
用户可以将集团资金投入到集团同意的某些事情上,并通过创建Transaction类的实例并将其发送到Bank类进行数据库存储来报告事务.

银行类:

class Bank {
   // Group-agreed reasons to spend money
   public static $valid_transaction_reasons;
   public function __construct(User $user) {
      Bank::$valid_transaction_reasons = load_reasons_for_this_group($user->bank_id);
   }
}

用户类:

class User {
   public $bank_id;
   public function __construct($username,$password) {
      $query = "SELECT bank_id FROM users WHERE username=$username AND password=$password";
      $result = mysql_fetch_array(mysql_query($query));
      $this->bank_id = $result['bank_id'];
   }
}

交易类:

class Transaction {
   public function __construct($reason,$amount) {
      if (!in_array($reason,Bank::$valid_transaction_reasons)) {
         // Error! Users can't spend money on this,the group doesn't cover it
      }
      else {
         // Build a Transaction object
      }
   }
}

实际代码(login.php或其他):

$user = new User($_GET['uname'],$_GET['pword']);
$_SESSION['bank'] = new Bank($user);

// Some shit happens,user navigates to submit_transaction.php

$trans = new Transaction(REASON_BEER,5.65);
// Error! Bank::$valid_transaction_reasons is empty!

解决方法

正如我在评论中提到的,这更像是一个软件设计问题,而不是如何用PHP实现这一目标的问题.

静态属性不是对象状态的一部分,因此不会使用它进行序列化.

我将举一个简短的例子来说明如何解决相关问题.想象一下,您有以下消息类,它具有静态$id属性,以确保所有实例都具有唯一ID:

class Message {

    public static $id;

    public $instanceId;

    public $text;

    /**
     *
     */
    public function __construct($text) {
        // the id will incremented in a static var
        if(!self::$id) {
            self::$id = 1;
        } else {
            self::$id++;
        }

        // make a copy at current state
        $this->instanceId = self::$id; 
        $this->text = $text;
    }
}

序列化/反序列化代码:

$m1 = new Message('foo');
printf('created message id: %s text: %s%s',$m1->instanceId,$m1->text,PHP_EOL);
$m2 = new Message('bar');
printf('created message id: %s text: %s%s',$m2->instanceId,$m2->text,PHP_EOL);

$messages = array($m1,$m2);

$ser1 = serialize($m1);
$ser2 = serialize($m2);

$m1 = unserialize($ser1);
printf('unserialized message id: %s text: %s%s',PHP_EOL);
$m2 = unserialize($ser2);
printf('unserialized message id: %s text: %s%s',PHP_EOL);

为了确保id在多个脚本运行中是唯一的,需要进一步的工作.您必须确保在创建任何对象之前使用上次脚本运行的值初始化Message :: $id.当涉及到Web服务器上的并行PHP请求时,这将获得额外的连接.

它只是我知道的最简单静态属性的一个例子:实例计数器.在这种情况下,我会这样做.但我希望您看到,在没有副作用的情况下序列化/反序列化静态属性还需要进一步的工作.这取决于您的应用需求.

这个问题无法回答一般我倾向于说无论如何序列化静态成员毫无意义.但我很感激对此的评论.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读