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

PHP:设置公共属性时调用函数

PHP:设置公共属性时调用函数

PHP
拉风的咖菲猫 2021-12-24 09:13:36
我有一个名为 reportPayment 的对象:class reportPayment extends JournalListElement {public $paymentType;public $paymentNum;public $paymentAmnt;public $accID;public $accDesc;function setPaymentAmnt($paymentAmnt) {    $this->paymentAmnt = MoneyHelper::centsToDollars($paymentAmnt);}function getPaymentAmnt() {    return $this->paymentAmnt;}}另一个类遍历此对象的公共属性以写入 XML 文件;通过:foreach ($object as $key => $value) { }我的问题是我$paymentAmnt只需要通过这里的 setter 进行设置,以便centsToDollars()调用函数。这仅在我转向$paymentAmnt私有属性时才有效,这是我在遍历对象属性时无法承受的。简而言之,我需要的是一种方法:确保centsToDollars()在设置时调用$paymentAmnt确保$paymentAmnt可以从外面看到编辑:现在可以按照 Michal 的回答将其设置为私有,并且仍然可以通过 getter 访问该属性。将它设置为私有意味着我无法迭代对象的属性,但在这种情况下这对我来说非常重要。有没有办法在 Yii2/PHP 中做到这一点?
查看完整描述

2 回答

?
慕森王

TA贡献1777条经验 获得超3个赞

一旦您将属性声明为公共属性,您就无法限制对它的访问,因此无法仅通过 setter 强制设置它。


但是在 Yii 中有一种方法可以让财产看起来是公开的,即使它不是。


如果你的类JournalListElement继承自 \yii\base\BaseObject(Yii 中的大多数类都继承自 this)并且如果你将 setter 和 getter 声明为 this


class ReportPayment extends JournalListElement

{

    private $paymentAmnt;


    public setPaymentAmnt($value)

    {

        ...

    }


    public getPaymentAmnt()

    {

       ...

    }

}

然后您仍然可以paymentAmnt像这样访问该属性,就像它是公开的一样:


  $report = new ReportPayment();

  $report->paymentAmnt = 20;

  echo $report->paymentAmnt;

那是因为\yii\base\BaseObject里面有__set和__get魔法方法的实现。当您尝试访问无法访问的属性时,这些方法将调用setPropertyName()或者getPropertyName()是否存在此类方法。


如果属性是,private您仍将直接从 ReportPayment 类中访问它。您将通过 getter/setter 从类外部或从扩展 ReportPayment 的类自动访问它。


如果属性是,protected您将直接从 ReportPayment 和扩展它的所有类中访问它。您将通过来自 ReportPayment 类或其子类之外的 getter/setter 访问它。


在纯 php 中,您可以通过自己实现__set和__get方法来获得类似的结果。


迭代属性


您可以使用 ReflectionClass 来获取所有属性的列表(包括私有属性),但我不建议这样做。使用这种方式违背了OOP的原则,以后可能会出现问题。例如在您需要添加更多私有属性的情况下。在这种情况下,您将不得不编辑所有 foreach 循环以跳过新属性。


可能的更好方法:


1) 返回可见属性数组的方法:


class ReportPayment extends JournalListElement

{

    ... code declaring properties and getters/setters

    public function getProperties()

    {

        return ['paymentType', 'paymentNum', 'paymentAmnt', ...];

    }

}


foreach ($object->getProperties() as $prop) {

    echo $object->$prop;

}

2) 将属性转换为数组的方法


class ReportPayment extends JournalListElement

{

    ... code declaring properties and getters/setters

    public function asArray()

    {

        return [

            'paymentType' => $this->paymentType,

            'paymentNum' => $this->paymentNum,

            'paymentAmnt' => $this->paymentAmnt,

            ...

        ];

    }

}


foreach ($object->asArray() as $prop => $value) {

    echo $prop . ": " . $value;

}

3) 实现Iterator接口。您可以在此处找到更多详细信息。自己的Iterator接口实现允许您控制 foreach 通过哪些键/值。


这些方法的最大优点是类本身仍然控制循环经过的属性。


查看完整回答
反对 回复 2021-12-24
?
幕布斯6054654

TA贡献1876条经验 获得超7个赞

通过反射,您可以遍历对象属性,即使它们是私有的:


$reflect = new ReflectionClass($reportPaymentObject);

$props   = $reflect->getProperties(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED | ReflectionProperty::IS_PRIVATE);


foreach ($props as $prop) {

    print $prop->getName() . "\n";

}


查看完整回答
反对 回复 2021-12-24
  • 2 回答
  • 0 关注
  • 221 浏览

添加回答

举报

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