Nhập từ khóa tìm kiếm

post

10 lỗi lập trình PHP phổ biến hay gặp phải (P.1)

10 lỗi lập trình PHP phổ biến hay gặp phải (P.1)

Một trong những điều tốt nhất về PHP là đây là một ngôn ngữ tuyệt vời nhờ vào sự phổ biến rộng rãi của nó. Vậy liệu PHP có tồn tại những lỗi lập trình nào hay không? 

Bất kỳ ai có khả năng nhấn “Tìm kiếm” trên Google đều có thể nhanh chóng tạo một chương trình bằng PHP. Tuy nhiên, điều này cũng dẫn đến một số hạn chế đối với PHP: nó có nhiều lỗi không hề phức tạp nhưng các lập trình vẫn dễ mắc phải và gần như quá dễ dàng để dính mã xấu.

Dưới đây là các lỗi PHP mà bất kỳ lập trình viên nào, bất kể trình độ kỹ năng, đều có thể mắc phải tại bất kỳ thời điểm nào. Một số sai lầm rất cơ bản, nhưng ngay cả những lập trình viên PHP giỏi nhất cũng sẽ mắc phải. Nhưng tất cả những sai lầm này đều có một điểm chung: Chúng rất dễ tránh nếu bạn chú ý kiểm tra.

Hãy dành thời gian và đảm bảo rằng PHP của bạn an toàn, sạch sẽ và chạy trơn tru bằng cách kiểm tra trang web của bạn để tìm các lỗi PHP phổ biến này.

 

lỗi lập trình 1: Dấu ngoặc ‘’ và “”

Thật dễ dàng để chỉ sử dụng dấu ngoặc kép khi nối các chuỗi vì nó phân tích cú pháp mọi thứ một cách gọn gàng mà không cần phải xử lý các ký tự thoát và sử dụng các giá trị dấu chấm. Tuy nhiên, việc sử dụng các dấu ngoặc kép có hiệu suất đáng kể, vì nó đòi hỏi ít xử lý hơn.

Hãy xem xét chuỗi này:

# $howdy = ‘everyone’; 

# $foo = ‘hello $howdy’; 

# $bar = “hello $howdy”;

$ foo xuất thành “hello $ howdy” và $ bar cho chúng ta “hello everyone”. Đó là một bước ít hơn mà PHP phải xử lý. Đó là một thay đổi nhỏ có thể tạo ra lợi ích đáng kể trong hiệu suất của mã.

loi-php-1

lỗi lập trình 2: Không xoá reference sau vòng lặp foreach

Sử dụng reference là đặc biệt hữu ích khi bạn muốn thao tác với phần tử trong mảng

$arr = array(1, 2, 3, 4);

foreach ($arr as &$value) {

    $value = $value * 2;

}

// $arr bây giờ là (2, 4, 6, 8)

Nếu không cẩn thận bạn rất dễ gây ra side-effect không mong muốn ở đây. Trong ví dụ này, sau khi vòng lặp foreach chạy xong, $value vẫn giữ nguyên scope và đang là reference tới phần tử cuối cùng của mảng $arr. Những dòng lệnh sau sử dụng $value sẽ rất dễ sinh bug ở đây. Cần phải nhớ là trong php vòng lặp foreach không tạo ra scope mới. Bởi vậy, biến $value hiện đang giữ reference đang ở toàn cục ngay cả sau vòng foreach. Hãy xem ví dụ dưới đây:

$array = [1, 2, 3];

echo implode(‘,’, $array), “\n”;    //1,2,3

foreach ($array as &$value) {}    // reference

echo implode(‘,’, $array), “\n”;    //1,2,3

foreach ($array as $value) {}     // copy

echo implode(‘,’, $array), “\n”;    //1,2,2

Giá trị sau cùng in ra là 1, 2, 2 chứ không như bạn mong đợi phải không? Chúng ta cùng phân tích điều gì đã xảy ra trong ví dụ này. Sau vòng foreach đầu tiên, mảng vẫn giữ nguyên nhưng lúc này biến toàn cục $value đang là reference tới $arr[2]. Vòng foreach thứ 2, không sử dụng reference, các giá trị $value sẽ được copy từ $array.

Vòng lặp đầu tiên, $value nhận giá trị copy từ $arr[0] = 1, vì $value là reference tới $arr[2] nên $arr[2] = 1. Kết quả sau vòng đầu : $arr = [1,2,1]. Vòng lặp thứ 2, $value nhận giá trị copy từ $arr[1] = 2, vì $value là reference tới $arr[2] nên $arr[2] = 2. Kết quả sau vòng đầu : $arr = [1,2,2]. Vòng lặp thứ 3, $value nhận giá trị copy từ $arr[2] = 2, vì $value là reference tới $arr[2] nên $arr[2] = 2. Kết quả sau vòng đầu : $arr = [1,2,2].

Để tránh mắc lỗi này, các bạn cần nhớ giải phóng biến reference sau vòng lặp foreach.

$arr = array(1, 2, 3, 4);

foreach ($arr as &$value) {

    $value = $value * 2;

}

unset($value);   // $value không còn là reference tới $arr[3]

loi-php-1

lỗi lập trình 3: Thực hiện truy vấn vòng lặp

Không hiếm khi bạn sẽ gặp đoạn code giống như thế này:

$models = [];

foreach ($inputValues as $inputValue) {

    $models[] = $valueRepository->findByValue($inputValue);

}

