5

PHPの単純なORMにフックシステムを実装したい:

class Record {
  public function save() {
    if (method_exists($this,"before_save")) {
      $this->before_save();
    }
    //...Storing record etc.
  }
}

class Payment extends Record {
  private function before_save() {
    $this->payed_at = time();
  }
}

$payment = new Payment();
$payment->save();

これにより、致命的なエラーが発生します。

致命的なエラー: コンテキスト 'Record' からプライベート メソッド Payment::before_save() を呼び出します

理にかなっています。

スコープを public に変更することもできましたが、それは醜いようです: 誰も Payment 以外は と関係がありませんbefore_save()。プライベートのままにしておくのが最善です、IMHO。

Record から継承するクラスで Record 呼び出しをプライベート メソッドにするにはどうすればよいですか?

4

6 に答える 6

8

before_saveクラスにダミー関数を追加しRecord、アクセス可能に保護を設定します。から継承するすべてのクラスRecordがこの関数を持ち、上書きしない場合は何もしません。上書きすると、目的の機能を実装できます。

class Record {
  public function save() {
    $this->before_save();
    //...Storing record etc.
  }

  protected function before_save() {
     return;
  }
}

class Payment extends Record {
  protected function before_save() {
    $this->payed_at = time();
  }
}
于 2012-09-26T14:21:27.453 に答える
4

エラーメッセージを確認する

Call to private method Payment::before_save() from context 'Record'

Paymentこれは、内にいる間に で定義された関数を呼び出そうとしていることを意味しますRecord。クラスは、関数が定義されている場所よりも継承チェーンの上位にあるため、メソッドRecordを持っていません。before_save

つまり、親子関係はRecord (is parent of) Paymentであり、(親から継承することにより) 関数PaymentにアクセスできますがRecords、その逆はできません (親は子クラスの関数を「継承」できません)。関数を保護して、継承チェーンの上下にアクセスできるようにすることができますが、アーキテクチャを再考して、必要かどうかを決定することをお勧めします.. 理想的には、関数を で定義しRecord、オーバーライドする必要がありますPayment

また(これは間違っているかもしれませんが)、method_exists実行時のクラスをオーバーラップおよび/または生成できる本当に動的なシステムを作成していない限り、通常は明示的にチェックする必要はありません。クラスベースのシステムをゼロから定義していて、さまざまな部分をどのようにつなぎ合わせているかを知っている場合は、通常、実行時にチェックする必要はありませんmethod_exists...ただの考え..

于 2012-09-26T14:18:58.783 に答える
3

スコープを保護に変更します。

http://php.net/manual/en/language.oop5.visibility.php

于 2012-09-26T14:18:40.433 に答える
2

PHP における可視性と継承の規則:

保護されていると宣言されたメンバーは、クラス自体内で、継承されたクラスと親クラスによってのみアクセスできます

于 2012-09-26T14:23:12.643 に答える
0
class test {

    private function pri($val){
        return $val;
    }

    function caller(){
       return $this->pri(5);
    }
}

$testobj = new test;
echo $testobj->caller();

出力として 5 が得られます。

このようにして、クラスのプライベート関数にアクセスできます。

于 2012-09-26T14:24:12.520 に答える