2011-12-16 159 views
0

想象一下,你有一些對象的列表。這些對象是擴展基類的各種類的實例。 現在我想將這些對象保存在數據庫中。動態類實例:良好實踐?

作爲一個額外的要求,擴展基類的類的數量可能相當大。

它是很好的做法,類名保存爲字符串,在數據庫中,這樣取,

<?php 
class Page { 
    abstract public function foo($args); 
} 

class ChartPage : Page{ 
    public function foo($args){ 
     var_dump($args); 
    } 
} 

// other classes like ChartPage would be defined here 

// fetched row from a MySQL database 
$row = array("id" => 21, "title" => "Test", "class" => "ChartPage", "args" => "{}"); 
$object = new $row['class']; 
$object->foo($row['args']); 
?> 

是否有任何的做法去做那些以更好的方式什麼?

回答

1

除非你編寫自己的職能序列化/反序列化使用那些可原生支持PHP一個具體的理由:

你可以閱讀更多關於PHP的對象序列化的鏈接如下:

如果序列化的數據是與外界事物的PHP你可以選擇序列化的另一種方法,如JSON或XML共享。但是,如果只是稍後通過PHP存儲訪問對象的問題,標準的序列化方法已經足夠了。


某種標識必須存儲與序列化的數據,否則將無法爲您確定是什麼類型的對象確實是。

當然,我已經看到反序列化方法,其中序列化數據的鍵已被用於搜索最匹配的對象類型,但這不是我推薦的,因爲它不是100%準確的案例。


在您的示例代碼片段我認爲Page::foo被用作工廠建設新類。

如果您要編寫自己的序列化/反序列化數據的方法,並且想要存儲對象的所有數據,則不需要強制繼承Page的類來實現工廠。

Page也可以有一個統一的方法,通過循環對象包含的鍵/值對來序列化任意類。儘管這種方法存在一個小問題。

如果繼承對象具有相當複雜的成員(即不是基本的,例如用戶定義的類),那麼您可能不想完全保存它。

例如,如果一個對象有一個活動的mysql連接,你只需要存儲憑證重新打開這樣的連接,因爲你如何將連接本身存儲在序列化的數據中?

然後,再次存儲與套接字連接關聯的文件描述符,並使用假想的總是在後臺運行的MySQLKeepConnAlive對象打開它將很酷,但它通常是非常必要的。無論如何;

無論如何;如果我是你,我會爲基礎對象中的序列化/反序列化編寫一個默認方法,如果繼承的類型很複雜,則由開發人員來重寫這些方法並提供他自己的方法。

我會使用數據結構來存儲對象,如下所示,這與前面描述的並不遙遠。 '__PAYLOAD'將包含對象的成員,其他值應該在你的基類中定義。

對於不同類的兩個實例,'__PAYLOAD'看起來不會相同,但是會有一種統一的方式來加載具有特定ID和類型的對象,並找出關於該對象的基本信息。

當然,你可以添加比下面更多的「基礎」字段,這只是我想的一個例子。

$serialized_data = array (
    '__TITLE': 'Test', 
    '__TYPE': 'CharPage', 
    '__ID':   21, 
    '__PAYLOAD': array (
    'member_1' => 'foobar', 
    'member_2' => 'barbaz', 
    'member_3' => 'bazbir' 
) 
);