Mặc dù hoàn toàn không có gì sai ở đây, nhưng nếu bạn để ý logic trong code, bạn có thể thấy rằng giá trị $valueRepository->findByValue() đang được gọi một cách vô tội vạ, cuối cùng kết quả của truy vấn của một số thứ, sẽ giống như thế này: 

$result = $connection->query(“SELECTx,yFROMvaluesWHEREvalue=” . $inputValue);

Kết quả là, mỗi lần lặp của vòng lặp ở trên sẽ dẫn đến một truy vấn đến cơ sở dữ liệu. Ví dụ, nếu bạn lặp một mảng có 1000 giá trị, nó sẽ tạo ra 1000 truy vấn riêng biệt cho cơ sở dữ liệu. Nếu như việc này được gọi trong nhiều threads, nó có thể làm cho hệ thống bị ngừng hoạt động. Do đó cần phải xác định khi nào các truy vấn được thực hiện trong code của bạn. Bất cứ khi nào có thể, hãy thu thập các giá trị và sau đó chạy một truy vấn để lấy ra tất cả các kết quả.

Một ví dụ về một chỗ khá phổ biến để gặp phải việc thực hiện truy vấn không hiệu quả (hay truy vấn trong vòng lặp) là với danh sách các giá trị (ví dụ ID). Sau đó, để lấy dữ liệu đầy đủ cho mỗi ID, code sẽ lặp qua array và thực hiện truy vấn SQL riêng cho mỗi ID. Giống thế này:

$data = [];

foreach ($ids as $id) {

    $result = $connection->query(“SELECT `x`, `y` FROM `values` WHERE `id` = ” . $id);

    $data[] = $result->fetch_row();

}

Nhưng cùng một vấn đề như vậy có thể được giải quyết bằng cách hiệu quả hơn nhiều:

$data = [];

if (count($ids)) {

    $result = $connection->query(“SELECT `x`, `y` FROM `values` WHERE `id` IN (” . implode(‘,’, $ids));

    while ($row = $result->fetch_row()) {

        $data[] = $row;

    }

}

Do đó, điều quan trọng để nhận ra các truy vấn đang được thực hiện, hoặc trực tiếp hoặc gián tiếp, đó là bằng code của bạn. Bất cứ khi nào có thể, hãy thu thập các giá trị sau đó chạy một truy vấn để lấy tất cả các kết quả. Tuy nhiên, phải thận trọng khi thực hiện điều đó, nó có thể dẫn chúng ta tới một sai lầm phổ biến tiếp theo.

loi-php-2

lỗi lập trình 4: Bỏ qua các vấn đề liên quan đến Unicode/UTF-8

Trong một số trường hợp, đây thực sự là một vấn đề trong chính PHP hơn là một cái gì đó bạn sẽ chạy trong quá trình debug PHP, nhưng nó lại chưa bao giờ được giải quyết đầy đủ. Điều cốt lõi ở trong PHP 6 là làm cho có thể nhận dạng được Unicode, nhưng đáng tiếc nó đã không được phát triển tiếp do PHP 6 bị đình chỉ trong năm 2010.

Dưới đây là một danh sách kiểm tra nhỏ để tránh những vấn đề liên quan trến Unicode/UTF-8 trong code của bạn: Nếu bạn không biết nhiều về Unicode và UTF-8, ít nhất bạn nên học các điều cơ bản:

  • Hãy chắc chắn luôn sử dụng các chức năng mb_ * thay vì các hàm xử lý chuỗi cũ (đảm bảo phần mở rộng “multibyte” được xây dựng cùng với mã code PHP của bạn).
  • Hãy chắc chắn rằng cơ sở dữ liệu và bảng của bạn được thiết lập để sử dụng Unicode (nhiều bản xây dựng của MySQL theo mặc định vẫn sử dụng latin1).
  • Hãy nhớ rằng json_encode () chuyển đổi các ký hiệu non-ASCII (ví dụ: “Schrödinger” trở thành “Schr \ u00f6dinger”) nhưng serialize() thì không.
  • Đảm bảo rằng các file code PHP của bạn cũng được mã hoá UTF-8 để tránh xung đột khi nối chuỗi với hằng số chuỗi được mã hoá hoặc đã được config.

 

lỗi lập trình 5: Không kiểm tra dữ liệu đầu vào

Có một điều quan trọng cần ghi nhớ đó là “đừng bao giờ tin tưởng vào những gì người sử dụng nhập”. Cần kiểm tra tất cả các chuỗi được nhập vào ở phía PHP server – không dựa trên JavaScript. Các cuộc tấn công SQL injection đơn giản nhất phụ thuộc vào mã.

Nó có thể bị bẻ khóa khi nhập vào “admin’; –” ở ô username. 

Người tấn công có thể login như “admin”; mà không cần phải biết mật khẩu.

Hãy sử dụng:

  • mysql_real_escape_string() cho biến kiểu chuỗi.
  • intval() cho biến integer.
  • filter_var(). Đây là một hàm rất mạnh được sử dụng nhiều trong những năm gần đây, với các tính năng: xác định tính hợp lệ của dữ liệu, lọc các ký tự không mong muốn.

 

[Tài liệu tham khảo: theo fullstackstation.com]


Bài viết liên quan: 9 câu hỏi về lập trình web PHP dành cho người mới bắt đầu

Chat Zalo
0906.801.479
Chương trình đào tạo Liên hệ Đăng ký tư vấn