簡體   English   中英

如何拆分 PHP 類以分隔文件?

[英]How to split a PHP class to separate files?

我想做一些類似於 Objective-C 中的類類別的事情,在一個文件中定義一個類,在那里實現一些核心方法,然后在另一個沒有子類化或接口的情況下實現一些輔助方法,只需“繼續”這個類。

在 PHP 中可能嗎?

從 PHP 5.4 開始,您可以使用Traits完成此操作。 引用官方文檔:

特性 [使] 開發人員能夠在位於不同類層次結構中的幾個獨立類中自由地重用方法集。 [...] Trait 類似於類,但僅用於以細粒度和一致的方式對功能進行分組。 不可能單獨實例化 Trait。 它是對傳統繼承的補充,可以實現行為的橫向組合; 也就是說,類成員的應用不需要繼承。

使用 trait 允許您將解決橫切關注點的輔助方法存儲在一個中心位置,並在您需要的任何類中使用這些方法。

// File "HelperMethodTrait.php"
trait HelperMethodTrait
{
    public function myIncredibleUsefulHelperFunction()
    {
        return 42;
    }
}

// File "MyClass.php"
class MyClass
{
    use HelperMethodTrait;

    public function myDomainSpecificFunction()
    {
        return "foobar";
    }
}

$instance = new MyClass();
$instance->myIncredibleUsefulHelperFunction(); // 42

先驗的 PHP 不會通過語言構造為您提供此功能,整個類必須在單個文件中。

現在有一些技巧可以做這些事情,它們對 CPU 的要求非常高:

例如,您可以在不同文件之間分離您的類,然后加載文件並使用整個代碼構建單個字符串,然后執行 eval(string) 來解釋類並將它們構建到可運行的代碼區域中。

順便說一句,這不是一個好主意,原因有很多

如果您的唯一目標是使類定義文件更小,則可以在函數定義中包含文件

class MyClass {
    public function doStuff($foo,$bar) {
        global $quz;
        include('MyClass.doStuff.php');
    }
}

在包含中,您的本地范圍適用(將定義 $foo、$bar 和 $quz)

我不確定開銷是什么 - 包含似乎發生在運行時,而不是編譯時(因為包含實際上可以返回一個值 ..)

2 美分,*-派克

我認為你最好按照功能標准將你的類分成 n 個部分,然后使用依賴注入模式在 B 的構造函數中將 A 類“注入”到 B 類中,而不需要子類化/接口。

您可以使用此方法向外部的某些對象添加函數,這與向類本身添加方法不同。

https://stackoverflow.com/a/2938020/2277620

另一個不太好的方法是創建多個子類,因此每個級別的子類只添加一個“組”函數。

我在一個類超過 10k 行的情況下使用了這個技巧。

現在我有 6 個繼承級別,其中每個級別都添加了一個“上一級”類的函數“類別”。

沒那么耗cpu,難看,沒那么難維護

這在很大程度上取決於您希望實現的目標。 我有一個聰明的主意做你想做的事。 我喜歡關鍵字 set、get run delete 等。假設有一個類,我想要 set 刪除。 正如 Ph.T 指出的那樣,類需要在單個文件中

所以在一個文件中制作 abc->set 而在另一個文件中制作 abc->get 沒有任何用處和意義。

因此,不得不重新思考並將類視為微服務,執行按功能分解的特定任務。

解決方案使用名稱間距。

        namespace A;
    class Get{public static function myCode(){}
public static function myAnotherCode(){}}

這將被稱為 A\\Get::myCode(); 或 A\\Get::myAnotherCode(); 同樣設置將是

        namespace A;
    class Set{public static function myCode(){}
public static function myAnotherCode(){}}

這將被稱為 A\\Set::myCode(); 或 A\\Set::myAnotherCode();

然后用戶 spl_autoload_register 加載類記得用 / 替換 \\

spl_autoload_register(function ($class) {
 require_once __DIR__ . '/' . strtolower(str_replace('\\', '/', $class) . '.php')
});

和目錄結構如下

main (folder)
--  A (folder)
    --  set.php (file)
    --  get.php (file)

我們要求 A\\Get::myCode() 需要將其視為 A/Get.php 然后運行其邏輯,無論它是正確的名稱空間還是類等。

如果計划得當,它的好處是它會迫使您以合乎邏輯的方式運行,而不僅僅是隨處可見。 其次,您只會加載您需要的功能,而不僅僅是一堆這樣那樣的東西。

不利的是,類的兩個部分不會在它們之間共享,除非一個從另一個擴展一個,這將違反整個邏輯,因為另一個將因此以任何方式加載。

必須仔細否定哪些邏輯和規划數據將被共享,並且必須事先制定。

namespace A;
class Universal {
protected static $share_one;
protected static $share_two;
}

namespace A;
class Set extends Universal {
public static function myCode(){ parent::$share_one ='wow';}
}

namespace A;
class Get extends Universal {
public static function myCode(){ return parent::$share_one;}
    }

    main (folder)
    --  A (folder)
        --  universal.php (file)
        --  set.php (file)
        --  get.php (file)

運行代碼,看看魔術

 A\Set::myCode();
 echo  A\Get::myCode();  

如果您只需要一組功能,例如 get 那么只需使用 get echo A\\Get::myCode(); 將工作沒有錯誤。

老實說,如果不玩名稱空間,那只是浪費時間而頭疼。 旁注:如果做得對,它可以加快速度,因為通用類不會加載兩次。 即使調用了無數次我們想要加載默認值,然后在我們需要的地方填充它們。 我已經制作了大量的類,除了默認值外,只需要很少的函數,其余的只是內存負載。 打破只是加速事情。

暫無
暫無

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

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