【发布时间】:2013-01-29 07:55:39
【问题描述】:
当用户登录我的站点时,我创建了一个 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 类进行数据库存储来报告交易。
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);
}
}
User类:
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'];
}
}
Transaction类:
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!
【问题讨论】:
-
你确定
$allowedActions应该是static吗?它是用户状态的一部分,因此它不应该是静态的。 -
谢谢!你能举一个
__sleep()和__wakeup的例子,它们模仿了默认的serialize()和unserialized(),所以我知道要改变什么吗? -
@hek2mgl,
$allowed_actions就是一个例子。我贴的代码没什么用,只是说明问题,不是实际用例。 -
@Dori 我目前正准备写一个回答,说明您的软件中的设计错误。虽然你可以这样做 __sleep, __wakeup hack 它会导致不必要的副作用。那是因为静态变量的性质。静态属性不是对象状态的一部分,因此不会被序列化。
标签: php class serialization static