2017-05-23 28 views
1

考慮使用靜態構建器返回模型實例的Active Record實現。這裏是一個非常減少版本的模型構建器和模型類證明的,所有的代碼無關的問題刪除:從構建器方法調用的類型提示方法

class ModelBuilder { 
    public function __construct($class) { 
     $this->class = $class 
    } 

    private function _execute() { 
     $result = $pdo->query("SELECT * FROM {$this->class}"); 
     return $result->fetchAll(PDO::FETCH_CLASS, $this->class); 
    } 

    public function all() { 
     return $this->_execute(); 
    } 

    public function one() { 
     return $this->_execute()[0]; 
    } 
} 

class Model { 
    public static function builder() { 
     return new ModelBuilder(get_called_class()); 
    } 
} 

class FooModel extends Model { 

} 

爲了讓我們稱之爲FooModel類這樣一個Foo項目:

$foo = FooModel::builder()->one(); 

在這種情況下,智能IDE(在我的情況下PhpStorm)不知道什麼類型的對象$foo是。每次創建對象時,我都可以鍵入提示變量/** @var $foo FooModel */,但我更喜歡all()one()方法中的正確類型提示。

什麼是適當的類型提示添加到all()one()方法?請注意,static不起作用,我相信因爲ModelBuilder不是初始調用類的祖先,並且它在builder()方法中被明確調用。

這個特定的項目使用PHP 5.6,但也歡迎PHP 7特定的答案。

+1

你不能。增加這一推薦是唯一可行的選擇。當然,我也會建議從活躍記錄的反模式中保持樂觀,但這只是我關於OOP和SRP的愚蠢概念。 –

回答

1

如果你的模型具有父類一樣BaseModel - 你可以返回塊使用BaseModel DOC塊內的allone方法,如:

/** 
* @return BaseModel Model instance. 
*/ 
public function one() { 
    return $this->_execute()[0]; 
} 

但在這種情況下 - 它只是BaseModel這是不FooModel也不BooModel ...
你將只能訪問BaseModel方法和屬性,而不是具體的FooModel ...

隨着目的有一定的模型 - ÿ OU已覆蓋所需的方法與適當的文檔塊子模型,如:

class FooModel extends BaseModel 
{ 
    /** 
    * @return FooModel Foo model instance. 
    */ 
    public function one() { 
     return parent::one(); 
    } 
} 

或者有doc塊類,像這樣:

/** 
* @method FooModel one Foo model instance. 
*/ 
class FooModel extends BaseModel 
{ 
} 

或者使用DOC塊/** @var $foo FooModel */喜歡你」已經提到過。

+0

謝謝。實際上,我正在尋找一種方法來獲得'FooModel'屬性,而不僅僅是'Model'的屬性,並且我想避免在每個擴展類中重寫僅用於提示類型的方法。我想這不是重寫就是我必須堅持doc塊。 – dotancohen

+0

我已經更新了我的答案,添加了示例'@method FooModel one Foo model instance.'您可以爲'FooModel'類設置此塊,因此您不必重寫'one'方法。 –

+0

感謝您的更新,我不知道課堂上的'@ method' typehinting。太好了!然而,這裏不起作用,因爲'one()'是'ModelBuilder'類的一個方法,而不是'Model'。 – dotancohen