ゲッターとセッター?


203

私はPHP開発者ではないので、PHPでは明示的なゲッター/セッターを純粋なOOPスタイルでプライベートフィールドとともに使用する方が一般的かどうか(私が好きな方法)はどうでしょうか。

class MyClass {
    private $firstField;
    private $secondField;

    public function getFirstField() {
        return $this->firstField;
    }
    public function setFirstField($x) {
        $this->firstField = $x;
    }
    public function getSecondField() {
        return $this->secondField;
    }
    public function setSecondField($x) {
        $this->secondField = $x;
    }
}

または単にパブリックフィールド:

class MyClass {
    public $firstField;
    public $secondField;
}

ありがとう


7
回答からいくつかのコードを試した後、質問で使用しているコードを使用しました。なんて悲しい:-(
sumid

9
PHPstorm ...生成>ゲッターとセッター。==勝利
DevDonkey

@DevDonkeyまったく勝利ではありません。構造化データを保持するには、代わりに配列を使用します。@:Markこれはオブジェクトの目的ではありません。ゲッターとセッターは悪です:yegor256.com/2014/09/16/getters-and-setters-are-evil.html
Kubo2

回答:


222

PHPのマジックメソッド __getとを使用できます__set

<?php
class MyClass {
  private $firstField;
  private $secondField;

  public function __get($property) {
    if (property_exists($this, $property)) {
      return $this->$property;
    }
  }

  public function __set($property, $value) {
    if (property_exists($this, $property)) {
      $this->$property = $value;
    }

    return $this;
  }
}
?>

15
と思う__get__set。アンダースコアは2つあり、1つではありません。これはページの右側の部分への直接リンクです:php.net/manual/en/… (正解は+1)
Computerish

28
public検証/衛生設備がない場合、プロパティに対するメリットは何ですか?
KingCrunch、

7
@KingCrunch、これはほんの一例です。強力なリソースの非常にダミーの例。
Davis Peixoto、

10
それは本当にセッターとゲッターではありません。通常、ゲッターの実装ごとに異なるプロパティが必要です!
sumid

79
してはいけないこと:マジックメソッドを使用すると、多くのIDE(vimも含む)で、品質関連のほぼすべての機能が失われます。cf. stackoverflow.com/a/6184893/490589
Ronan

113

なぜゲッターとセッターを使うのですか?

  1. スケーラビリティ:プロジェクトコード内のすべての変数割り当てを検索するよりも、ゲッターをリファクタリングする方が簡単です。
  2. デバッグ:セッターとゲッターにブレークポイントを設定できます。
  3. Cleaner:マジック関数は、書き込みを少なくするための適切なソリューションではありません。IDEはコードを提案しません。高速に作成するゲッターにはテンプレートを使用するほうがよい。

直接割り当てとゲッター/セッター


7
@propertyを使用する場合、IDEがコードを提案します(PhpStorm 7でテスト)
Alex2php

41

GoogleはすでにPHPの最適化に関するガイドを公開しており、結論は次のとおりです。

getterとsetterがない PHPの最適化

そして、いいえ、あなたは魔法の方法を使用してはなりませ。PHPの場合、マジックメソッドは悪です。どうして?

  1. デバッグするのは難しいです。
  2. パフォーマンスに悪影響があります。
  3. 彼らはより多くのコードを書く必要があります。

PHPはJava、C ++、C#ではありません。PHPは異なり、さまざまな役割を果たします。


10
私はその考えに同意する傾向があります。それ$dog->name = 'fido'はより良いです$dog->setName('fido')。プロパティを実際に変更する場合(例:$dog->increaseAge(1)必要な検証を実行してそのプロパティを変更するメソッドを構築できます。ただし、すべてのアクションがその意味で実際に変更を必要とするわけではありません。)
Charlie Schliesser

11
記事にしないでください」とは書かれておらず、「素朴なセッターとゲッター」と書かれています。
Brett Santore 14


13
「PHPパフォーマンスのヒント」という見出しのあるGoogleの記事は、優れたコーディングスタイルを提案するものではなく、高速なコード実行を想定していると考えるのが無難です。セッターとゲッターを扱う章には「ナイーブなセッターとゲッターの作成を避ける」というラベルが付いており、コード例はまさにナイーブです。検証なしで変数を設定および取得します。この種のセッター/ゲッターは役に立たない。セッター内で検証を行うと(メソッドの引数にタイプヒントを使用するだけ)、セッター/ゲッターが便利になります。これは、コードが処理対象を認識しているためです。
2016

3
これは、インラインスタイルの方が優れていると言っているようなものです。もちろんパフォーマンスは優れていますが、コードの方が優れていますか?とにかく、Googleのエンジニアがphpを使用していることを知りませんでした
Claudiu Creanga

13

カプセル化はどのOO言語でも重要です。人気はそれとは関係ありません。PHPのような動的に型付けされた言語では、セッターを使用せずにプロパティが特定の型であることを確認する方法がほとんどないため、これは特に便利です。

PHPでは、これは機能します。

class Foo {
   public $bar; // should be an integer
}
$foo = new Foo;
$foo->bar = "string";

Javaでは、次のことは行いません。

class Foo {
   public int bar;
}
Foo myFoo = new Foo();
myFoo.bar = "string"; // error

マジックメソッド(__getおよび__set)の使用も機能しますが、現在のスコープよりも低い可視性を持つプロパティにアクセスできる場合のみです。正しく使用しないと、デバッグしようとすると頭痛がしやすくなります。


7
ゲッターとセッターはカプセル化をもたらしません。カプセル化==オブジェクトは、外部に渡すのではなく、独自のデータで何かを行います。ゲッターとセッターは、PHPのような動的に型付けされた言語で型を強制するためのツールではありません。
smentek

14
@smentek:カプセル化が実際に何であるかの少なくとも半分が明らかに欠けています。
ネットコーダー、2011年

2
PHP 7.4には、これを更新する人のための型付きプロパティサポートが付属しています。あなたは宣言することができるように$barint最初の例では:wiki.php.net/rfc/typed_properties_v2
ケビン・

7

__call関数を使用する場合は、このメソッドを使用できます。それはで動作します

  • GET => $this->property()
  • セット=> $this->property($value)
  • GET => $this->getProperty()
  • セット=> $this->setProperty($value)

カルスダス

public function __call($name, $arguments) {

    //Getting and setting with $this->property($optional);

    if (property_exists(get_class($this), $name)) {


        //Always set the value if a parameter is passed
        if (count($arguments) == 1) {
            /* set */
            $this->$name = $arguments[0];
        } else if (count($arguments) > 1) {
            throw new \Exception("Setter for $name only accepts one parameter.");
        }

        //Always return the value (Even on the set)
        return $this->$name;
    }

    //If it doesn't chech if its a normal old type setter ot getter
    //Getting and setting with $this->getProperty($optional);
    //Getting and setting with $this->setProperty($optional);
    $prefix = substr($name, 0, 3);
    $property = strtolower($name[3]) . substr($name, 4);
    switch ($prefix) {
        case 'get':
            return $this->$property;
            break;
        case 'set':
            //Always set the value if a parameter is passed
            if (count($arguments) != 1) {
                throw new \Exception("Setter for $name requires exactly one parameter.");
            }
            $this->$property = $arguments[0];
            //Always return the value (Even on the set)
            return $this->$name;
        default:
            throw new \Exception("Property $name doesn't exist.");
            break;
    }
}

2
@ krzysztof-przygoda:この「マジックメソッド」には常に価格が付いています。彼らは再帰を使わなければならずproperty_exists(get_class($this), $name)、再帰は遅いです。キャッシュを使用してこれを軽減する方法はありますが、ゲッターとセッターを手動で作成するよりも遅くなります。私はこれを代わりとして書いただけです。私は実際には「魔法の方法」の使用を推奨していません。ゲッターとセッターを作成する余分な時間は通常重要ではありません。
J-Rou

7

ここですでに高く評価されている回答に加えて、セッター/ゲッターを持たないPHPについて詳しく説明します。

PHPにはゲッターとセッターの構文はありませんDaveが指摘したように、プロパティのルックアッププロセスを「フック」してオーバーライドできるようにするために、サブクラス化されたメソッドまたはマジックメソッドを提供します。

マジックを使用すると、怠惰なプログラマーは、プロジェクトに積極的に取り組んでいるときに、少ないコードでより多くのことを実行でき、親密にそれを知ることができますが、通常は読みやすさが犠牲になります。

パフォーマンス PHPでゲッター/セッターのようなコードアーキテクチャを強制した結果として生じるすべての不要な関数は、呼び出し時に独自のメモリスタックフレームを含み、CPUサイクルを浪費しています。

読みやすさ: LOCが多いほどスクロールが多くなるため、コードベースではコード行が肥大化し、コードナビゲーションに影響します。

好み:個人的には、私の経験則として、明らかな長期的な利益がその時点で私に及ばない限り、魔法の道を進むのを避けるために、静的コード分析の失敗を兆候として捉えます。

誤謬:

一般的な議論は読みやすさです。たとえば、それ$someobject->widthよりも読みやすいです$someobject->width()。ただし、と見なすことができる 惑星のcircumferenceor とは異なり、幅関数を必要とするのようなオブジェクトのインスタンスは、オブジェクトのインスタンスの幅を測定する可能性があります。 したがって、可読性は主に断定的な命名方式のために向上し、特定のプロパティ値を出力する関数を非表示にすることによっては向上しません。widthstatic$someobject

__get / __setの使用:

  • プロパティ値の事前検証と事前衛生

  • ストリング

    "
    some {mathsobj1->generatelatex} multi
    line text {mathsobj1->latexoutput}
    with lots of variables for {mathsobj1->generatelatex}
     some reason
    "

    この場合generatelatex、actionname + methodnameの命名スキームに従います。

  • 特別な明らかな場合

    $dnastringobj->homeobox($one_rememberable_parameter)->gattaca->findrelated()
    $dnastringobj->homeobox($one_rememberable_parameter)->gttccaatttga->findrelated()

注: PHPは、getter / setter構文を実装しないことを選択しました。ゲッター/セッターが一般的に悪いとは主張していません。


6
class MyClass {
    private $firstField;
    private $secondField;
    private $thirdField;

    public function __get( $name ) {
        if( method_exists( $this , $method = ( 'get' . ucfirst( $name  ) ) ) )
            return $this->$method();
        else
            throw new Exception( 'Can\'t get property ' . $name );
    }

    public function __set( $name , $value ) {
        if( method_exists( $this , $method = ( 'set' . ucfirst( $name  ) ) ) )
            return $this->$method( $value );
        else
            throw new Exception( 'Can\'t set property ' . $name );
    }

    public function __isset( $name )
    {
        return method_exists( $this , 'get' . ucfirst( $name  ) ) 
            || method_exists( $this , 'set' . ucfirst( $name  ) );
    }

    public function getFirstField() {
        return $this->firstField;
    }

    protected function setFirstField($x) {
        $this->firstField = $x;
    }

    private function getSecondField() {
        return $this->secondField;
    }
}

$obj = new MyClass();

echo $obj->firstField; // works
$obj->firstField = 'value'; // works

echo $obj->getFirstField(); // works
$obj->setFirstField( 'value' ); // not works, method is protected

echo $obj->secondField; // works
echo $obj->getSecondField(); // not works, method is private

$obj->secondField = 'value'; // not works, setter not exists

echo $obj->thirdField; // not works, property not exists

isset( $obj->firstField ); // returns true
isset( $obj->secondField ); // returns true
isset( $obj->thirdField ); // returns false

いいよ


定型文が多すぎます。このようなものがすべてのクラスにあると想像してください。IMOを回避する
DarkNeuron、2015

PHPは、あなたが言及したのと同じ理由でゲッターとセッターをサポートしません。このタイプの実装は、サーバー側スクリプトのパフォーマンスに深刻な影響を与えます。
joas

これは「プライベート」プロパティに反すると思います。それらをカプセル化しますが、直接アクセスすることもできます。
KorayKüpe19年

@KorayKüpe(ゲッターが定義されている場合のみ)。私はこのカプセル化を(多くの改良を加えて)頻繁に使用しており、完全に機能します。クラスを拡張して、すべてのコードで簡単に使用することもできます。
-joas

5

まあ、PHPは魔法のメソッドを持っている__get__set__isset__unset常に開始されています、。残念ながら、適切な(それを取得しますか?)OOプロパティは、魔法のメソッド以上のものです。PHPの実装の主な問題は、アクセスできないすべてのプロパティに対して魔法のメソッドが呼び出されることです。つまり、名前が実際にオブジェクトのプロパティであるかどうかを判断するときは、マジックメソッドで(たとえば、property_exists()を呼び出して)自分自身を繰り返す必要があります。そして、すべてのクラスがieから継承しない限り、基本クラスでこの一般的な問題を実際に解決することはできません。PHPには多重継承がないため、ClassWithProperties。

対照的に、Pythonの新しいスタイルクラスはを提供しますproperty()。これにより、すべてのプロパティを明示的に定義できます。C#には特別な構文があります。

http://en.wikipedia.org/wiki/Property_(programming)


1
property_exists、class_vars、またはarray_key_existsを呼び出す(つまり、プロパティが実際に存在するかどうかを確認する)ことは、実行時の致命的なエラーを回避するための手順にすぎません。不満がないことがコーディングで反復的であることと同じかどうかはわかりません。
Davis Peixoto

1
けっこうだ。しかし、PythonとC#では、この繰り返しは必要ありません。それが強みだと思います。
エマニュエルランデホルム2010

4

魔法のメソッド__callを使用して実験を行いました。(他の回答やコメントにある「魔法の方法を使用しないでください」という警告があるため)投稿する必要があるかどうかはわかりませんが、誰かが役に立つと思った場合に備えて、ここに残しておきます。


public function __call($_name, $_arguments){
    $action  = substr($_name, 0, 4);
    $varName = substr($_name, 4);

    if (isset($this->{$varName})){
        if ($action === "get_") return $this->{$varName};
        if ($action === "set_") $this->{$varName} = $_arguments[0];
    }
}

上記のメソッドをクラスに追加するだけで、次のように入力できます。

class MyClass{
    private foo = "bar";
    private bom = "bim";
    // ...
    // public function __call(){ ... }
    // ...
}
$C = new MyClass();

// as getter
$C->get_foo(); // return "bar"
$C->get_bom(); // return "bim"

// as setter
$C->set_foo("abc"); // set "abc" as new value of foo
$C->set_bom("zam"); // set "zam" as new value of bom


このように、存在する場合はクラス内のすべてを取得/設定できるため、特定の要素のみに必要な場合は、「ホワイトリスト」をフィルターとして使用できます。

例:

private $callWhiteList = array(
    "foo" => "foo",
    "fee" => "fee",
    // ...
);

public function __call($_name, $_arguments){
    $action  = substr($_name, 0, 4);
    $varName = $this->callWhiteList[substr($_name, 4)];

    if (!is_null($varName) && isset($this->{$varName})){
        if ($action === "get_") return $this->{$varName};
        if ($action === "set_") $this->{$varName} = $_arguments[0];
    }
}

現在は、「foo」と「fee」のみを取得/設定できます。
その「ホワイトリスト」を使用して、varにアクセスするためのカスタム名を割り当てることもできます。
例えば、

private $callWhiteList = array(
    "myfoo" => "foo",
    "zim" => "bom",
    // ...
);

このリストを使用して、次のように入力できます。

class MyClass{
    private foo = "bar";
    private bom = "bim";
    // ...
    // private $callWhiteList = array( ... )
    // public function __call(){ ... }
    // ...
}
$C = new MyClass();

// as getter
$C->get_myfoo(); // return "bar"
$C->get_zim(); // return "bim"

// as setter
$C->set_myfoo("abc"); // set "abc" as new value of foo
$C->set_zim("zam"); // set "zam" as new value of bom




それで全部です。


Doc: __call()は、オブジェクトコンテキストでアクセスできないメソッドを呼び出すとトリガーされます。


これらのすべての「マジック」ソリューションの問題は、これらのマジックメソッドが存在するためにそれらを使用するだけであり、求められる問題が単純で一般的なものであるため、有用であるということです。このレベルの一般的な問題から離れると、単純な魔法の方法では解決できない特定の要件が発生しますが、非常に複雑な魔法の方法、または個別のコード化されたセッターとゲッターが必要になります。
2016

2

他のアドバイスを読んだ後、私はこう言う傾向があります:

GENERICルールとして、すべてのプロパティ、特に「内部」プロパティ(セマフォ、内部フラグ...)のセッターを常に定義するわけではありません。読み取り専用プロパティには明らかにセッターがないため、一部のプロパティにはゲッターしかありません。ここで__get()がコードを圧縮します。

  • 同様のすべてのプロパティに対して__get()(魔法のグローバルゲッター)を定義します。
  • それらを配列にグループ化します。
    • それらは共通の特徴を共有します:金銭的価値は適切にフォーマットされます/特定のレイアウト(ISO、US、Intl。)などの日付が表示されます。
    • コード自体は、この魔法の方法を使用して、既存の許可されたプロパティのみが読み取られていることを確認できます。
    • 新しい同様のプロパティを作成する必要があるときはいつでも、それを宣言し、その名前を適切な配列に追加するだけで完了です。これは、新しいゲッターを定義するよりもはるかに高速です。おそらく、コードのいくつかの行がクラスコード全体で何度も繰り返されます。

はい!そのためのプライベートメソッドを作成することもできますが、繰り返しになりますが、多くのメソッドが宣言され(++ memory)、別の常に同じメソッドが呼び出されます。それらすべて統治するSINGLEメソッドを作成しないのはなぜですか...?【うん!絶対に意図的なしゃれ!:)]

マジックセッターは特定のプロパティのみに応答することもできるため、すべての日付型プロパティを1つのメソッドだけで無効な値に対してスクリーニングできます。日付型のプロパティが配列にリストされている場合、それらのセッターは簡単に定義できます。もちろん一例です。状況が多すぎます。

可読性私はIDE(実際には、私が利用していないの用途にバインドするのが好きではありません、彼らは私に言う(とする傾向がある:...うーん...別の議論だ強制的に私を)どのように書く...そして私は「美」のコーディングについて私の好きなものがあります)。私は命名について一貫している傾向があるので、ctagsと他のいくつかの援助を使用することで十分です...とにかく:すべてのこの魔法のセッターとゲッターが完了したら、あまりにも具体的または「特別」な他のセッターを記述します__set()メソッドで一般化されます。そして、それは私がプロパティを取得して設定するために必要なすべてをカバーしています。もちろん、常に共通の根拠があるわけではありません。または、魔法のメソッドをコーディングするのに値しないようないくつかのプロパティがあり、それから古い古くて良い伝統的なセッター/ゲッターのペアがまだあります。

プログラミング言語はまさにそれです:人間の人工言語。したがって、それぞれに独自のイントネーションまたはアクセント、構文、およびフレーバーがあるため、JavaまたはC#と同じ「アクセント」を使用してRubyまたはPythonコードを書くふりをしたり、JavaScriptまたはPHPに似せたりすることはありませんPerlまたはSQL ...本来の使用方法で使用してください。


1

一般的に言って、最初の方法は全体的に人気があります。プログラミングの知識がある人はPHPに簡単に移行でき、オブジェクト指向で作業を行うことができるためです。最初の方法はより普遍的です。私のアドバイスは、多くの言語で試され、真実に固執することです。そうすれば、別の言語を使用している場合は、(ホイールの再発明に時間を費やす代わりに)何かを達成する準備が整います。


0

netbeans-conventionでソースコードを作成する方法はたくさんあります。これはいいね。それはそのように簡単に考えることになります===偽。特にカプセル化するプロパティとカプセル化しないプロパティがわからない場合は、traditionelを使用してください。私は知っています、それはboi .... pla ...コードですが、デバッグ作業や他の多くの人にとっては、それがより良い明確な方法であると考えています。簡単なゲッターとセッターを作成する方法について、アートのThousendで多くの時間を費やさないでください。マジックを使用する場合、demeter-ruleなどの一部の設計パターンを実装することはできません。特定の状況では、magic_callsを使用するか、小さくて高速かつ明確なソリューションを使用できます。もちろん、この方法でデザインパターンのソリューションを作成することもできますが、なぜ生活を困難にするのでしょうか。


0

検証+値のフォーマット/導出

セッターを使用してデータを検証し、ゲッターを使用してデータをフォーマットまたは導出できます。オブジェクトを使用すると、データとその検証およびフォーマットコードを、DRYを促進するきちんとしたパッケージにカプセル化できます。

