模仿 ThinkPHP - db 類的封裝實例

模仿 ThinkPHP - db 類的封裝實例:

class Db extends \mysqli
{
    // 實例對象
    protected static $_instance = null;
    // mysql配置
    protected static $options = [
        // 服務器地址
        'host' => '127.0.0.1',
        // 數據庫名
        'database' => 'test',
        // 用戶名
        'username' => 'root',
        // 密碼
        'password' => 'root',
        // 端口
        'hostport' => '3306',
        // socket
        "socket" => "",
        // 數據庫編碼默認採用utf8
        'charset' => 'utf8mb4',
        // 數據庫表前綴
        'prefix' => 'fd_',
    ];

    // 表
    protected $tbl = null;
    // 條件
    protected $where = "";
    // 字段,field 被佔有
    protected $f = "*";
    // 排序
    protected $order = "";
    // 分頁
    protected $limit = "";
    // 關聯
    protected $join = "";
    // $lastSql
    protected $lastSql = "";

    /**
     * Db constructor.
     * @param string $host
     * @param string $username
     * @param string $passwd
     * @param string $dbname
     * @param int $port
     * @param string $socket
     * @author atong
     */
    public function __construct(string $host, string $username, string $passwd, string $dbname, int $port, string $socket)
    {
        @parent::__construct($host, $username, $passwd, $dbname, $port, $socket);

        if ($this->connect_errno) {
            exit("mysql連接錯誤[{$this->connect_errno}]:{$this->connect_error}");
        }
        $this->set_charset(self::$options["charset"]);
    }

    /**
     * 數據庫初始化,並取得數據庫類實例
     * @access public
     * @param array $options 連接配置
     * @param bool $is_force 連接標識 true 強制重新連接
     * @author atong
     * @return Mysql
     */
    public static function getInstance($options = [])
    {
        if (self::$_instance == null) {
            $db_config = self::$options;
            self::$_instance = new self(
                $options["host"] ?? $db_config["host"]
                , $options["username"] ?? $db_config["username"]
                , $options["password"] ?? $db_config["password"]
                , $options["database"] ?? $db_config["database"]
                , $options["hostport"] ?? $db_config["hostport"]
                , $options["socket"] ?? $db_config["socket"]
            );
        }
        return self::$_instance;
    }


    /**
     * todo::鏈式函數封裝
     * 模仿 tp db類的風格
     */

    // 無前綴
    public function _table($tbl)
    {
        $this->tbl = $tbl;
        return $this;
    }

    // 拼接表(前綴+$tbl)
    public function _name($tbl)
    {
        $this->tbl = self::$options["prefix"] . $tbl;
        return $this;
    }

    public function _alias($alias)
    {
        $this->tbl .= " AS {$alias} ";
        return $this;
    }

    /**
     * @param array $where
     * $where = [
     *      ["id",">",1]
     *      ["status","=",1]
     * ]
     * or
     * ["id","=","1"]
     * or
     * [
     *      "id" => 10,
     *      "status" => 1
     * # 跟tp5一樣,val值不能是數組
     * ]
     * or
     * $where = "id > 1"
     * @param string $type OR|AND
     * @author atong
     * @return string|null
     */
    public function _where($where, $type = "AND")
    {
        if ($where) {
            if (is_string($where)) {
                $this->where .= " {$type} {$where} ";
            }
            if (is_array($where)) {
                // 一維,
                if (count($where) == count($where, 1)) {
                    $keys = array_keys($where);
                    // 索引數組 斷定格式爲:["id","=","1"]
                    if ($keys === array_keys($keys)) {
                        $this->where .= " $type $where[0] $where[1] '$where[2]' ";
                    } else {
                        // 聯合數組 斷定格式爲:["id"=> 10 ,"status" => 1]
                        foreach ($where as $key => $val) {
                            $this->where .= " $type $key = '$val' ";
                        }
                    }

                } else {
                    foreach ($where as $k => $v) {
                        $this->where .= " $type $v[0] $v[1] '$v[2]' ";
                    }
                }
            }
        }
        return $this;
    }

