Việc sử dụng lớp pdo trong php là gì?

Mặc dù không có quá nhiều lý do để tạo một trình bao bọc (vì PDO đã là một trình bao bọc), nhưng vẫn có một số vấn đề có thể gây lỗi cho lập trình viên

Vấn đề #1, dài dòng

Vấn đề chính với cả câu lệnh chuẩn bị PDO và mysqli là cơ chế được thiết kế để thực hiện nhiều lần, khi

$data = $pdo->prepare($sql)->execute($params)->fetch();
5 và
$data = $pdo->prepare($sql)->execute($params)->fetch();
6 chỉ được gọi một lần và sau đó
$data = $pdo->prepare($sql)->execute($params)->fetch();
7 được gọi nhiều lần với các bộ dữ liệu khác nhau. Đó là lý do tại sao mã quá dài dòng

Tuy nhiên, trong thực tế, việc thực thi nhiều lần hiếm khi được sử dụng, trong khi hầu hết các câu lệnh chuẩn bị sẵn chỉ được sử dụng để thực hiện truy vấn một lần. Kết quả là, đối với mỗi truy vấn đơn lẻ, chúng tôi buộc phải viết đi viết lại cùng một quy trình lặp đi lặp lại

$stmt = $pdo->prepare("SELECT * FROM users WHERE sex=?");
$stmt->execute([$sex]);
$data = $stmt->fetchAll();

Sẽ tốt hơn nếu

$data = $pdo->prepare($sql)->execute($params)->fetch();
8 trả về câu lệnh, cho phép xâu chuỗi phương thức gọn gàng

$data = $pdo->prepare($sql)->execute($params)->fetch();

Nhưng than ôi -

$data = $pdo->prepare($sql)->execute($params)->fetch();
8 đang trả về một giá trị boolean

Dù bằng cách nào, ngay cả cách tiếp cận như vậy cũng sẽ không cần thiết trong hầu hết thời gian, vì chúng ta không cần các cuộc gọi chuẩn bị và thực hiện riêng biệt

Để giải quyết sự bất tiện này, sẽ là một ý kiến ​​hay nếu có một chức năng tương tự như Postgres'

function pdo($pdo, $sql, $args = NULL)
{
    if (!$args)
    {
         return $pdo->query($sql);
    }
    $stmt = $pdo->prepare($sql);
    $stmt->execute($args);
    return $stmt;
}
0 để đóng gói thủ tục chuẩn bị/thực thi và trả về câu lệnh

Một chức năng PDO đơn giản

Giải pháp đơn giản nhất là tạo một hàm chấp nhận một đối tượng PDO, một truy vấn SQL và một mảng tùy chọn với các tham số cho exec() và trả về một đối tượng

function pdo($pdo, $sql, $args = NULL)
{
    if (!$args)
    {
         return $pdo->query($sql);
    }
    $stmt = $pdo->prepare($sql);
    $stmt->execute($args);
    return $stmt;
}
1

function pdo($pdo, $sql, $args = NULL)
{
    if (!$args)
    {
         return $pdo->query($sql);
    }
    $stmt = $pdo->prepare($sql);
    $stmt->execute($args);
    return $stmt;
}

Nó sẽ phục vụ nếu mã của bạn chủ yếu là thủ tục. Do bạn có thể xâu chuỗi bất kỳ phương thức

function pdo($pdo, $sql, $args = NULL)
{
    if (!$args)
    {
         return $pdo->query($sql);
    }
    $stmt = $pdo->prepare($sql);
    $stmt->execute($args);
    return $stmt;
}
1 nào trực tiếp vào lệnh gọi của hàm này, hầu hết các truy vấn sẽ chỉ trở thành một lớp lót

// getting the number of rows in the table
$count = pdo($pdo, "SELECT count(*) FROM users")->fetchColumn();

// the user data based on email
$user = pdo($pdo, "SELECT * FROM users WHERE email=?", [$email])->fetch();

// getting many rows from the table
$data = pdo($pdo, "SELECT * FROM users WHERE salary > ?", [$salary])->fetchAll();

// getting the number of affected rows from DELETE/UPDATE/INSERT
$deleted = pdo($pdo, "DELETE FROM users WHERE id=?", [$id])->rowCount();

// insert
pdo($pdo, "INSERT INTO users VALUES (null, ?,?,?)", [$name, $email, $password]);

// named placeholders are also welcome though I find them a bit too verbose
pdo($pdo, "UPDATE users SET name=:name WHERE id=:id", ['id'=>$id, 'name'=>$name]);

// using a sophisticated fetch mode, indexing the returned array by id
$indexed = pdo($pdo, "SELECT id, name FROM users")->fetchAll(PDO::FETCH_KEY_PAIR);

Một lớp PDO đơn giản

