Chia sẻ vài kinh nghiệm PHP căn bản

355

Cách sử dụng include và require

include và require là hàm để chèn một đoạn mã từ file khác trong hệ thống file local hoặc từ url nếu config allow_url_include được bật. Chúng khác nhau ở chỗ: khi dùng include, nếu file được chèn xảy ra lỗi thì chương trình vẫn tiếp tục chạy; còn với require, chương trình sẽ dừng ngay chỗ bị lỗi nếu nó xuất hiện trong file được chèn.
include_once và require_once cũng tương tự, chúng chỉ khác hai hàm trên là sẽ kiểm tra file đó đã được chèn trước đó chưa để đảm bảo những file đó chỉ được chèn một lần trong toàn bộ chương trình. Hai hàm này dùng chung vùng nhớ lưu thông tin included files nên nếu một file được chèn bởi include_once sẽ không được chèn lại bởi require_once. Điều này hữu ích khi chúng ta không thể biết chắc file đó đã được chèn hay chưa vì nếu chèn một file chứa hàm/lớp hai lần thì PHP sẽ báo lỗi khai báo lại hàm/lớp đó (Cannot redeclare…)

Theo những mô tả trên thì tôi luôn luôn chỉ sử dụng hai hàm require_once và include. require_once được dùng để chèn các file chỉ chứa lớp, hàm… và logic chương trình. Dữ liệu trong toàn bộ chương trình sẽ không được toàn vẹn nếu một file được chèn gặp lỗi mà nó vẫn tiếp tục, đó là lí do include_once không được sử dụng. include file được dùng để chèn các file HTML trong phần template. View layer không chứa mã logic nên không nhất thiết phải ngừng khi gặp lỗi.

Bốn hàm trên tuy là hàm nhưng cũng cũng có thể được dùng như những từ khóa: include ‘a.php’ hay include(‘a.php’) đều được. Tuy nhiên theo khuyến cáo của PEAR thì nên sử dụng chúng như từ khóa (không chứa cặp dấu ngoặc).

Mở và đóng khối mã PHP

Nếu bạn không thể kiểm soát thiết lập short_open_tag trên server chứa ứng dụng thì nên luôn luôn sử dụng thẻ mở đầy đủ short_open_tag.

Trong các file được chèn, PHP không bắt buộc phải có thẻ đóng ?> ở cuối khối mã PHP. Sau khi đóng khối mã PHP thì các kí tự sau nó bắt đầu được in ra. Việc không sử dụng thẻ đóng ?> trong các file thư viện hàm/lớp sẽ tránh được việc in ra những kí tự vô tình không kiểm soát được như tab, xuống dòng, spaces… chúng sẽ làm các đoạn mã phía sau không thể modify header nữa, điều này đã từng gây khổ sở cho rất nhiều người mới làm quen PHP.

Và sau thẻ đóng ?> thì nên có ít nhất một dòng trống. Tôi không nhớ rõ tại sao, chỉ biết là nó giúp PHP engine hoạt động tối ưu hơn.

Dấu nháy đơn (‘) và nháy kép (“)

Trong PHP thì dấu nháy đơn và nháy kép đều được dùng để đánh dấu chuỗi. Chỉ khác một điều là phía trong cặp dấu nháy kép thì vẫn có thể sử dụng biến từ bên ngoài còn nháy đơn thì không.

Ví dụ:

$a = '123';
echo "Print me: $a"; // sẽ in ra Print me: 123
echo 'Print me $a'; // sẽ in ra nguyên chuỗi Print me $a

Việc dùng nháy kép sẽ khiến trình thông dịch PHP tốn thêm công sức phân tích chuỗi trong nó để parse giá trị các biến dẫn đến tốn tài nguyên hơn nháy đơn. Bởi vậy trong các chuỗi thông thường không chứa biến tôi luôn dùng dấu nháy đơn. Không hiểu sao vẫn có rất nhiều người thích dùng dấu nháy kép để khai báo chuỗi trong khi dấu nháy đơn vừa tiết kiệm tài nguyên hệ thống vừa tiết kiệm sức người (vì không phải đè phím Shift 

)).

Tuy nhiên cũng tùy tình huống mà dùng cho hợp lí. Trong các câu lệnh SQL thì nên dùng nháy kép vì hầu hết các RDBMS đều dùng nháy đơn để đánh dấu chuỗi. Dùng nháy kép trong PHP ở đây sẽ giúp đoạn mã nhìn đỡ rối rắm hơn. Nếu echo HTML thì nên dùng nháy đơn vì giá trị của thuộc tính thẻ HTML được bọc bởi nháy kép. Hãy thử so sánh các câu SQL và HTML dưới đây:

$sql = "SELECT user_id FROM user WHERE user_first_name = 'John' AND user_company_name = 'John\'s'";
$sql = 'SELECT user_id FROM user WHERE user_first_name = \'John\' AND user_company_name = \'John\\\'s\'';
echo '<span style="color: green;">This is a good look</span>';
echo "<span style="">It's hard to read this</span>";

Biểu thức so sánh trong điều kiện khối lệnh if

PHP dùng dấu bằng (=) để gán giá trị cho biến, hằng và cặp dấu == trong so sánh bằng. Một đoạn mã dưới đây sẽ không gặp vấn đề gì:

if ($string == 'a') {
    // do something
} else {
    // do something else
}

Tuy nhiên nếu bất cẩn bạn quên mất một dấu bằng thì sẽ trở thành việc gán giá trị a cho biến $string chứ không phải so sánh $string với giá trị a nữa:

if ($string = 'a') {
    // do something
} else {
    // do something else
}

Vì việc gán dữ liệu luôn thành công nên luôn trả lại giá trị true và cũng luôn luôn chỉ có đoạn lệnh “do something” được thực hiện còn “do something else” sẽ không bao giờ được thực thi.

Một cách đơn giản để tránh khỏi sự bất cẩn này là đặt giá trị cần so sánh phía trước và biến ở phía sau:

if ('a' == $string) {
    // do something
} else {
    // do something else
}

Nếu bạn quên mất một dấu “=” thì PHP sẽ báo lỗi ngay vì không thể gán giá trị cho một chuỗi tường minh

Tận dụng PHPDoc

Việc comment trong source sẽ khiến người phát triển sau hiểu được các đoạn mã viết gì. PHPDoc là các đoạn comment có quy tắc thường được đặt ở đầu file, trước class, thuộc tính, hằng, biến… để giúp PHPDocumentor tự động tạo document. Hầu hết các PHP IDEs phổ biến (Zend Studio, Eclipse PDT…) đều hỗ trợ PHPDoc. Chúng sẽ phân tích PHPDoc và đưa ra hướng dẫn gợi ý khi bạn gọi đến lớp hay hàm nào đó. Điều này hữu ích khi trong một project có hàng trăm hàm/lớp và bạn không thể nào nhớ tất cả chúng.

PHPDoc có một số quy tắc và cấu trúc bạn có thể tham khảo tại đây

Dưới đây là một ví dụ sử dụng PHPDoc:

/**
 * Ducthuans: PHP code library developed by NGUYEN Duc Thuan
 *
 * @package     Ducthuans
 * @author      Nguyen Duc Thuan
 * @link        http://www.ducthuan.info
 * @copyright   Copyright (c) 2008, Nguyen Duc Thuan
 * @license     http://www.opensource.org/licenses/bsd-license.php
 * @Project     (This is a bad tag because it is not supported by PHPDocumentor)
 */
class Ducthuans
{
 
    /**
     * Holds Ducthuans' instance
     *
     * @var Ducthuans
     */
    private static $_instance = null;
 
    /**
     * Initializes and returns Ducthuans' instance
     *
     * @return Ducthuans
     */
    public static function &getInstance()
    {
        if (null === self::$_instance) {
            self::$_instance = new self();
        }
 
        return self::$_instance;
    }
 
    /**
     * Disables creating instance directly from public
     *
     */
    private function __construct()
    {}
 
    /**
     * Disables cloning object
     *
     */
    private function __clone()
    {}
 
    // I cannot understand what the hell this method does without reading the code line by line... :-w
    public function badDefinition ($paramOne, $paramTwo)
    {
        foreach ($paramTwo as $item) {
            doSomething($paramOne, $item);
        }
 
        return doAnotherThing();
    }
 
    /**
     * These are some lines
     * to describe what the method does
     *
     * @param string    $paramOne This is a string to be passed in function 'doSomething'
     * @param array     $paramTwo This is an array to do something
     * @param integer   Good, I know this method will return an INTEGER value
     */
    public function goodDefinition ($paramOne, $paramTwo)
    {
        foreach ($paramTwo as $item) {
            doSomething($paramOne, $item);
        }
 
        return doAnotherThing();
    }
}

(Nguồn SinhvienIT)