    // 查詢字段
    public function _field($field)
    {
        $this->f = is_array($field)
            ? implode(",", $field)
            : $field;
        return $this;
    }

    // 排序
    public function _order($order)
    {
        if (!$this->order) {
            $this->order = " ORDER BY {$order} ";
        } else {
            $this->order .= " ,$order ";
        }
        return $this;
    }

    // 分頁
    public function _page($limit1, $limit2 = "")
    {
        if (!$limit2) {
            $this->limit .= " limit {$limit1} ";
        } else {
            $this->limit .= " limit " . ($limit1 - 1) * $limit2 . "," . $limit2;
        }
        return $this;
    }

    // 表關聯
    public function _join($tbl, $condition, $relation = "LEFT")
    {
        $this->join .= " {$relation} JOIN {$tbl}";
        $this->join .= " ON {$condition} ";
        return $this;
    }

    // 獲取查詢語句的 sql
    public function _getSelectSql()
    {
        $this->lastSql .= "SELECT $this->f FROM $this->tbl ";
        $this->lastSql .= $this->join;
        if ($this->where) {
            $this->where = trim(trim(trim($this->where), "AND"), "OR");
            $this->lastSql .= " WHERE " . $this->where;
        }
        $this->lastSql .= $this->order;
        $this->lastSql .= $this->limit;
        return $this->lastSql;
    }


    // 獲取最新的 sql 語句
    public function _getLastSql()
    {
        return $this->lastSql;
    }

    // 單記錄查詢
    public function _find($just_do_it = true)
    {
        $sql = $this->_getSelectSql();

        $rs = !$just_do_it ? $sql : $this->getFind($sql);
        $this->destroy();
        return $rs;
    }

    // 多記錄查詢
    public function _select($just_do_it = true)
    {
        $sql = $this->_getSelectSql();

        $rs = !$just_do_it ? $sql : $this->getSelect($sql);
        $this->destroy();
        return $rs;
    }

    // 刪除操作
    public function _delete($just_do_it = true)
    {
        $this->lastSql = "DELETE FROM $this->tbl ";
        $this->where = trim(trim(trim($this->where), "AND"), "OR");
        $this->lastSql .= " WHERE " . $this->where;
        $rs = !$just_do_it ? $this->lastSql : $this->query($this->lastSql);
        $this->destroy();
        return $rs;
    }

    // 修改
    public function _update($data = [], $just_do_it = true)
    {
        $this->lastSql = "UPDATE $this->tbl ";
        $set = "";
        foreach ($data as $field => $val) {
            $set .= "{$field} = '$val',";
        }
        $this->lastSql .= "SET " . trim($set, ",");
        $this->where = trim(trim(trim($this->where), "AND"), "OR");
        $this->lastSql .= " WHERE " . $this->where;
        $rs = !$just_do_it ? $this->lastSql : $this->query($this->lastSql);
        $this->destroy();
        return $rs;
    }

    // 插入
    public function _insert($data = [], $just_do_it = true)
    {
        $this->lastSql = "INSERT INTO $this->tbl ";
        $fields = $values = "";
        foreach ($data as $field => $value) {
            $fields .= "" . $field . ",";
            $values .= "'" . $value . "',";
        }
        $this->lastSql .= "(" . trim($fields, ',') . ") VALUES (" . trim($values, ',') . ")";

        $rs = !$just_do_it ? $this->lastSql
            : ($this->query($this->lastSql) ? $this->insert_id : false);
        $this->destroy();
        return $rs;
    }

