OOP PHP新手,指导请求,类间数据共享设计



用PHP编写我的第一个使用类和对象的应用程序。我有一个DB类,它使用一个字符串来选择适当的配置,因为有多个数据库。我一开始是用一个登录类,但为了交换一个用户类,我放弃了这个想法,这样我就可以做user->isLoggedIn之类的事情。user类使用MySQL,MySQL存储用户和登录信息,以及第二个数据库的凭据。

$mysql = new db( 'mysql' );
$user = new user( $mysql );
if( !( $user->isLoggedIn() === true ) )
{
goToPage( 'login.php' );
exit();
}

第二个数据库是Sybase,用于存储帐户信息。我需要来自用户类的凭据来从这里获取列表和帐户信息。我认为下一个应该是账户类,但不确定最好的方法。也许是这样的。。

$sybase = new db( 'sybase' );
$account = new account( $sybase );
$account_list = $account->getList( $user->info );

$user->info是帐户表所需的凭据和信息的数组,或者有更好的方法吗?

编辑以包括数据库类示例

config.db.php

$config_array = array();
$config_array[ 'mysql' ][ 'dsn' ] = "mysql:host=localhost;dbname=********;charset=UTF-8";
$config_array[ 'mysql' ][ 'user' ] = "********";
$config_array[ 'mysql' ][ 'pass' ] = "**************";
$config_array[ 'sybase' ][ 'dsn' ] = "odbc:DRIVER={Adaptive Server Anywhere 8.0};***************";
$config_array[ 'sybase' ][ 'user' ] = "**********";
$config_array[ 'sybase' ][ 'pass' ] = "*********";

class.db.php

public function __construct( $type )
{
require 'config.db.php';
$this->type = $type;
foreach( $config_array[ $this->type ] AS $key => $value )
{
$this->$key = $value;
}
try
{
$this->connection = new PDO( $this->dsn, $this->user, $this->pass, $this->options );
}
catch( PDOException $ex )
{
log_action( "db->" . $this->type, $ex->getCode() . ": " . $ex->getMessage() );
$this->error = true;
}
return $this->connection;
}

以下内容有意义吗?

class User()
{
public function getAccountList()
{
$this->Account = new Account( new Database( 'sybase' ) );
return $this->Account->list( $this->userid );
}
}

此外,账户有不同的部分(即历史记录和注释、财务交易、文档),这些部分将是页面上不同的"选项卡"。它们中的每一个也应该是一个类吗?

首先,作为Dimitry对另一个答案的次要回答:

拥有辛格尔顿,你将获得的东西与你失去的东西相比相形见绌。您得到了一个全局对象,程序的每个部分都可以读取和修改该对象,但您失去了可测试性、可读性和可维护性。

因为Singleton对象实际上是全局的,所以您无法准确地隔离应用程序中的单个单元(这对单元测试至关重要),因为您的功能依赖于其他组件,这些组件被"神奇地"插入其中

您失去可读性是因为method()实际上可能需要其他东西才能工作(例如,user对象需要一个db实例,这使得new user($db)new user()可读得多,因为即使不看源代码,我也可以判断出方法/对象需要什么工作。

由于上述原因,您也会失去可维护性。与在函数的"契约"中看到它相比,更难判断哪些组件是通过Singleton插入的,因此,未来的您和/或任何其他开发人员都更难阅读和重构您的代码。


顺便说一句,用第一个字母大写来命名Class名称被认为是一种很好的命名约定,从现在起我将使用这种约定。

让我们从头开始。Db对象有两种可能的状态:MysqlDbSybaseDb。这就需要多态性。您有一个抽象Db,以及从中继承的两个concrete类MysqlDbSybaseDb。正确Db对象的实例化由工厂负责

class DbFactory {
private $db;
/**
* Create a new Db object base on Type, and pass parameters to it.
*
* @param string $type Type of database, Mysql or Sybase.
* @param string $dsn  The DSN string corresponding to the type.
* @param string $user User credential
* @param string $pass Password credential
*
* @return Db
*/
public function create($type, $dsn, $user, $pass) {
if (!is_a($this->db, "Db")) {
$type     = $type . "Db";
$this->db = new $type($dsn, $user, $pass);
}
return $this->db;
}
}
abstract class Db {
/**
* @param $dsn
* @param $user
* @param $pass
*/
public function __construct($dsn, $user, $pass) {
$this->db = new PDO("$dsn", $user, $pass);
$this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}
}
class MysqlDb extends Db {
/*
* More specific, Mysql only implementation goes here
*/
}
class SybaseDb extends Db {
/*
* More specific, Sybase only implementation goes here
*/
}

现在你应该问问自己,谁负责获得账户列表?当然,它们不应该自己获取数据(就像用户没有责任从数据库中获取自己的数据一样)。User负责使用SybaseDb连接来获取这些帐户。

事实上,User需要以下功能才能工作:

  • Sybase数据库连接-以获取帐户列表。我们将把DbFactory实例传递给它,这样,如果实例已经实例化,我们就可以很容易地获得它,如果还没有实例化,我们也可以实例化它
  • 状态信息(登录状态、用户ID、用户名等)

User不负责设置此数据,它需要才能工作。

因此User构造函数应该是这样的(假设"ID"one_answers"name"字段):

User::__construct($id, $name, DbFactory $factory);

User将有一个字段$accounts,它将包含一个Account对象数组。该数组将使用User::getAccounts()方法填充。

我会让Account成为User类的成员。"用户帐户",对吗?

另外,在谈到类时,请确保您的两个DB是singletone,并通过getInstance()而不是__construct()获取它们。

最新更新