Tuy nhiên, bước tiếp theo sẽ là tạo một lớp chứa tất cả mã kết nối PDO, cũng như hàm hữu ích

function pdo($pdo, $sql, $args = NULL)
{
    if (!$args)
    {
         return $pdo->query($sql);
    }
    $stmt = $pdo->prepare($sql);
    $stmt->execute($args);
    return $stmt;
}
3. Lưu ý rằng vì mục đích sử dụng, lớp này chỉ có thể được sử dụng với cơ sở dữ liệu mysql

class DB
{
    public $pdo;

    public function __construct($db, $username = NULL, $password = NULL, $host = '127.0.0.1', $port = 3306, $options = [])
    {
        $default_options = [
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_EMULATE_PREPARES => false,
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        ];
        $options = array_replace($default_options, $options);
        $dsn = "mysql:host=$host;dbname=$db;port=$port;charset=utf8mb4";

        try {
            $this->pdo = new \PDO($dsn, $username, $password, $options);
        } catch (\PDOException $e) {
            throw new \PDOException($e->getMessage(), (int)$e->getCode());
        }
    }
    public function run($sql, $args = NULL)
    {
        if (!$args)
        {
            return $this->pdo->query($sql);
        }
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute($args);
        return $stmt;
    }
}

Bây giờ lớp này có thể được bao gồm trong tất cả các lớp khác dưới dạng tham số hàm tạo trong tất cả các lớp khác yêu cầu tương tác cơ sở dữ liệu. Lưu ý rằng biến PDO được đặt ở chế độ công khai. Đó là bởi vì chúng tôi sẽ cần truy cập chức năng PDO đầy đủ thông qua biến này

Để sử dụng lớp này, trước tiên hãy tạo một thể hiện, như thế này

$db = new DB($dbname, $user, $password);

và sau đó được sử dụng giống như chức năng nhưng thay vì khá vụng về

function pdo($pdo, $sql, $args = NULL)
{
    if (!$args)
    {
         return $pdo->query($sql);
    }
    $stmt = $pdo->prepare($sql);
    $stmt->execute($args);
    return $stmt;
}
4, chúng ta có thể viết nó thành
function pdo($pdo, $sql, $args = NULL)
{
    if (!$args)
    {
         return $pdo->query($sql);
    }
    $stmt = $pdo->prepare($sql);
    $stmt->execute($args);
    return $stmt;
}
5

$db->run("INSERT INTO users VALUES (null, ?,?,?)", [$name, $email, $password]);
$id = $db->pdo->lastInsertId();

Mở rộng PDO

Một cách khác để truy cập chức năng PDO đầy đủ là mở rộng đối tượng của chúng ta từ PDO

Hãy mở rộng PDO và thêm một phương thức mới có tên là

function pdo($pdo, $sql, $args = NULL)
{
    if (!$args)
    {
         return $pdo->query($sql);
    }
    $stmt = $pdo->prepare($sql);
    $stmt->execute($args);
    return $stmt;
}
3 (vì tôi thích đặt tên ngắn hơn cho các hàm thường được gọi). Ngoài ra, để thuận tiện, chúng ta có thể thêm các tùy chọn kết nối cần thiết nhất vào hàm tạo

class MyPDO extends PDO
{
    public function __construct($dsn, $username = NULL, $password = NULL, $options = [])
    {
        $default_options = [
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
            PDO::ATTR_EMULATE_PREPARES => false,
            PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        ];
        $options = array_replace($default_options, $options);
        parent::__construct($dsn, $username, $password, $options);
    }
    public function run($sql, $args = NULL)
    {
        if (!$args)
        {
             return $this->query($sql);
        }
        $stmt = $this->prepare($sql);
        $stmt->execute($args);
        return $stmt;
    }
}

và bây giờ chúng tôi đã có một lớp MyPDO mới hoạt động như PDO cũ theo bất kỳ cách nào tiết kiệm cho việc bổ sung một phương thức mới cho phép chúng tôi chạy một truy vấn đã chuẩn bị trong một cuộc gọi

$data = $pdo->run("SELECT * FROM users WHERE sex=?",[$sex])->fetchAll();

Ngoài ra, chúng tôi chỉ bao gồm các tùy chọn cấu hình hữu ích nhất theo mặc định, mặc dù chúng có thể bị ghi đè

Vấn đề #2, tính khả dụng

Một vấn đề khác là tính khả dụng của phiên bản PDO. Cũng giống như bất kỳ biến nào khác, nó bị ràng buộc với phạm vi của nó và theo mặc định không có sẵn trong bất kỳ hàm hoặc phương thức nào của lớp. Có thể có cách tiếp cận để giải quyết vấn đề này. Hãy xem xét một số trong số họ

Cách OOP thực sự

Để đơn giản, Dependency injection là viết tắt của việc chuyển tất cả các dịch vụ cần thiết thông qua hàm tạo của lớp

Vì vậy, nếu mã của bạn là hướng đối tượng, thì bạn có thể sử dụng giải pháp lớp MyPDO ở trên, chuyển thể hiện của nó xung quanh bằng cách sử dụng hàm tạo của các lớp khác

class User
{
    /* @var MyPDO */
    protected $db;

    protected $data;

    public function __construct(MyPDO $db)
    {
        $this->db = $db;
    }

    public function find($id)
    {
        $this->data = $this->db->run("SELECT * FROM users WHERE id = ?", [$id])->fetch();

    }
}

Và sau đó sử dụng nó theo cách này

$data = $pdo->prepare($sql)->execute($params)->fetch();
0

Lưu ý rằng phương pháp này sẽ hoạt động miễn là tất cả các lớp của bạn được khởi tạo thủ công. Trong trường hợp một số lớp được khởi tạo động, bạn sẽ cần một Bộ chứa tiêm phụ thuộc, nó sẽ lưu trữ một thể hiện duy nhất của lớp kết nối cơ sở dữ liệu và đưa nó vào tất cả các lớp đã tạo nếu chúng cần

Giải pháp tĩnh cho Mã hướng đối tượng

Nhưng trong một mã được tổ chức kém, thật khó để vượt qua phiên bản cơ sở dữ liệu theo cách này. Đối với điều này, có một sự đánh đổi giữa cách đúng đắn và một kẻ độc thân cùn. một lớp có thể trả về thể hiện của nó thông qua một hàm tĩnh

$data = $pdo->prepare($sql)->execute($params)->fetch();
1

Vì vậy, bây giờ chúng ta có thể thay đổi lớp

function pdo($pdo, $sql, $args = NULL)
{
    if (!$args)
    {
         return $pdo->query($sql);
    }
    $stmt = $pdo->prepare($sql);
    $stmt->execute($args);
    return $stmt;
}
7 theo cách này

$data = $pdo->prepare($sql)->execute($params)->fetch();
2

Nó sẽ kém linh hoạt hơn trong trường hợp bạn sẽ cần các nhà cung cấp cơ sở dữ liệu khác nhau cho các phiên bản Người dùng khác nhau nhưng ít nhất nó đang sử dụng biến lớp

function pdo($pdo, $sql, $args = NULL)
{
    if (!$args)
    {
         return $pdo->query($sql);
    }
    $stmt = $pdo->prepare($sql);
    $stmt->execute($args);
    return $stmt;
}
8 tập trung

Singleton cùn, cho mã thủ tục của bạn

Nếu bạn đến đây chỉ để tìm kiếm sự thay thế cho hàm mysql_query cũ tốt sẽ được sử dụng trong mã tất cả thủ tục của mình, bạn có thể sử dụng mẫu Singleton bị coi thường

$data = $pdo->prepare($sql)->execute($params)->fetch();
3

chỉ cần đặt mã này vào tệp có tên, chẳng hạn như,

function pdo($pdo, $sql, $args = NULL)
{
    if (!$args)
    {
         return $pdo->query($sql);
    }
    $stmt = $pdo->prepare($sql);
    $stmt->execute($args);
    return $stmt;
}
9, đặt nó ở đâu đó trong trang web của bạn và đừng quên đưa nó vào bất cứ nơi nào bạn cần cơ sở dữ liệu

ví dụ

Các ví dụ dưới đây chứng minh việc sử dụng phương pháp đơn lẻ ở trên. Mã đã sẵn sàng để sử dụng. Bạn có thể sao chép và dán mã bên dưới và chạy nó như bình thường. Chỉ cần đừng quên tạo một 'cơ sở dữ liệu. php' từ chương trên

Lợi ích của PDO là gì?

Chỉ polydioxanone hoặc PDO được làm từ protein và mỏng hơn sợi tóc. Theo nghiên cứu y học, chúng giúp thư giãn cơ và gân . Phản ứng của hệ thống miễn dịch đối với cơ thể nước ngoài giúp cải thiện lưu lượng máu đến khu vực này, kích thích sản xuất collagen mới trong da của bạn.

Tại sao nên sử dụng PDO thay vì MySQLi?

PDO sẽ hoạt động trên 12 hệ thống cơ sở dữ liệu khác nhau, trong khi MySQLi sẽ chỉ hoạt động với cơ sở dữ liệu MySQL . Vì vậy, nếu bạn phải chuyển dự án của mình sang sử dụng cơ sở dữ liệu khác, PDO sẽ giúp quá trình này trở nên dễ dàng. Bạn chỉ phải thay đổi chuỗi kết nối và một vài truy vấn.