たとえば、誕生日を含む次の単純なクラスを考えてみます。

class BirthDate {

    private $birth_date;

    public function getBirthDate($format='Y-m-d') {
        //format $birth_date ...
        //$birth_date = ...
        return $birth_date;
    }

    public function setBirthDate($birth_date) {                   
        //if($birth_date is not valid) throw an exception ...          
        $this->birth_date = $birth_date;
    }

    public function getAge() {
        //calculate age ...
        return $age;
    }

    public function getDaysUntilBirthday() {
        //calculate days until birth days
        return $days;
    }
}

設定されている値が

  • 有効な日付
  • 将来ではない

また、アプリケーション全体(または複数のアプリケーション)でこの検証を実行する必要はありません。代わりに、(セッターを唯一のアクセスポイントにするために)メンバー変数を保護またはプライベートにし、セッターで検証する方が簡単です。オブジェクトの取得元のアプリケーション。さらに検証を追加する場合は、1つの場所に追加できます。

同じメンバー変数を操作する複数のフォーマッターを追加する場合getAge()getDaysUntilBirthday()getBirthDate()ロケールに応じて構成可能なフォーマットを適用する場合があります。したがって、私はと混合$date->getAge()するのではなく、ゲッターを介して一貫して値にアクセスすることを好みます$date->birth_date

