如何在php项目中连接多个数据库

How to connect multiple database in php project

提问人:Liton Mazumder 提问时间:4/5/2023 最后编辑:ShadowLiton Mazumder 更新时间:4/5/2023 访问量:106

问:

我正在尝试连接我的项目中的多个数据库。由于我使用的是单个数据库并且它工作正常,现在我想在我现有的项目中连接多个 2 或 3 个数据库,这对我很有帮助。请参阅下面我现有的项目代码,以便更好地理解:

include_once(dirname(__FILE__) . '/config.php');

Class Database{
 public $host   = DB_HOST;
 public $user   = DB_USER;
 public $pass   = DB_PASS;
 public $dbname = DB_NAME;
 
 
 public $link;
 public $error;
 
 public function __construct(){
  $this->connectDB();
 }
 
private function connectDB(){
 $this->link = new mysqli($this->host, $this->user, $this->pass, 
  $this->dbname);
 if(!$this->link){
   $this->error ="Connection fail".$this->link->connect_error;
  return false;
 }
 }
}

这是config.php文件,我将在其中提供我的多个数据库连接凭据。因此,现在这里是我正在使用的单一信息。

define("DB_HOST", "localhost");
define("DB_USER", "user");
define("DB_PASS", "pass");
define("DB_NAME", "db");

我还有另一个文件名叫做 main.php 所有查询操作函数都写在其中。示例代码如下:

include_once(dirname(__FILE__) . '/database.php');

    class Model
    {
        private $db;
    
        public function __construct()
        {
            
            $this->db = new Database();
        }
        public function employee_list()
        {
            $query = "SELECT * FROM emp_list ORDER BY emp_id DESC";
    
            return mysqli_query($this->db->link,$query);
        }
    }

现在我想用这个现有项目添加多个数据库,所以你能告诉我这段代码中需要更新什么吗?谢谢

php oop mysqli

评论

1赞 Professor Abronsius 4/5/2023
您已经使用全局常量声明了类的公共属性(用户名,密码等),而不是将它们作为变量提供给构造函数,并且您以后无法重新定义常量,因此您可能希望查看另一种方法?Database
0赞 droopsnoot 4/5/2023
我会修改您的类以接受数据库连接详细信息作为参数,然后在每次创建该类的新对象时传递它们。比如每次都用不同的参数重复。Database$this->db1 = new Database(connection details)
0赞 Liton Mazumder 4/5/2023
但是我每次都把我的连接细节写成参数,我想把我的连接保存在一个文件中,这样我就可以在需要时从那里更改它。可能吗?
0赞 Professor Abronsius 4/5/2023
不同的数据库是否使用不同的凭据(用户名、密码等)?
0赞 Liton Mazumder 4/5/2023
是的,我将config.php每个数据库的文件上包含不同的凭据。

答:

0赞 Eyad Mohammed Osama 4/5/2023 #1

由于您已经使用默认值初始化了类中的数据成员,因此您可以选择性地让构造函数接受连接参数,例如:Database

class Database
{
    public $host   = DB_HOST;
    public $user   = DB_USER;
    public $pass   = DB_PASS;
    public $dbname = DB_NAME;


    public $link;
    public $error;

    public function __construct(
        $host = NULL,
        $user = NULL,
        $pass = NULL,
        $dbname = NULL
    )
    {
        $this->host = $host ?? $this->host;
        $this->user = $user ?? $this->user;
        $this->pass = $pass ?? $this->pass;
        $this->dbname = $dbname ?? $this->dbname;
        
        $this->connectDB();
    }

    private function connectDB()
    {
        $this->link = new mysqli(
            $this->host,
            $this->user,
            $this->pass,
            $this->dbname
        );
        if (!$this->link) {
            $this->error = "Connection fail" . $this->link->connect_error;
            return false;
        }
    }
}

这样,只有更改的值才会更新,因此,如果同一主机上有两个数据库,则只需传递参数而保持其他数据库不变。$dbname

$connection_1 = new Database();
$connection_2 = new Database(dbname: "my_other_database");

另一种解决方案是保持原始代码不更改它,但每次都包含不同的配置文件,它仍然可以正常工作。

评论

