我們有一個基於Yii的PHP應用程序,它可以在不同類型的對象上執行一些通用操作(例如與社交網絡「共享」或在內部網上商店「購買」)。如何爲查找數據庫表定義ActiveRecord,以便它與枚舉常量一樣有用?
現在開發人員使用類常量來分離不同類型的對象。像這樣:
在模式:
class Referral extends CActiveRecord {
//... a lot more stuff here...
const ITEM_TYPE_PRODUCT = 'product';
const ITEM_TYPE_DESIGN = 'design';
const ITEM_TYPE_BRAND = 'brand';
const ITEM_TYPE_INVITE = 'invite';
const ITEM_TYPE_DESIGNER = 'designer';
//... a lot more stuff here...
}
然後在一些控制器後:
// calling static method of Referral and pass a type IDs to change it's behavior
$referral_params = Referral::buildReferallParams(
Referral::TYPE_PINTEREST,
Referral::ITEM_TYPE_PRODUCT
)
類常量的這種使用導致我想移動的主要代碼重複遠。
我個人認爲,我們確實應該增加一個查找表類型,像這樣:
CREATE TABLE `item_type` (
id int primary key auto_increment,
name varchar(255)
);
而且使命名ItemType
從與表中提取ID的Yii的模型類。
但它會導致另一個問題:無論如何,我們需要在代碼中使用這種類型的ID,並且需要很長一段時間。我們需要以某種方式爲ID創建符號名稱。現在撥打電話Referral::ITEM_TYPE_PRODUCT
非常方便,將它改爲Yii-flavoured ItemType::model()->findByAttributes(array('name' => 'Product'))
是完全不能接受的。
我想避免在ItemType
中維護類常量(現在通過我們的代碼庫重複)的相同列表,因爲每增加一個新類型都需要添加新的常量,而這只是一個不同步的問題等待發生。
所以,問題如下:如何使一個查詢表的ActiveRecord與'enum'-like數字常量集一樣有用?
我想出了下面的有些漂亮的解決方案,使用的ItemType類的子類:
ProductItemType::id(); // returns lazy-loaded ID for 'Product' item type
BrandItemType::id(); // the same for 'Brand' item type
// ... and so on
但如果需要單獨的基類五個小類,現在,也許打的另一半更晚。有沒有可行的架構解決方案?
EDIT
問題的複製是這樣的:類常量聲明類型ID 成爲重新定義在每一個類這需要不同項目類型之間區分某種方式。我知道最「真實」的解決方案是顛倒這個內部結構,並將依賴於對象類型的特徵移動到對象本身,但是我們有遺留的代碼,沒有任何測試覆蓋,這個解決方案現在只是一個夢想。現在我想要做的就是刪除這個重複。也是常數。
什麼存儲在'interface'類的所有常量,這就是我們做的,我們只是在這裏我們需要使用它們的類實現。關於第二個問題,您能否詳細說明您在代碼中重複的內容,您不想要的更多示例。 – Pentium10
同意@ pentium10更清楚代碼重複。但是,如果我理解它的大部分,你的問題是如何管理你的枚舉/常量。請檢查這個[輕鬆管理常量](http://www.yiiframework.com/wiki/288/managing-constants-easily/),也許你會發現一些有用的東西。使用給定的函數,您可以將常量用作數組的任何地方(即使在驗證規則中)。 –
@ Pentium10,我添加了關於代碼重複的解釋。 – hijarian