ゲッターとセッターは、オブジェクトを拡張するときにも役立ちます。たとえば、アプリケーションで、150年以上の生年月日を許可する必要がある場所と許可しない場所があるとします。コードを繰り返さずに問題を解決する1つの方法は、BirthDateオブジェクトを拡張し、追加の検証をセッターに配置することです。

class LivingBirthDate extends BirthDate {

    public function setBirthDate($birth_date) {
        //if $birth_date is greater than 150 years throw an exception
        //else pass to parent's setter
        return parent::setBirthDate($birth_date);
    }
}

ただし、多くの場合、プロパティを(個別にではなく)一緒に検証する必要があります。「セッター」を許可すると、コンテキストもキャプチャされなくなると思います。検証は状況に応じて行う必要があります。また、すべてのメソッドの「isValid」フラグをチェックする必要があります(それがfalseの場合は検証を実行します)。そうは言っても、値オブジェクト(つまりMoney)にしたいプロパティがある場合など、セッターはタイプヒントに役立つ方法を提供します。
プログラハンマー2015

「isValid」フラグをチェックすることを強制されたという意味がわかりませんか?値を設定する唯一の方法が検証を実行するセッターを使用する場合、データが正常に設定されたという事実により、データが有効であることがわかります。プロパティを一緒に検証する必要がある場合は、それらのプロパティのセッターが呼び出す共通の検証メソッドを記述できます。
FuzzyTree、2015

