我有一个中型MVC应用程序。应用程序的用例是这样的,我需要更多地控制用于与我的数据库交互的SQL(除其他外,数据是高度规范化的,我们使用大量的连接)。所以,我已经为模型增加了自己的设计,而不是使用Doctrine或Eloquent或其他任何东西。我最近发现我的设计被称为Table Data Gateway模式。无论如何,它看起来像这样(为了清晰起见,简化了一点):
我们有一个抽象类,我的所有TableGateways都扩展了。它知道如何与PDO交谈并做SQL的事情,但不知道任何特定的表:
abstract class TableGateway {
protected $db = null;
public $tableName = '';
public $outputClass = null;
function __contruct(\PDO $pdo) {
$this->db = $pdo;
}
/**
* $return \StdClass[]
*/
function all() {
$result = $this->query(sprintf('SELECT * FROM %s',$this->tableName));
return $result;
}
/**
* @param $query
* @param array $params
* @return \StdClass[]
*/
public function query($query, $params = array()) {
$stmt = $this->db->prepare($query);
if($this->outputClass) {
$stmt->setFetchMode(PDO::FETCH_CLASS, $this->outputClass);
} else {
$stmt->setFetchMode(PDO::FETCH_OBJ);
}
$success = $stmt->execute($params);
return $stmt->fetchAll();
}
}
然后每个表都有一个网关类,它扩展父类并应用特定于表的东西。这里将会有许多函数调用$this->query()
,使他们对表结构的了解构建一个有用的查询,但也有一些基本函数,如PostsGateway::all()
,每个函数都是相同的表,所以他们住在父类。
class PostsGateway extends TableGateway {
public $tableName = 'posts';
public $outputClass = 'Post';
}
查询的每个结果都会加载到一个对象中。默认情况下,它们只是StdClass对象,但您可以指定备用$this->outputClass
以使其在其他类中输出,如下所示:
class Post {
/** @var int $id */
/** @var string $content */
}
这一切对我来说都很有效。但是,我的IDE无法跟上。您和我知道PostsGateway::all()
将返回一个数组Post
对象,但IDE认为它只是一个常规数组。这意味着我不会自动完成Post
对象属性的提示。
有没有人知道任何解决这个问题的聪明方法,那么IDE会知道这个变化吗?
我正在考虑一个自动为PostsGateway
生成文档块的脚本,但我总是对代码生成小问题,尤其是我将要定期修改的类中的代码。该脚本必须根据TableGateway
的更改定期更新文档块,而不是弄乱我添加到PostsGateway
的任何内容。
还有其他很酷的方法来解决这个问题吗?或者你能推荐一些好的库来生成这些代码块吗?