如何区分 PHP 属性 是否未定义或设置为 NULL
How to distinguish if a PHP property is undefined or set to NULL
所以我正面临这个问题。我有一个 class 表示我的数据库中的一条记录(本例中为用户)。 class 的属性与数据库 table 的列一样多。为简单起见,我的示例中只有三个:
$id
- 用户 ID(对于注册用户必须设置为正整数,对于尚未保存在数据库中的用户对象可能设置为 0)
$name
- 用户名(必须为每个用户设置,但在从数据库加载之前可能未定义)
$email
- 用户的电子邮件地址(如果用户未提交电子邮件地址,则可能为 NULL)
我的(简体)class 看起来像这样:
<?php
class User
{
private $id;
private $name;
private $email;
public function __construct(int $id = 0)
{
if (!empty($id)){ $this->id = $id; }
//If $id === 0, it means that the record represented by this instance isn't saved in the database yet and the property will be filled after calling the save() method
}
public function initialize(string $name = '', $email = '')
{
//If any of the parameters isn't specified, prevent overwriting curent values
if ($name === ''){ $name = $this->name; }
if ($email === ''){ $email = $this->email; }
$this->name = $name;
$this->email = $email;
}
public function load()
{
if (!empty($this->id))
{
//Load name and e-mail from the database and save them into properties
}
}
public function save()
{
if (!empty($this->id))
{
//Update existing user record in the database
}
else
{
//Insert a new record into the table and set $this->id to the ID of the last inserted row
}
}
public function isFullyLoaded()
{
$properties = get_object_vars($this);
foreach ($properties as $property)
{
if (!isset($property)){ return false; } //TODO - REPLACE isset() WITH SOMETHING ELSE
}
return true;
}
//Getters like getName() and getId() would come here
}
现在终于解决了我的问题。如您所见,可以在未设置所有属性的情况下创建此 class 的实例。如果我想 e,那将是一个问题。 G。在名称未知时调用 getName()
(它不是通过 initialize()
方法设置的,也没有调用 load())。为此,我编写了方法 isFullyLoaded()
检查所有属性是否已知,如果不知道,则应调用 load()
(从调用 isFullyLoaded()
的方法开始)。问题的核心是,一些变量可能是空字符串 ('')、零值 (0) 甚至 null(如 $email
属性)。所以我想区分具有任何值集(包括 null)和那些从未被赋予任何价值的人。
具体示例:我要实现这段代码:
$user1 = new User(1);
$user1->initialize('Vic', 'nerd.from.klamath@fallout2.com');
var_dump($user1->isFullyLoaded());
$user2 = new User(2);
$user2->initialize('Cassidy', null); //No e-mail was specified during the registration
var_dump($user2->isFullyLoaded());
$user3 = new User(3);
$user3->initialize('Myron'); //E-mail isn't known yet, but might be saved in the database
var_dump($user3->isFullyLoaded());
输出这个:
bool(true)
bool(true)
bool(false)
TL:DR 如何区分PHP中未定义的变量和已赋值为NULL的变量?
使用property_exists()
:
<?php
error_reporting(E_ALL);
// oop:
class A {
public $null_var = null;
}
$a = new A;
if(property_exists($a, 'null_var')) {
echo "null_var property exists\n";
}
if(property_exists($a, 'unset_var')) {
echo "unset_var property exists\n";
}
// procedural:
$null_var = null;
if(array_key_exists('null_var', $GLOBALS)) {
echo "null_var variable exists\n";
}
if(array_key_exists('unset_var', $GLOBALS)) {
echo "unset_var variable exists\n";
}
// output:
// null_var property exists
// null_var variable exists
PHP 没有像 javascript 那样未定义的值。但它不是严格类型的,所以如果你没有找到更好的解决方案,这里有一个自定义类型 UNDEFINED
<?php
class UNDEFINED { }
class Test {
var $a;
function __construct( $a='' ) {
$this->a = new UNDEFINED();
if( $a !== '' ) {
$this->a = $a;
}
}
function isDefined() {
$result =true;
if(gettype($this->a) === 'object'){
if(get_class($this->a) === 'UNDEFINED') {
$result=false;
}
}
echo gettype($this->a) . get_class($this->a);
return $result;
}
}
$test= new Test();
$test->isDefined();
这是一个可能更好的版本,它使用 instanceof 而不是 get_call 和 getType
<?php
class UNDEFINED { }
class Test {
var $id;
var $a;
var $b;
function __construct( $id) {
$this->id = $id;
$this->a = new UNDEFINED();
$this->b = new UNDEFINED();
}
function init( $a = '' , $b = '') {
$this->a = $this->setValue($a,$this->a);
$this->b = $this->setValue($b,$this->b);
}
function setValue($a,$default) {
return $a === '' ? $default : $a;
}
function isUndefined($a) {
return $a instanceof UNDEFINED;
}
public function isFullyLoaded()
{
$result = true;
$properties = get_object_vars($this);
print_r($properties);
foreach ($properties as $property){
$result = $result && !$this->isUndefined($property);
if ( !$result) break;
}
return $result;
}
function printStatus() {
if($this->isFullyLoaded() ) {
echo 'Loaded!';
} else {
echo 'Not loaded';
}
}
}
$test= new Test(1);
$test->printStatus();
$test->init('hello');
$test->printStatus();
$test->init('', null);
$test->printStatus();
这里是另一种引入自定义未定义class(作为单例)的方法。此外,请确保键入您的 class 属性:
class Undefined
{
private static Undefined $instance;
protected function __constructor()
{
}
protected function __clone()
{
}
public function __wakeup()
{
throw new Exception("Not allowed for a singleton.");
}
static function getInstance(): Undefined
{
return self::$instance ?? (self::$instance = new static());
}
}
class Person
{
private int $age;
public function getAge(): int|Undefined
{
return $this->age ?? Undefined::getInstance();
}
}
$person = new Person();
if ($person->getAge() instanceof Undefined) {
// do something
}
但是使用单例模式有一个缺点,因为您应用中的所有 undefined 对象都将严格相等。否则,每个返回 undefined 值的 get 操作都会产生副作用,即另一块已分配的 RAM。
所以我正面临这个问题。我有一个 class 表示我的数据库中的一条记录(本例中为用户)。 class 的属性与数据库 table 的列一样多。为简单起见,我的示例中只有三个:
$id
- 用户 ID(对于注册用户必须设置为正整数,对于尚未保存在数据库中的用户对象可能设置为 0)$name
- 用户名(必须为每个用户设置,但在从数据库加载之前可能未定义)$email
- 用户的电子邮件地址(如果用户未提交电子邮件地址,则可能为 NULL)
我的(简体)class 看起来像这样:
<?php
class User
{
private $id;
private $name;
private $email;
public function __construct(int $id = 0)
{
if (!empty($id)){ $this->id = $id; }
//If $id === 0, it means that the record represented by this instance isn't saved in the database yet and the property will be filled after calling the save() method
}
public function initialize(string $name = '', $email = '')
{
//If any of the parameters isn't specified, prevent overwriting curent values
if ($name === ''){ $name = $this->name; }
if ($email === ''){ $email = $this->email; }
$this->name = $name;
$this->email = $email;
}
public function load()
{
if (!empty($this->id))
{
//Load name and e-mail from the database and save them into properties
}
}
public function save()
{
if (!empty($this->id))
{
//Update existing user record in the database
}
else
{
//Insert a new record into the table and set $this->id to the ID of the last inserted row
}
}
public function isFullyLoaded()
{
$properties = get_object_vars($this);
foreach ($properties as $property)
{
if (!isset($property)){ return false; } //TODO - REPLACE isset() WITH SOMETHING ELSE
}
return true;
}
//Getters like getName() and getId() would come here
}
现在终于解决了我的问题。如您所见,可以在未设置所有属性的情况下创建此 class 的实例。如果我想 e,那将是一个问题。 G。在名称未知时调用 getName()
(它不是通过 initialize()
方法设置的,也没有调用 load())。为此,我编写了方法 isFullyLoaded()
检查所有属性是否已知,如果不知道,则应调用 load()
(从调用 isFullyLoaded()
的方法开始)。问题的核心是,一些变量可能是空字符串 ('')、零值 (0) 甚至 null(如 $email
属性)。所以我想区分具有任何值集(包括 null)和那些从未被赋予任何价值的人。
具体示例:我要实现这段代码:
$user1 = new User(1);
$user1->initialize('Vic', 'nerd.from.klamath@fallout2.com');
var_dump($user1->isFullyLoaded());
$user2 = new User(2);
$user2->initialize('Cassidy', null); //No e-mail was specified during the registration
var_dump($user2->isFullyLoaded());
$user3 = new User(3);
$user3->initialize('Myron'); //E-mail isn't known yet, but might be saved in the database
var_dump($user3->isFullyLoaded());
输出这个:
bool(true)
bool(true)
bool(false)
TL:DR 如何区分PHP中未定义的变量和已赋值为NULL的变量?
使用property_exists()
:
<?php
error_reporting(E_ALL);
// oop:
class A {
public $null_var = null;
}
$a = new A;
if(property_exists($a, 'null_var')) {
echo "null_var property exists\n";
}
if(property_exists($a, 'unset_var')) {
echo "unset_var property exists\n";
}
// procedural:
$null_var = null;
if(array_key_exists('null_var', $GLOBALS)) {
echo "null_var variable exists\n";
}
if(array_key_exists('unset_var', $GLOBALS)) {
echo "unset_var variable exists\n";
}
// output:
// null_var property exists
// null_var variable exists
PHP 没有像 javascript 那样未定义的值。但它不是严格类型的,所以如果你没有找到更好的解决方案,这里有一个自定义类型 UNDEFINED
<?php
class UNDEFINED { }
class Test {
var $a;
function __construct( $a='' ) {
$this->a = new UNDEFINED();
if( $a !== '' ) {
$this->a = $a;
}
}
function isDefined() {
$result =true;
if(gettype($this->a) === 'object'){
if(get_class($this->a) === 'UNDEFINED') {
$result=false;
}
}
echo gettype($this->a) . get_class($this->a);
return $result;
}
}
$test= new Test();
$test->isDefined();
这是一个可能更好的版本,它使用 instanceof 而不是 get_call 和 getType
<?php
class UNDEFINED { }
class Test {
var $id;
var $a;
var $b;
function __construct( $id) {
$this->id = $id;
$this->a = new UNDEFINED();
$this->b = new UNDEFINED();
}
function init( $a = '' , $b = '') {
$this->a = $this->setValue($a,$this->a);
$this->b = $this->setValue($b,$this->b);
}
function setValue($a,$default) {
return $a === '' ? $default : $a;
}
function isUndefined($a) {
return $a instanceof UNDEFINED;
}
public function isFullyLoaded()
{
$result = true;
$properties = get_object_vars($this);
print_r($properties);
foreach ($properties as $property){
$result = $result && !$this->isUndefined($property);
if ( !$result) break;
}
return $result;
}
function printStatus() {
if($this->isFullyLoaded() ) {
echo 'Loaded!';
} else {
echo 'Not loaded';
}
}
}
$test= new Test(1);
$test->printStatus();
$test->init('hello');
$test->printStatus();
$test->init('', null);
$test->printStatus();
这里是另一种引入自定义未定义class(作为单例)的方法。此外,请确保键入您的 class 属性:
class Undefined
{
private static Undefined $instance;
protected function __constructor()
{
}
protected function __clone()
{
}
public function __wakeup()
{
throw new Exception("Not allowed for a singleton.");
}
static function getInstance(): Undefined
{
return self::$instance ?? (self::$instance = new static());
}
}
class Person
{
private int $age;
public function getAge(): int|Undefined
{
return $this->age ?? Undefined::getInstance();
}
}
$person = new Person();
if ($person->getAge() instanceof Undefined) {
// do something
}
但是使用单例模式有一个缺点,因为您应用中的所有 undefined 对象都将严格相等。否则,每个返回 undefined 值的 get 操作都会产生副作用,即另一块已分配的 RAM。