0赞 Liton Mazumder 4/5/2023
@EyadMohammedOsama 我需要将连接详细信息作为参数吗?我需要config.php文件,然后我该如何使用它。
0赞 Eyad Mohammed Osama 4/5/2023
@LitonMazumder 如果将连接详细信息作为参数传递,则将获得一种动态方法,该方法允许您根据条件(例如)实例化数据库连接。如果您不喜欢它,可以使用其他参数指定不同的文件并包含它。config.php
0赞 Liton Mazumder 4/5/2023
@EyadMohammedOsama我在两个连接config.php文件中添加了行,但我有点困惑如何在名为 main.php 的查询操作页面中调用它$connection_1 = new Database(host: "localhost", user: "user", pass: "pass",dbname: "db1"); $connection_2 = new Database(host: "localhost", user: "user", pass: "pass",dbname: "db2");
0赞 Professor Abronsius 4/5/2023 #2

如果您要将所有数据库连接详细信息存储在一个文件中(作为 JSON ),您可以执行如下操作。

<?php
    /*
        connection details for each database
        in JSON format. This could be saved
        as, for instance, db-credentials.json 
        -------------------------------------
        
        {
            "db1":{
                "dbuser":"dbo-764931",
                "dbhost":"localhost",
                "dbpwd":"xxx",
                "dbname":"blackrock"
            },
            "db2":{
                "dbuser":"dbo-984633",
                "dbhost":"localhost",
                "dbpwd":"xxx-yyy",
                "dbname":"area51"
            }
        }
        
    */
    
    
    
    
    class Database{
        private static $instance=false;
        private $db;
        
        private function __construct( $dbhost, $dbuser, $dbpwd, $dbname ){
            mysqli_report( MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT );
            $this->db=new mysqli( $dbhost, $dbuser, $dbpwd, $dbname );
        }
        public static function initialise( $dbhost, $dbuser, $dbpwd, $dbname ){
            if( !self::$instance ) self::$instance=new self( $dbhost, $dbuser, $dbpwd, $dbname );
            return self::$instance;
        }
    }
    
    class Credentials{#class to read the db connection details for given $db
        private $json;
        private $db;
        
        public function __construct( $file, $db ){
            $this->json=file_exists( $file ) ? json_decode( file_get_contents( $file ) ) : false;
            $this->db=$db;
        }
        public function fetch(){
            return is_object( $this->json ) && property_exists( $this->json,$this->db ) ? $this->json->{$this->db} : false;
        }
    }
    
    class Model{
        private $db;
        private $config;
        
        public function __construct( $config,$db ){
            $credentials=new Credentials( $config,$db );
            $obj=$credentials->fetch();
            $this->db=Database::initialise( $obj->dbhost, $obj->dbuser, $obj->dbpwd, $obj->dbname );
        }
        public function employee_list(){
            $sql='SELECT * FROM emp_list ORDER BY emp_id DESC';
            return $this->db->query( $sql )->fetch_all( MYSQLI_ASSOC );
        }
    }








    # only to show result
    function debug($obj){
        printf('<pre>%s</pre>',print_r($obj,true));
    }








    $config = __DIR__ . '/db-credentials.json';

    $model_1=new Model( $config, 'db1' );
    $model_2=new Model( $config, 'db2' );
    
    
    debug( $model_1 );
    debug( $model_2 );
?>

测试上述产量:

Model Object
(
    [db:Model:private] => Database Object
        (
            [db:Database:private] => mysqli Object
                (
                    [affected_rows] => 0
                    [client_info] => mysqlnd 5.0.12-dev - 20150407 - $Id: 38fea24f2847fa7519001be390c98ae0acafe387 $
                    [client_version] => 50012
                    [connect_errno] => 0
                    [connect_error] => 
                    [errno] => 0
                    [error] => 
                    [error_list] => Array
                        (
                        )

                    [field_count] => 0
                    [host_info] => localhost via TCP/IP
                    [info] => 
                    [insert_id] => 0
                    [server_info] => 5.5.8
                    [server_version] => 50508
                    [stat] => Uptime: 2210764  Threads: 3  Questions: 702637  Slow queries: 11  Opens: 12000  Flush tables: 1  Open tables: 256  Queries per second avg: 0.317
                    [sqlstate] => 00000
                    [protocol_version] => 10
                    [thread_id] => 52276
                    [warning_count] => 0
                )

        )

    [config:Model:private] => 
)

...省略的输出。$model_2

使用这样的方法,您可以编辑连接详细信息,而无需稍后修改类,并且可以根据需要使用任意数量的不同数据库。