如何在 PHP 中永久转换 class 属性?
How to permanently typecast class properties in PHP?
我一直在阅读 the "Visibility" section of the PHP manual,在第一个评论中,有人提到:
OUTSIDE CODE can cast Item properties to any other PHP types (booleans, integers, floats, strings, arrays, and objects etc.) -- another huge mistake.
考虑这个例子:
class base {
public $foo = 1;
}
$first = new base();
(string)$first->foo; //I thought just this expression would typecast
var_dump($first->foo); //but I found it still is int
$first->foo = (string)$first->foo;
var_dump($first->foo); //ok so public props can be typecasted
难道只有受保护的私有属性我们不能从外部改变它们的类型吗?或者这也适用于 public 属性吗?
你正在做的是用一个新值覆盖 属性,它恰好是不同的类型。
类型转换不影响原始变量或值。它创建一个新的类型转换类型的值,如果你想保留你需要分配它。
你问的与对象属性可见性无关,但要理解类型转换是一种不影响其操作数的操作。
这对 $string
完全没有任何作用:
$string = "123";
(int)$string;
... 并且类型转换值丢失,因为我们没有分配操作的结果
如果满足以下几个条件,我们可以使用以下内容覆盖 $class::$someInteger
的值:
$class->someInteger = (string) 123;
- 属性 是 public。 (您显然不能从 class 外部直接访问
private
或 protected
属性。您可以通过使用反射或奇怪的东西来绕过这个 getter returns 对 属性 的 引用 ,但两者对于生产代码来说都是非常糟糕的想法)。
- 您没有使用 PHP 7.4 typed properties,并为其声明了类型。
问题的 "permanently" 部分特别容易被误导,因为在 PHP 中通常变量 没有类型 .
您可以将任何类型的值赋给任何变量。当它们确实有类型(PHP 7.4 类型属性)时,没有实用的方法来更改定义的类型(同样,可能 是一种使用反射的方法......但是我不会去那里)。
你的问题是基于对术语 typecasting 的含义的误解。 PHP Manual's page on type casting 和整个手册一般来说,是不充分的,不是自己的-包含学习 php 语言的规范参考。此外,它假定您了解其他编程语言,例如 C。
类型转换未定义为变量的数据类型转换;它是 expression 的数据类型转换——一般来说,在大多数编程语言中都是如此。 Wikipedea 定义如下:
In computer science, type conversion, type casting, type coercion, and type juggling are different ways of changing an expression from one data type to another.
官方手册使用了三个术语,即type juggling、type conversion和type casting.从第一段可以猜到,type juggling和type conversion是一回事。他们在第一段中说:
Note that this does not change the types of the operands themselves; the only change is in how the operands are evaluated...
应该清楚 type juggling 绝对不会改变变量的类型。从 php 手册看来,type juggling 和 type casting 是两个不同的概念。问题是,由于 PHP 手册从未定义这些术语,我们如何确定这两个术语是否相同以及它们的实际含义。在 Type Casting 文章中,手册说:
Type casting in PHP works much as it does in C:...
所以,答案是,我们可以安全地假设来自 C 语言的 类型转换 的定义适用于 PHP 语言。 C语言中type casting的定义和维基百科的定义一样,只是表达式的数据类型被转换。以下摘录自书 The C Programming Language by K&R, 2nd edition,第 2.7 节,第 45 页:
In the construction (type-name) expression
, the expression is converted to the named type... ...The precise meaning of cast is as if the expression were assigned to a variable of the specific type... ...we can use sqrt((double) n)
... ...Note that cast produces the value of n in the proper type, n itself is not altered.
这总结了 php 中的 type casting 与 type juggling 的工作方式相同,因为数据类型所作用的变量(操作数)的数量不变。您可以使用函数 settype()
来转换变量的数据类型。
正如第一段中指出的那样,php manual's page on types 在最后一段中给出了以下 技术上错误的 评论:
To forcibly convert a variable to a certain type, either cast the variable or use the settype() function on it.
现在,您知道 php 中的 type casting 的实际含义以及您为什么会有这种误解,最好将您的问题改写如下:
改写问题:如何永久转换PHP中class属性的数据类型。
显然 public 属性将很容易被 settype($myObj->myPubProp, required-type)
转换为不同的类型。有趣的是,与 user yivi's original answer, privated
and protected
properties can be assessed and can have their type converted from outside the class[1][] 中的建议相反。
方法一:使用引用:
class myClass {
private $prop = 786; //Could be protected too.
public function &assess_priv(){
return $this->prop;
}
public function display_prop() {
echo var_dump($this->prop);
}
}
$obj = new myClass;
$newObjProp = &$obj->assess_priv();
settype($newObjProp, "string");
$obj->display_prop(); //converted the data type of private property of a class
方法二:使用PHP属性重载
error_reporting(E_ALL);
class myClass {
private $prop = 786; //Could be protected too.
public function __set($name, $value)
{
$this->$name = $value;
}
public function __get($name)
{
return $this->$name;
}
}
$obj = new myClass;
var_dump($obj->prop);
$obj->prop = (string)$obj->prop; //Interestingly, settype($obj->prop, "string"); can't be used
echo "</br>";
var_dump($obj->prop); //converted the data type of private property of a class
类型转换 class 属性现在可用于 php7.4
。
<?php
class User {
public int $id;
public string $name;
}
$user = new User;
$user->id = 123; // this will work
$user->id = "hello world"; // throws fatal error
Fatal error: Uncaught TypeError: Typed property
User::$id must be int, string used in [...][...]:7 Stack trace:
#0 {main} thrown in [...][...] on line 7
您需要切换到 php7.4
。此功能现已在 7.4
link to their official docs
中可用
这是 sandbox link 在线试用。
我一直在阅读 the "Visibility" section of the PHP manual,在第一个评论中,有人提到:
OUTSIDE CODE can cast Item properties to any other PHP types (booleans, integers, floats, strings, arrays, and objects etc.) -- another huge mistake.
考虑这个例子:
class base {
public $foo = 1;
}
$first = new base();
(string)$first->foo; //I thought just this expression would typecast
var_dump($first->foo); //but I found it still is int
$first->foo = (string)$first->foo;
var_dump($first->foo); //ok so public props can be typecasted
难道只有受保护的私有属性我们不能从外部改变它们的类型吗?或者这也适用于 public 属性吗?
你正在做的是用一个新值覆盖 属性,它恰好是不同的类型。
类型转换不影响原始变量或值。它创建一个新的类型转换类型的值,如果你想保留你需要分配它。
你问的与对象属性可见性无关,但要理解类型转换是一种不影响其操作数的操作。
这对 $string
完全没有任何作用:
$string = "123";
(int)$string;
... 并且类型转换值丢失,因为我们没有分配操作的结果
如果满足以下几个条件,我们可以使用以下内容覆盖 $class::$someInteger
的值:
$class->someInteger = (string) 123;
- 属性 是 public。 (您显然不能从 class 外部直接访问
private
或protected
属性。您可以通过使用反射或奇怪的东西来绕过这个 getter returns 对 属性 的 引用 ,但两者对于生产代码来说都是非常糟糕的想法)。 - 您没有使用 PHP 7.4 typed properties,并为其声明了类型。
问题的 "permanently" 部分特别容易被误导,因为在 PHP 中通常变量 没有类型 .
您可以将任何类型的值赋给任何变量。当它们确实有类型(PHP 7.4 类型属性)时,没有实用的方法来更改定义的类型(同样,可能 是一种使用反射的方法......但是我不会去那里)。
你的问题是基于对术语 typecasting 的含义的误解。 PHP Manual's page on type casting 和整个手册一般来说,是不充分的,不是自己的-包含学习 php 语言的规范参考。此外,它假定您了解其他编程语言,例如 C。
类型转换未定义为变量的数据类型转换;它是 expression 的数据类型转换——一般来说,在大多数编程语言中都是如此。 Wikipedea 定义如下:
In computer science, type conversion, type casting, type coercion, and type juggling are different ways of changing an expression from one data type to another.
官方手册使用了三个术语,即type juggling、type conversion和type casting.从第一段可以猜到,type juggling和type conversion是一回事。他们在第一段中说:
Note that this does not change the types of the operands themselves; the only change is in how the operands are evaluated...
应该清楚 type juggling 绝对不会改变变量的类型。从 php 手册看来,type juggling 和 type casting 是两个不同的概念。问题是,由于 PHP 手册从未定义这些术语,我们如何确定这两个术语是否相同以及它们的实际含义。在 Type Casting 文章中,手册说:
Type casting in PHP works much as it does in C:...
所以,答案是,我们可以安全地假设来自 C 语言的 类型转换 的定义适用于 PHP 语言。 C语言中type casting的定义和维基百科的定义一样,只是表达式的数据类型被转换。以下摘录自书 The C Programming Language by K&R, 2nd edition,第 2.7 节,第 45 页:
In the construction
(type-name) expression
, the expression is converted to the named type... ...The precise meaning of cast is as if the expression were assigned to a variable of the specific type... ...we can usesqrt((double) n)
... ...Note that cast produces the value of n in the proper type, n itself is not altered.
这总结了 php 中的 type casting 与 type juggling 的工作方式相同,因为数据类型所作用的变量(操作数)的数量不变。您可以使用函数 settype()
来转换变量的数据类型。
正如第一段中指出的那样,php manual's page on types 在最后一段中给出了以下 技术上错误的 评论:
To forcibly convert a variable to a certain type, either cast the variable or use the settype() function on it.
现在,您知道 php 中的 type casting 的实际含义以及您为什么会有这种误解,最好将您的问题改写如下:
改写问题:如何永久转换PHP中class属性的数据类型。
显然 public 属性将很容易被 settype($myObj->myPubProp, required-type)
转换为不同的类型。有趣的是,与 user yivi's original answer, privated
and protected
properties can be assessed and can have their type converted from outside the class[1][
方法一:使用引用:
class myClass {
private $prop = 786; //Could be protected too.
public function &assess_priv(){
return $this->prop;
}
public function display_prop() {
echo var_dump($this->prop);
}
}
$obj = new myClass;
$newObjProp = &$obj->assess_priv();
settype($newObjProp, "string");
$obj->display_prop(); //converted the data type of private property of a class
方法二:使用PHP属性重载
error_reporting(E_ALL);
class myClass {
private $prop = 786; //Could be protected too.
public function __set($name, $value)
{
$this->$name = $value;
}
public function __get($name)
{
return $this->$name;
}
}
$obj = new myClass;
var_dump($obj->prop);
$obj->prop = (string)$obj->prop; //Interestingly, settype($obj->prop, "string"); can't be used
echo "</br>";
var_dump($obj->prop); //converted the data type of private property of a class
类型转换 class 属性现在可用于 php7.4
。
<?php
class User {
public int $id;
public string $name;
}
$user = new User;
$user->id = 123; // this will work
$user->id = "hello world"; // throws fatal error
Fatal error: Uncaught TypeError: Typed property User::$id must be int, string used in [...][...]:7 Stack trace: #0 {main} thrown in [...][...] on line 7
您需要切换到 php7.4
。此功能现已在 7.4
link to their official docs
这是 sandbox link 在线试用。