为了账号安全,请及时绑定邮箱和手机立即绑定

如何在PHP中永久地类型转换类属性?

如何在PHP中永久地类型转换类属性?

PHP
暮色呼如 2022-08-05 18:46:40
我一直在阅读PHP手册的“可见性”部分,在第一条评论中,有人提到:OUTSIDE CODE可以将 Item 属性转换为任何其他 PHP 类型(布尔值、整数、浮点数、字符串、数组和对象等)——这是另一个巨大的错误。请考虑以下示例:class base {    public $foo = 1;}$first = new base();(string)$first->foo; //I thought just this expression would typecastvar_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难道只是对于受保护的私有属性,我们不能从外部更改它们的类型吗?或者这是否也适用于公共财产?
查看完整描述

3 回答

?
LEATH

TA贡献1936条经验 获得超6个赞

您正在执行的操作是用新值覆盖属性,该值恰好是不同的类型。

类型强制转换不会影响原始变量或值。它将创建一个类型转换类型的新值,如果要保留该值,则需要分配该值。

您所要求的内容与对象属性可见性无关,而是与理解类型转换是一种不影响其操作数的操作有关。

这对以下方面绝对没有任何作用:$string

$string = "123";
(int)$string;

...并且类型转换值丢失,因为我们没有分配操作的结果

通过以下方法,如果满足几个条件,我们可以覆盖 的值:$class::$someInteger

$class->someInteger = (string) 123;
  1. 该物业是公共的。(您显然无法从类外部直接访问或属性。你可以通过使用反射或奇怪的东西来欺骗这个问题,比如有一个 getter 返回对属性的引用,但对于生产代码来说,这两者都是非常糟糕的主意)。privateprotected

  2. 您没有使用 PHP 7.4 类型化属性,并且已为其声明了类型。

这个问题的“永久”部分特别被误导,因为在PHP中,变量通常没有类型

您可以将任何类型的值赋给任何变量。当它们确实具有类型(PHP 7.4类型化属性)时,没有实际的方法可以更改定义的类型(再次,可能有一种方法使用反射...但我不会去那里)。


查看完整回答
反对 回复 2022-08-05
?
白猪掌柜的

TA贡献1893条经验 获得超10个赞

你的问题是基于对术语类型转换含义的误解。PHP手册中关于类型转换的页面和整个手册是不够的,也不是学习php语言的独立规范参考。另外,它假设您了解其他编程语言,例如C。

类型转换不定义为变量的数据类型转换;它是表达式的数据类型转换 - 通常,这是在大多数编程语言中。Wikipedea将其定义如下:

在计算机科学中,类型转换、类型强制转换、类型强制和类型杂耍是将表达式从一种数据类型更改为另一种数据类型的不同方法。

官方手册使用三个术语,即类型杂耍类型转换类型转换。从第一段中可以猜到,类型杂耍类型转换是一回事。在第一段中,他们说:

请注意,这不会更改操作数本身的类型;唯一的变化是操作数的计算方式...

应该清楚的是,类型杂耍绝对不会改变变量的类型。从php手册中可以看出,类型杂耍类型转换是两个不同的概念。问题是,由于PHP手册从未定义过这些术语,我们如何确保这两个术语是否相同以及它们的实际含义。在类型铸造文章中,手册说:

PHP中的类型转换的工作方式与在C:...

所以,答案是,我们可以安全地假设C语言的类型转换的定义适用于PHP语言。在C语言中,类型转换的定义与维基百科定义相同,即仅转换表达式的数据类型。以下摘录摘自K&R的《The C Programming Language by K&R》一书,第2版,第2.7节,第45页:

在构造中,表达式被转换为命名类型... ...cast的确切含义是,就好像表达式被分配给特定类型的变量一样......我们可以使用...请注意,强制转换在正确的类型中产生n的值,n本身不会改变。(type-name) expressionsqrt((double) n)

这样的结论是,php 中的类型转换的工作方式与类型杂耍相同,因为所操作的变量(操作数)的数据类型不会更改。您可以使用该函数来转换变量的数据类型。settype()

正如第一段所指出的,php手册的type页面在最后一段中给出了以下技术上错误的注释:

要强制将变量转换为特定类型,请强制转换该变量或对其使用 settype() 函数。

现在,您知道php中的类型转换实际上意味着什么,以及为什么您有这种误解,最好将您的问题改写如下:

改写的问题:如何在 PHP 中永久转换类属性的数据类型。

很明显,公共属性将很容易地通过 转换为不同类型的。有趣的是,与用户yivi的原始答案中提出的建议相反,可以评估私有受保护的属性,并且可以从类外转换其类型[1][2]。settype($myObj->myPubProp, required-type)

方法 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  

方法 2: 使用 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 


查看完整回答
反对 回复 2022-08-05
?
繁星淼淼

TA贡献1775条经验 获得超11个赞

类型转换类属性现在在 中可用。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


致命错误: 未捕获的类型错误: 键入的属性 用户::$id 必须是 int, 字符串用于 [...][...]:7 堆栈跟踪: #0 {main} 抛入 [...][...]在7号线

您需要切换到 .此功能现已在其官方文档的链接中提供php7.47.4

这是在线试用的沙盒链接


查看完整回答
反对 回复 2022-08-05
  • 3 回答
  • 0 关注
  • 163 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信