猿问

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

我有一个名为 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私有属性时才有效,这是我在遍历对象属性时无法承受的。

简而言之,我需要的是一种方法:

  1. 确保centsToDollars()在设置时调用$paymentAmnt

  2. 确保$paymentAmnt可以从外面看到

编辑:现在可以按照 Michal 的回答将其设置为私有,并且仍然可以通过 getter 访问该属性。将它设置为私有意味着我无法迭代对象的属性,但在这种情况下这对我来说非常重要。有没有办法在 Yii2/PHP 中做到这一点?


拉风的咖菲猫
浏览 222回答 2
2回答

慕森王

一旦您将属性声明为公共属性,您就无法限制对它的访问,因此无法仅通过 setter 强制设置它。但是在 Yii 中有一种方法可以让财产看起来是公开的,即使它不是。如果你的类JournalListElement继承自 \yii\base\BaseObject(Yii 中的大多数类都继承自 this)并且如果你将 setter 和 getter 声明为 thisclass 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 通过哪些键/值。这些方法的最大优点是类本身仍然控制循环经过的属性。

幕布斯6054654

通过反射,您可以遍历对象属性,即使它们是私有的:$reflect = new ReflectionClass($reportPaymentObject);$props   = $reflect->getProperties(ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED | ReflectionProperty::IS_PRIVATE);foreach ($props as $prop) {    print $prop->getName() . "\n";}
随时随地看视频慕课网APP
我要回答