簡體   English   中英

是否可以覆蓋PHP中的函數

[英]Is it possible to overwrite a function in PHP

你能宣布一個這樣的函數......

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

然后重新宣布它有點像這樣......

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

是否有可能以這種方式覆蓋一個函數?

無論如何?

編輯

為了解決這些答案沒有直接解決原始問題的評論。 如果您從Google搜索到達此處,請從此處開始

有一個名為override_function的函數實際上適合賬單。 但是,鑒於此函數是高級PHP調試器擴展的一部分,因此很難創建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();

名稱空間php> = 5.3中的猴子補丁

比修改解釋器更少回避的方法是猴子補丁。

猴子修補是用你自己的類似“補丁”取代實際實現的藝術。

忍者技能

在你像PHP忍者一樣修補補丁之前,我們首先要了解PHP的命名空間。

從PHP 5.3開始,我們引入了名稱空間,你可能乍一看它們可能等同於java包這樣的東西,但它們並不完全相同。 PHP中的命名空間是一種通過創建焦點層次結構來封裝范圍的方法,尤其是對於函數和常量。 作為這個話題, 回歸全球功能 ,旨在解釋。

如果在調用函數時沒有提供命名空間 ,PHP首先查找當前命名空間,然后向下移動層次結構,直到找到在該前綴命名空間內聲明的第一個函數並執行該命名空間。 對於我們的示例,如果您正在調用print_r(); 來自namespace My\\Awesome\\Namespace; PHP的作用是首先查找名為My\\Awesome\\Namespace\\print_r();的函數My\\Awesome\\Namespace\\print_r(); 然后My\\Awesome\\print_r(); 然后My\\print_r(); 直到它在全局命名空間\\print_r();找到PHP內置函數\\print_r();

您將無法在全局命名空間中定義function print_r($object) {} ,因為這將導致名稱沖突,因為具有該名稱的函數已存在。

預計會出現致命錯誤:

Fatal error: Cannot redeclare print_r()

但是,沒有什么能阻止你在命名空間范圍內做這件事。

修補猴子

假設你有一個使用幾個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!

看看override_function來覆蓋這些函數。

override_function - 覆蓋內置函數

例:

override_function('test', '$a,$b', 'echo "DOING TEST"; return $a * $b;');

簡短的回答是否定的,你不能在PHP函數范圍內覆蓋一個函數。

你最好使用這樣的匿名函數

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

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

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

您無法在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;');

我將一個案例的所有功能都包含在一個include文件中,而另一個include在另一個案例中。

例如, simple.inc將包含function boofoo() { simple }really.inc將包含function boofoo() { really }

它有助於程序的可讀性/維護,在同一個inc具有相同類型的所有功能。

然后在主模塊的頂部

  if ($_GET['foolevel'] == 10) {
    include "really.inc";
  }
  else {
    include "simple.inc";
  }

您可以使用PECL擴展

但在我看來這是不好的做法。 您正在使用函數,但請查看Decorator設計模式 可以借用它的基本思想。

不,這將是一個問題。 PHP變量函數

對於相關案例的解決方案,您有一個包含文件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() ”。

根據您需要的情況,也許你可以使用這樣的匿名函數:

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

$greet('World');

...然后您可以隨時為給定變量設置新功能

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM