iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 11
0
Modern Web

寫給朋友的 PHP 從 0 到 100 實戰教程系列 第 11

Day 11. PHP教學: 使用單例模式來連接資料庫

  • 分享至 

  • xImage
  •  

Why
我們已經可以透過 composer 這個相依函式庫管理軟體來快速的使用資料庫連接物件了,為什麼要重新調整這個連接資料庫的功能呢?

因為實務上,我們發現常常一次網頁請求要建立好幾個跟資料庫的連線,這會佔用很多的系統資源,如果瞬間連線數一衝高,伺服器就會開始裝死,導致所有顧客都無法下單,服務終止,那就真的糗了。

我們要避免這種情況的話,就要保持一個請求只有一次連線,不管使用多少次資料庫資源。這樣的優化無形中,會降低伺服器的負擔,出狀況的機率也可以降低很多。

How
那要怎麼弄呢?
首先,我們先做幾個專案上的優化,把必要參數抽出來寫成弄成 config 資料夾
裡面放一些固定的參數,我們可以學著靜態 Class 的方式來製作

config/MySQL.php

<?php
class MySQL {
  const ADDRESS = "localhost";
  const USERNAME = "root";
  const PASSWORD = "root";
  const DATABASE = "game";
}

新建立一個檔案,專門來維持只會一個靜態資料庫物件

libraries/Database.php

<?php
/**
 * 使用單例模式的資料庫連接方式,無論使用多少次都是使用同一個連線
 */
<?php
/**
 * 使用單例模式的資料庫連接方式,無論使用多少次都是使用同一個連線
 */
class Database {
  
    private static $instance;
    private function __construct() {
        // 使用 private 建構子避免在外面被意外地初始化
    }

    private static function getInstance() {
        if (!isset(self::$instance)) {
            self::$instance = new DatabaseAccessObject(
              MySQL::ADDRESS,
              MySQL::USERNAME,
              MySQL::PASSWORD,
              MySQL::DATABASE
            );
        }
    }

    public static function get() {
        self::getInstance();
        if (isset(self::$instance)) {
            return self::$instance;
        } else {
            return NULL;
        }
    }

    public static function unlinkDAO() {
        if (isset(self::$instance)) {
            self::$instance = null; // 會自動執行解構子 close link
        }
    }
}

記得要設定 composer 才能直接使用哦
修改 composer.json

{
    "name": "jarvis/game",
    "authors": [
        {
            "name": "Jarvis",
            "email": "endless640c@gmail.com"
        }
    ],
    "require": {
      "monolog/monolog": "^1.23"
    },
    "autoload": {
      "classmap": [
          "libraries",
          "config"
      ]
    }
}

開啟終端機後跳到專案目錄下再下 composer 指令

cd /Application/XAMPP/htdocs/game
composer dump

那在程式碼裡要怎麼使用呢?直接呼叫即可:

$db = Database::get();

What
有沒有注意到 static 這個詞一直冒出來,這是靜態的意思
他可以不需要先 new 實作成物件就可以直接以 class name 後面接 :: 即可使用
如果是變數可以直接 ::變數名,但是如果是 function 函數的話 記得還是要加小括號 ::函數名()

這樣取得 DatabaseAccessObject 的話,無論取幾次都只有一次連線,因為每次取都會檢查是否連線物件已存在,不存在才會建立連線,否則就用同一個連線就好,這樣一來就達到我們的需求:每次來自瀏覽器的請求,都只會跟資料庫建立一個連線。不會因為專案越來老,開始堆積連線數量。

附上參考資料:

https://rongli.gitbooks.io/design-pattern/content/chapter5.html
https://en.wikipedia.org/wiki/Singleton_pattern


上一篇
Day 10. PHP教學: Clean URL 優化連結
下一篇
Day 12. PHP教學: 取得使用者輸入的資料存到資料庫
系列文
寫給朋友的 PHP 從 0 到 100 實戰教程30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言