在PHP中编写我的第一个应用程序,它使用类和对象.我有一个DB类,它接受一个字符串来选择适当的配置,因为有多个数据库.我从一个登录类开始,但是为了交换用户类而划掉了这个想法,所以我可以做user-> isLoggedIn.用户类使用MySQL来存储用户和登录信息,以及第二个数据库的凭据.
$mysql = new db( 'mysql' );
$user = new user( $mysql );
if( !( $user->isLoggedIn() === true ) )
{
goToPage( 'login.php' );
exit();
}
Run Code Online (Sandbox Code Playgroud)
第二个数据库是Sybase并存储帐户信息.我需要来自用户类的凭据才能从此处获取列表和帐户信息.我认为一个帐户类应该是下一个但不确定最好的方法.这样的事可能......
$sybase = new db( 'sybase' );
$account = new account( $sybase );
$account_list = $account->getList( $user->info );
Run Code Online (Sandbox Code Playgroud)
$ user-> info是一个数组,我猜测帐户表所需的凭据和信息,还是有更好的方法来解决这个问题?
编辑包含db类示例
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' ] = "*********";
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
像下面这样的东西有意义吗?
class User()
{
public function getAccountList()
{
$this->Account = new Account( new Database( 'sybase' ) );
return $this->Account->list( $this->userid );
}
}
Run Code Online (Sandbox Code Playgroud)
此外,帐户有不同的部分(即历史和笔记,财务交易,文档),这些部分将在页面上显示不同的"标签".每个人都应该成为一个班级吗?
首先,作为 Dimitry 另一个答案的次要答案:
拥有 Singleton 所获得的东西与你失去的东西相比显得苍白无力。你得到了一个全局对象,程序的每个部分都可以读取和修改它,但你失去了可测试性、可读性和可维护性。
因为 Singleton 对象实际上是全局的,所以您无法准确地隔离应用程序中的单个单元(这对于单元测试至关重要),因为您的函数依赖于其他组件,而这些组件“神奇地”插入了其中。
您失去了可读性,因为method()实际上可能需要其他东西才能工作(例如,user对象需要一个db实例,这new user($db)比 更具可读性new user(),因为即使不查看源代码,我也可以知道方法/对象需要什么工作。
由于上述原因,您也会失去可维护性。与在函数的“契约”中看到相比,通过 Singleton 插入哪些组件更难,因此,将来您和/或任何其他开发人员将更难阅读和重构您的代码。
附带说明一下,
Class用首字母大写命名名称被认为是很好的命名约定,从现在开始我将使用此约定。
让我们从顶部开始。您的Db对象有 2 种可能的状态,MysqlDb和SybaseDb。这就需要多态性。您有一个抽象类Db和两个具体类MysqlDb并SybaseDb从它继承。正确的 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
*/
}
Run Code Online (Sandbox Code Playgroud)
现在您应该问自己,谁负责获取帐户列表?当然,它们不应该获取自己(就像用户没有责任从数据库获取自己的数据一样)。使用连接User获取这些帐户是的责任。SybaseDb
事实上,需要User满足以下条件才能工作:
DbFactory实例传递给它,这样我们就可以轻松地获取该实例(如果它已经实例化),如果没有则实例化它。不User负责设置此数据,它需要它才能工作。
所以User构造函数应该如下所示(假设“ID”和“name”字段):
User::__construct($id, $name, DbFactory $factory);
Run Code Online (Sandbox Code Playgroud)
将User有一个字段$accounts,其中包含一个对象数组Account。该数组将填充一个User::getAccounts()方法。