Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
数据库对象类PHP_Php_Database_Oop - Fatal编程技术网

数据库对象类PHP

数据库对象类PHP,php,database,oop,Php,Database,Oop,我最近做了一些项目,使用了一个数据库对象超类,用于快速的一次性查询/更新,并使用适当的类(如用户类)进行扩展 我发现我正在编写的许多类都有完全相同的方法:query_values()、update()、delete()等等 所以我提出了一个类,它的构造函数如下所示: public function __construct($table, $db_object, $record_id = null){ $this->db = $db_object; // Database objec

我最近做了一些项目,使用了一个数据库对象超类,用于快速的一次性查询/更新,并使用适当的类(如用户类)进行扩展

我发现我正在编写的许多类都有完全相同的方法:query_values()、update()、delete()等等

所以我提出了一个类,它的构造函数如下所示:

public function __construct($table, $db_object, $record_id = null){
    $this->db = $db_object; // Database object with query methods

    $this->table = $table; // The name of the database table

    $this->get_column_data();

    if(!is_null($record_id)){
        // This retrieves all column values, 
        // stores into private $fields array property
        $this->query_values($record_id);
    }
}
public function __construct($db_object, $record_id = null){
    parent::__construct($this->table, $db_object, $record_id);
}
子类构造函数如下所示:

public function __construct($table, $db_object, $record_id = null){
    $this->db = $db_object; // Database object with query methods

    $this->table = $table; // The name of the database table

    $this->get_column_data();

    if(!is_null($record_id)){
        // This retrieves all column values, 
        // stores into private $fields array property
        $this->query_values($record_id);
    }
}
public function __construct($db_object, $record_id = null){
    parent::__construct($this->table, $db_object, $record_id);
}
其中$table属性在顶部定义,因为我们应该知道这个特定对象使用哪个表

现在,所有常见的记录管理方法都在一个地方,特定于该类的方法都是在各自的子类中定义的

我在这里看到的最大缺点是,所有数据字段都被拉入并封装在$fields属性中,因此需要定义泛型get和set方法(我通常这样做),这几乎否定了封装*,或者必须为我们要公开的每个属性专门定义一个方法

*例如: $user\u id=$user->id;//不使用我的方法 vs。 $user\u id=$user->\u get('id');//访问$User->fields['id']


你认为这是缺点还是优点?其目标是易于使用,面向对象(封装),并且只是简单的令人敬畏

通过在对象上实现一些功能,您可以实现两个方面的最佳效果。例如,通过实现
\uuu get
\uu set
\uu isset
可以使属性访问看起来“自然”(例如
$user->id
),同时不必在每个单独的子类中定义属性

例如,的实现可以在运行时检查
$fields
成员,以查看您尝试获取的属性是否对特定对象类有效。您可以在基类中编写此通用实现一次,只需相应地填充
$fields
,即可使其适用于任何类型的对象。这实际上是所有现代映射工具所做的,包括您可能听说过的所有PHP框架


另外,我希望您在
get\u column\u data
中缓存每个类的表模式。每次构造相应类的对象时,为同一个表的模式重新查询数据库是非常低效的。

好吧,您可以轻松地使用PHP的magic overloading
\uu call
方法来创建通用的getter和setter。您可以将以下方法添加到“数据库对象超类”:

让我解释一下这里发生了什么。magic
\u call
方法将接收对任何与对象的具体方法之一不匹配的对象方法的调用。它接收被调用方法的名称及其参数数组作为参数

上面的
\u调用
方法会快速执行
substr
检查该方法是“getter”还是“setter”(使用方法名称的前三个字母)。它要求
$fields
数组存储小写的“属性”名称(
lcfirst
),并使用setter/getter前缀后面的所有内容作为预期的属性名称

如果某个属性与getter方法匹配,则返回该属性。如果不是,则抛出SplException
BadMethodCallException
。这是自PHP中包含Spl异常以来的最佳实践

同样,如果没有指定参数,setter方法也将抛出spleexception
InvalidArgumentException


PHP的神奇方法将改变你的生活。您还可以使用
\uuu get
\uu set
以类似的方式分配
$字段
数组值,而无需进行假方法调用。兴奋起来:)

有两种主要方法:

PHP文件创建 我知道的所有大型ORM/数据库项目都不允许用户自己编写所有getter方法。当您调用命令行脚本时,使用自动生成器和getter方法创建真正的PHP文件。这些文件包含所谓的基类方法,这些方法由您将自己的代码放入的某些类自动扩展(因此,重新创建基类不会删除您自己的代码)

文件创建的优点是您有一个定义良好的接口(有些人不喜欢在源代码中无法直接看到可调用方法时使用它)

神奇方法/重载 我在客户端应用程序中看到的一个数据库引擎使用了神奇的方法来模拟getter和setter。您可以使用神奇的方法
\uuu get()
\uu set()
\uu call()
(调用)来实现此目的。使用哪种方法取决于您希望如何访问值(最常见的
$obj->property
$obj->getProperty()


重载的优点是不需要编写复杂的PHP代码生成器,也不需要在每次更改数据库设计时调用命令行脚本。

成就解锁:直观地实现@Gordon-谢谢Gordon,这验证了我的想法!