    // 插入多條記錄
    public function _insertAll($datas = [], $just_do_it = true)
    {
        $this->lastSql = "INSERT INTO $this->tbl ";
        $fields = $values = "";
        foreach ($datas as $k => $data) {
            if ($k === 0) {
                foreach ($data as $field => $value) {
                    $fields .= "{$field},";
                    $values .= "'{$value}',";
                }
                $this->lastSql .= "(" . trim($fields, ',') . ") VALUES (" . trim($values, ',') . ")";
            } else {
                $values = "";
                foreach ($data as $value) {
                    $values .= "'" . $value . "',";
                }
                $this->lastSql .= ",(" . trim($values, ',') . ")";
            }
        }
        $rs = !$just_do_it ? $this->lastSql : $this->query($this->lastSql);
        $this->destroy();
        return $rs;
    }

    // 獲取異常
    public function getErr()
    {
        exit("語句錯誤 [{$this->errno}]:{$this->error}");
    }

    //
    public function getFind($sql)
    {
        $result = $this->query($sql); //mysqli_result對象
        if (!is_object($result)) {
            exit($sql . "語句錯誤 [{$this->errno}]:{$this->error}");
        }
        $row = $result->fetch_array(MYSQLI_ASSOC);
        return $row;
    }

    //
    public function getSelect($sql)
    {
        //mysqli_result對象
        $result = $this->query($sql);
        if (!is_object($result)) {
            exit($sql . "語句錯誤 [{$this->errno}]:{$this->error}");
        }
        return $result->fetch_all(MYSQLI_ASSOC);
    }

    // 銷燬對象
    protected function destroy()
    {
        self::$_instance = null;
    }
}

使用:

// require "./Db.php";

// 方法
if (!function_exists('db')) {
    /**
     * db 類操作
     * @param $key
     * @author atong
     * @return mixed
     */
    function db($tbl = "")
    {
        return Db::getInstance()->_name($tbl);
    }
}


// 使用

//   // 增
$sql1 = db("log")->_insert([
    "option_name" => "test key1",
    "option_value" => "test valu1"
],false);
echo "\$sql1:<span style='color:red'>{$sql1}</span>";
echo "<hr>";
// // or
$sql2 = db("log")->_insertAll([
    [
        "option_name" => "test key2",
        "option_value" => "test value2"
    ],
    [
        "option_name" => "test key3",
        "option_value" => "test value3"
    ],
    [
        "option_name" => "test key4",
        "option_value" => "test value4"
    ],
],false);
echo "\$sql2:<span style='color:red'>{$sql2}</span>";
echo "<hr>";

// // 刪
$sql3 = db("log")->_where(["option_id" => 1])->_delete(false);

echo "\$sql3:<span style='color:red'>{$sql3}</span>";
echo "<hr>";

$sql4 = db("log")->_where([
    ["option_id","=",10],
    ["option_id","=",13]
],"OR")->_delete(false);
echo "\$sql4:<span style='color:red'>{$sql4}</span>";
echo "<hr>";


// // 改
$sql5 = db("log")->_where(["option_id","=",1])->_update([
    "option_name" => "update",
    "option_value" => "update"
],false);
echo "\$sql5:<span style='color:red'>{$sql5}</span>";
echo "<hr>";


$sql6 = db("log")->_where([
    "option_id" => 1,
    "option_name" => "atong"
])->_find(false);
echo "\$sql6:<span style='color:red'>{$sql6}</span>";
echo "<hr>";

// // 查
$sql7 = db("user")->_alias("u")
    ->_join("fd_user_vip vip","vip.user_id = u.id")
    ->_field("u.id,email,level")
    ->_where("u.id = 1")
    ->_where([
        ["u.status","=",1],
        ["u.create_time",">",time()]
    ],"OR")
    ->_order("u.id desc")
    ->_order("u.create_time ASC")
    ->_page(1,10)
    ->_select(false);

echo "\$sql7:<span style='color:red'>{$sql7}</span>";
echo "<hr>";

結果:

結論:以上只是照葫蘆畫瓢,模仿db類的樣子而已,併爲考慮安全問題,實際上也只是折騰一下數組字符串的處理拼接罷了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章