78

このような関数を宣言できますか...

function ihatefooexamples(){
  return "boo-foo!";
};

そして、このように再宣言します...

if ($_GET['foolevel'] == 10){
  function ihatefooexamples(){
    return "really boo-foo";
  };
};

そのように関数を上書きすることは可能ですか?

ともかく?

4

10 に答える 10

110

編集

この回答が元の質問に直接対処していないというコメントに対処するため。Google検索からここにアクセスした場合は、ここから始めてください

実際に法案に適合するoverride_functionと呼ばれる利用可能な関数があります。ただし、この関数はAdvanced PHP Debugger拡張機能のoverride_function()一部であるため、実稼働での使用を目的とした引数を作成することは困難です。したがって、「いいえ」と言いますが、元の質問者が念頭に置いていた意図で関数を上書きすることはできません。

元の回答

ここで、OOP、特にポリモーフィズムを利用する必要があります。

interface Fooable
{
    public function ihatefooexamples();
}

class Foo implements Fooable
{
    public function ihatefooexamples()
    {
        return "boo-foo!";
    }
}

class FooBar implements Fooable
{
    public function ihatefooexamples()
    {
        return "really boo-foo";
    }
}

$foo = new Foo();

if (10 == $_GET['foolevel']) {
    $foo = new FooBar();
}

echo $foo->ihatefooexamples();
于 2010-09-01T17:46:01.673 に答える
84

名前空間phpのモンキーパッチ>=5.3

インタプリタを変更するよりも回避の少ない方法は、モンキーパッチです。

モンキーパッチは、実際の実装を独自の同様の「パッチ」に置き換える技術です。

忍者スキル

PHP忍者のようにモンキーパッチを適用する前に、まずPHPの名前空間を理解する必要があります。

PHP 5.3以降、一見するとJavaパッケージのようなものと同等であると思われる名前空間が導入されましたが、まったく同じではありません。PHPの名前空間は、特に関数と定数のフォーカスの階層を作成することにより、スコープをカプセル化する方法です。このトピックとして、グローバル関数へのフォールバックは、説明することを目的としています。

関数を呼び出すときに名前空間を指定しない場合、PHPは最初に現在の名前空間を調べ、次にそのプレフィックス付き名前空間内で宣言された最初の関数を見つけてそれを実行するまで階層を下に移動します。print_r();この例では、PHPが行うことから呼び出している場合namespace My\Awesome\Namespace;、最初に呼び出された関数を探し、次にMy\Awesome\Namespace\print_r();グローバル名前空間でPHP組み込み関数が見つかるまで探します。My\Awesome\print_r();My\print_r();\print_r();

function print_r($object) {}その名前の関数がすでに存在するため、名前の衝突が発生するため、グローバル名前空間でを定義することはできません。

次のようなものに致命的なエラーが発生する可能性があります。

Fatal error: Cannot redeclare print_r()

ただし、名前空間の範囲内でそれを実行することを妨げるものは何もありません。

サルにパッチを当てる

複数のprint_r();呼び出しを使用するスクリプトがあるとします。

例:

<?php
     print_r($some_object);
     // do some stuff
     print_r($another_object);
     // do some other stuff
     print_r($data_object);
     // do more stuff
     print_r($debug_object);

しかし、後で気が変わって、<pre></pre>代わりに出力をタグでラップする必要があります。あなたに起こったことはありますか?

行く前に、すべての呼び出しを変更して、print_r();代わりにモンキーパッチを検討してください。

例:

<?php
    namespace MyNamespace {
        function print_r($object) 
        {
            echo "<pre>", \print_r($object, true), "</pre>"; 
        }

        print_r($some_object);
        // do some stuff
        print_r($another_object);
        // do some other stuff
        print_r($data_object);
        // do more stuff
        print_r($debug_object);
    }

スクリプトはMyNamespace\print_r();グローバルの代わりに使用するようになります\print_r();

ユニットテストのモックに最適です。

nJoy!

于 2012-08-26T06:13:24.353 に答える
25

override_function関数をオーバーライドする方法を見てください。

override_function —組み込み関数をオーバーライドします

例:

override_function('test', '$a,$b', 'echo "DOING TEST"; return $a * $b;');
于 2010-09-01T17:36:33.487 に答える
14

簡単な答えはノーです。PHP関数スコープに入ると関数を上書きすることはできません。

そのような無名関数を使用するのが最善です

$ihatefooexamples = function()
{
  return "boo-foo!";
}

//...
unset($ihatefooexamples);
$ihatefooexamples = function()
{
   return "really boo-foo";
}

http://php.net/manual/en/functions.anonymous.php

于 2010-09-01T17:37:07.993 に答える
11

PHPで関数を再宣言することはできません。ただし、それらをオーバーライドすることはできます。必要に応じて、オーバーライドする関数を保存するために、関数のオーバーライド名前の変更を確認してください。

したがって、関数をオーバーライドすると、関数が失われることに注意してください。あなたはそれを維持することを検討したいかもしれませんが、別の名前で。ただ言って。

また、これらがオーバーライドしたいクラスの関数である場合は、rename_functionとoverride_functionを実行せずに、サブクラスを作成してクラス内の関数を再宣言する必要があります。

例:

rename_function('mysql_connect', 'original_mysql_connect' );
override_function('mysql_connect', '$a,$b', 'echo "DOING MY FUNCTION INSTEAD"; return $a * $b;');
于 2010-09-01T17:41:46.250 に答える
5

あるケースのすべての関数をincludeファイルに含め、他の関数を別のケースに含めますinclude

たとえば、simple.inc含まれ、含まfunction boofoo() { simple }really.incますfunction boofoo() { really }

それはあなたのプログラムの読みやすさ/メンテナンスを助け、同じ種類のすべての機能を同じに持っていますinc

次に、メインモジュールの上部にあります

  if ($_GET['foolevel'] == 10) {
    include "really.inc";
  }
  else {
    include "simple.inc";
  }
于 2010-09-01T17:41:22.527 に答える
3

PECL拡張機能を使用できます

しかし、それは私の意見では悪い習慣です。関数を使用していますが、デコレータのデザインパターンを確認してください。それから基本的な考え方を借りることができます。

于 2010-09-01T17:40:54.507 に答える
1

いいえ、これは問題になりません。 PHP変数関数

于 2010-09-01T17:36:08.167 に答える
1

これが必要な状況に応じて、次のような匿名関数を使用できます。

$greet = function($name)
{
    echo('Hello ' . $name);
};

$greet('World');

...その後、いつでも指定された変数に新しい関数を設定できます

于 2017-09-02T03:02:13.293 に答える
1

編集可能なインクルードファイルAがあり、インクルードファイルB(またはメインファイル)内のその機能の一部をオーバーライドしたい場合の関連ケースの解決策:

メインファイル:

<?php
$Override=true; // An argument used in A.php
include ("A.php");
include ("B.php");
F1();
?>

インクルードファイルA:

<?php
if (!@$Override) {
   function F1 () {echo "This is F1() in A";}
}
?>

インクルードファイルB:

<?php
   function F1 () {echo "This is F1() in B";}
?>

メインファイルを参照すると、「これはBのF1()です」と表示されます。

于 2018-10-22T15:49:20.810 に答える