との従業員クラスがあるsetHiredとしsetHireDateます。従業員を採用済みとして設定せずに誰かに採用日を設定させることはできません。しかし、これを強制する方法はありません。これらのセッターの1つでそれを強制する場合、「設定」の順序を強制するよりも、開発者からコードを読み取って知る必要があります。次に$employee->promote($newPosition);、フラグをチェックして検証が完了したかどうかを確認する必要があるようなメソッドを実行するときに、検証が完了していないと想定して再度実行します(冗長)。
プログラハンマー2015

代わりに、相互作用をキャプチャします。おそらく、$employee->updateWorkStatus($hired, $hireDate);またはより高度な場合$employee->adminUpdate(\Employee\AdminUpdateDTO $dto);。これで、必要なコンテキストで検証し、追加の検証が必要かどうかを判断できます。
プログラハンマー2015

updateWorkStatusは基本的に、1つの値ではなく2つの値を設定するセッター関数ですが、概念は同じです。これはその方法の1つですが、一緒に検証する必要のあるすべてのプロパティが設定されている場合にのみ実行される共通のメソッドにコンテキスト検証を配置することもできます。 isset hiredとisset hiredDateの両方がtrueの場合。
FuzzyTree 2015

0

この投稿は、程度、具体的ではない__get__setではなく、__callメソッドの呼び出しを除いて同じ考えです。原則として、私はコメントや記事に概説の理由でオーバーロードを許可するための魔法のメソッドのいずれかのタイプから離れもつとも、私は最近、私は、サービスおよびSUB-SERVICE、例を使用する使用することをサードパーティのAPIに走りました:

http://3rdparty.api.com?service=APIService.doActionOne&apikey=12341234

これの重要な部分は、このAPIでは、サブアクション(この場合)を除いてすべてが同じであることdoActionOneです。アイデアは、開発者(私とこのクラスを使用する他の人)が、次のようなものではなく、名前でサブサービスを呼び出すことができるということです。

$myClass->doAction(array('service'=>'doActionOne','args'=>$args));

私は代わりに行うことができます:

 $myClass->doActionOne($args);

ただ重複(この例では、たくさんのだろうこれをハードコーディングするには非常に緩くコードに似ています):

public function doActionOne($array)
    {
        $this->args     =   $array;
        $name           =   __FUNCTION__;
        $this->response =   $this->executeCoreCall("APIService.{$name}");
    }

public function doActionTwo($array)
    {
        $this->args     =   $array;
        $name           =   __FUNCTION__;
        $this->response =   $this->executeCoreCall("APIService.{$name}");
    }

public function doActionThree($array)
    {
        $this->args     =   $array;
        $name           =   __FUNCTION__;
        $this->response =   $this->executeCoreCall("APIService.{$name}");
    }

protected function executeCoreCall($service)
    {
        $cURL = new \cURL();
        return $cURL->('http://3rdparty.api.com?service='.$service.'&apikey='.$this->api.'&'.http_build_query($this->args))
                    ->getResponse();
    }

しかし、__call()私は魔法の方法で動的な方法ですべてのサービスにアクセスできます:

public function __call($name, $arguments)
    {
        $this->args     =   $arguments;
        $this->response =   $this->executeCoreCall("APIService.{$name}");   
        return $this;
    }

データを返すためのこの動的な呼び出しの利点は、ベンダーが別のサブサービスを追加する場合、クラスに別のメソッドを追加したり、拡張クラスを作成したりする必要がないことです。これが役立つかどうかはわかりません。誰もが、私は、私はどこの例を示すだろう考え出し__set__get__call主な機能は、データのリターンであることから、などが検討のための選択肢かもしれません。


編集:

偶然にも、投稿の数日後にこれが私のシナリオを正確に概説しています。これは私が参照していたAPIではありませんが、メソッドのアプリケーションは同じです。

私は正しくAPIを使用していますか?


-2

更新:これは私が学習中に見つけた非常にばかげたコードであるため、この回答は使用しないでください。単純なゲッターとセッターを使用するだけです。


私は通常、その変数名を関数名として使用し、オプションのパラメーターをその関数に追加して、そのオプションのパラメーターが呼び出し元によって入力されたときに、それをプロパティに設定して$ thisオブジェクト(チェーン)を返し、そのオプションのパラメーターが呼び出し元、プロパティを呼び出し元に返すだけです。

私の例:

class Model
{
     private $propOne;
     private $propTwo;

     public function propOne($propVal = '')
     {
          if ($propVal === '') {
              return $this->propOne;
          } else {
              $this->propOne = $propVal;
              return $this;
          }
     }

     public function propTwo($propVal = '')
     {
          if ($propVal === '') {
              return $this->propTwo;
          } else {
              $this->propTwo = $propVal;
              return $this;
          }
     }
}

ここで問題は残ります:プロパティを空の文字列にどのように設定しますか?そして、プロパティを空の文字列に設定することが実際に失敗してゲッターとして機能したことをどのように検出しますか?空のフィールドを文字列として送信するHTMLフォームについて考えてみてください。そしていいえ:デフォルト値としてNULLなどの別の値を使用しても問題は解決しません。
2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.