Giới thiệu

PHP là gì?

Cụm ký tự PHP ban đầu được viết tắt bởi cụm từ Personal Home Page, và được phát triển từ năm 1994 bởi Rasmus Lerdorf. Lúc đầu chỉ là một bộ đặc tả Perl, được sử dụng để lưu dấu vết người dùng trên các trang web. Sau đó, Rasmus Lerdorf đã phát triển PHP như là một máy đặc tả (Scripting engine). Vào giữa năm 1997, PHP đã được phát triển nhanh chóng trong sự yêu thích của nhiều người. PHP đã không còn là một dự án cá nhân của Rasmus Lerdorf và đã trở thành một công nghệ web quan trọng. Zeev Suraski và Andi Gutmans đã hoàn thiện việc phân tích cú pháp cho ngôn ngữ để rồi tháng 6 năm 1998, PHP3 đã ra đời (phiên bản này có phần mở rộng là *.php3). Cho đến tận thời điểm đó, PHP chưa một lần được phát triển chính thức, một yêu cầu viết lại bộ đặc tả được đưa ra, ngay sau đó PHP4 ra đời (phiên bản này có phần mở rộng không phải là *.php4 mà là *.php). PHP4 nhanh hơn so với PHP3 rất nhiều.

PHP bây giờ được gọi là "PHP: Hypertext PreProcesor" với phiên bản phát hành vào ngày 19/02/2015 là 5.6.6 .

Tại sao phải sử dụng PHP?

Ta hoàn toàn có thể xây dựng được những trang web bằng ngôn ngữ HTML (HyperText Markup Language). Tuy nhiên đây chỉ là những trang web tĩnh, nghĩa là chúng chỉ chứa đựng một nội dung cụ thể với những dòng văn bản và hình ảnh đơn thuần, và có thể được sự hỗ trợ bởi CSS và JavaScript. Những trang web như vậy người ta thường gọi là client-side. Tuy nhiên, Internet và Intranet đã được sử dụng cho các ứng dụng cần tới cơ sở dữ liệu. Các trang ứng dụng như vậy được gọi là trang web động, bởi vì nội dung của chúng thay đổi tùy thuộc vào dữ liệu và người sử dụng. PHP là ngôn ngữ làm được những điều như vậy. Bằng cách chạy chương trình PHP trên máy chủ Web server, bạn có thể tạo ra các ứng dụng có sự tương tác với cơ sở dữ liệu để tạo ra những trang web và đây được gọi là trang web động. Chúng ta hãy xem xét cách hoạt động của trang web được viết bằng ngôn ngữ HTML và PHP như thế nào.

Với các trang HTML, khi có yêu cầu tới một trang web từ phía người sử dụng (browser), web server sẽ thực hiện ba bước sau:

Bước 1: Đọc yêu cầu từ phía browser

Bước 2: Tìm trang web trên server

Bước 3: Gửi trang web đó trở lại cho browser (nếu tìm thấy) qua mạng Internet hoặc Intranet.

Còn với các trang PHP, khác với các trang HTML, khi một trang PHP được yêu cầu thì Web server sẽ phân tích và thi hành các đoạn mã PHP để tạo ra trang HTML. Điều đó được thể hiện bằng bốn bớc sau:

Bước 1: Đọc yêu cầu tử phía browser

Bước 2: Tìm trang web trên server

Bước 3: Thực hiện các đoạn mã PHP trên trang web đó để sửa đổi nội dung của trang

Bước 4: Gửi trở lại nội dung cho browser (đây là trang HTML có thể hiển thị được bởi trình duyệt Internet Explorer hoặc trình duyệt nào đó).

Tóm lại, sự khác nhau giữa HTML và PHP là HTML không được thực hiện trên máy chủ Web server, còn các trang *.php viết bằng các đoạn mã PHP được thực hiện trên máy chủ Web server do đó nó linh động và mềm dẻo hơn.

Hiện tại, đa số các web site được thiết kế bằng ngôn ngữ PHP và có thể nói PHP được dùng để tạo mọi loại web site từ nhỏ đến lớn, mạng xã hội được coi là lớn nhất thế giới hiện nay Facebook chính là một sản phẩm của PHP.

Những điểm mạnh của PHP

- PHP thực hiện với tốc độ rất nhanh và hiệu quả. Một Server bình thường có thể đáp ứng được hàng triệu truy cập tới trong một ngày. PHP hỗ trợ kết nối tới rất nhiều hệ CSDL khác nhau: như PostgreSQL, mSQL, Oracle, dbm, filePro, Hyperware, informix, InterBase, Sybase, ... Ngoài ra còn hỗ trợ kết nối với ODBC thông qua đó có thể kết nối với nhiều ngôn ngữ khác mà ODBC hỗ trợ.

- Thời gian để hoàn thành một web site bằng ngôn ngữ PHP có thể nói là rất nhanh, không một ngôn ngữ nào có thể so sánh được với PHP về điều này, đặc biệt thời gian thiết kế còn có thể nhanh hơn nữa nếu web site được thiết kế bằng một framework như Laravel, Joomla, Zend, Code Ignitor, ...

- PHP cung cấp một hệ thống thư viện phong phú. Do PHP ngay từ đầu được thiết kế nhằm mục đích xây dựng và phát triển các ứng dụng trên web nên PHP cung cấp rất nhiều hàm xây dựng sẵn giúp thực hiện các công việc rất dễ dàng: gửi, nhận mail, làm việc với các cookie, session, và nhiều thứ khác nữa.

- PHP là một ngôn ngữ rất dễ dùng, dễ học và đơn giản hơn nhiều so với các ngôn ngữ khác như Perl, Java. Nếu bạn đã biết ngôn ngữ C thì mọi việc sẽ hoàn toàn thuận lợi.

- PHP có thể sử dụng được trên nhiều hệ điều hành, chúng ta có thể viết chúng trên Unix, Linux và các phiên bản của Windows, và có thể đem mã PHP này chạy trên các hệ điều hành khác mà không phải sửa đổi lại mã.

- PHP là ngôn ngữ mã nguồn mở.

Kiểu dữ liệu

PHP có ba kiểu dữ liệu cơ bản: interger, doublestring.

Ngoài ra còn có các kiểu dữ liệu khác (nhưng không phải các kiểu dữ liệu cơ bản) như array (các kiểu dữ liệu mảng), object (các kiểu dữ liệu đối tượng), ...

interger là kiểu dữ liệu nguyên chiếm 4 byte bộ nhớ, giá trị của nó trong khoảng từ -2 tỷ tới +2 tỷ.

double là kiểu số thực, phạm vi biểu diễn từ -10^308 đến +10^308.

string dùng để chứa các giá trị bao gồm các ký tự và con số.

Ví dụ:

2                  // đây là kiểu interger

1.0               // đây là kiểu double

“2”               // đây là kiểu string

“2 hours”       // đây là một kiểu string khác

Hằng (Constant)

Hằng là giá trị không đổi. Chúng ta thường dùng hằng để lưu các giá trị không đổi trong suốt chương trình như: nhiệt độ, các giá trị thời gian chỉ sự chuyển giao giữa sáng, chưa, chiều, tối,...

Khai báo hằng bằng hàm define()

Ta dùng hàm define() để khai báo hằng.

Cú pháp:

define(“Tên_hằng”, “Giá_trị”);

Ví dụ:

define(“COMPANY”, “Phop’s Bicycles”); //Khai báo hằng có tên COMPANY và giá trị là Phop’s Bicycles

define(“YELLOW”, ”#FFFF00”);

define(“VERSION”, 4);

define(“NL”, ”<BR>\n”);

Trong ví dụ trên chúng ta đã dùng hàm define() để khai báo hằng NL. Hằng này là một thẻ ngắt dòng trong HTML.

Cách dùng hằng:

Chúng ta sẽ sử dụng các hằng trong PHP như sau:

echo (“Employment at “. COMPANY. NL); //Dùng dấu chấm '.' để nối chuỗi trong PHP

Cách viết trên cũng giống như cách viết sau:

echo(“Employment at Phop’s Bicycles<BR>\n”);

Chú ý: hằng phải ở ngoài hai dấu “”. Trường hợp sau là không có hiệu lực: echo(“Employment at COMPANY NL”);. Khi thực hiện nó sẽ cho kết quả là: “Employment at COMPANY NL”.

Hàm defined():

Hàm này dùng để kiểm tra xem một hằng nào đó đã được khai báo chưa.

Ví dụ:

if(defined(“YELLOW”)){

echo (“<BODY BGCOLOR=”. YELLOW. “>\n”);

}

Các hằng đã được định nghĩa sẵn trong PHP (Built-in Constants)

Để hỗ trợ cho người lập trình, PHP cung cấp sẵn các hằng như: các hằng môi trường, các hằng của Web server Apache, ... Người lập trình có thể sử dụng hàm phpinfo() để xem các giá trị này.

<HTML>

<!--phpinfo() -->

<BODY>

<? phpinfo(); ?>

</BODY>

</HTML>

+ Hằng số nguyên: là giá trị có kiểu integer.Ví dụ: 10

+ Hằng số thực: là giá trị có kiểu double.Ví dụ: 10.00

+ Hằng chuỗi: là một xâu ký tự đặt trong dấu ngoặc đơn hoặc kép. Ví dụ: “Ngôn ngữ lập trình PHP” hoặc 'Ngôn ngữ lập trình PHP'.

Biến (Variable)

Cũng giống với C/C++, PHP không có khái niệm TRUE Và FALSE. Các  giá trị FALSE là những giá trị bằng 0 hoặc xâu rỗng, các giá trị TRUE là những giá trị còn lại.

Khi sử dụng biến chúng ta không cần khai báo kiểu.

Cách khai báo biến trong PHP:

$Tên_biến;

Hoặc:

$Tên_biến = Giá_trị;

Lưu ý rằng một biến trong PHP có thể nhận giá trị có kiểu bất kỳ.

Ví dụ:

$a = 1;  //$a là một biến kiểu integer

$a = 1.2;  //bây giờ $a là một biến kiểu double

$a = “A”;  //bây giờ $a lại là một biến kiểu string.

+ Nếu như thực hiện phép toán giữa biến có kiểu số và kiểu string, PHP sẽ coi chuỗi là một dãy số như sau:

$str = “222B Baker Street”;

Ta thấy biến $str có giá trị kiểu string, và nếu cộng số 3 với giá trị này thì:

$x = 3 + $str; //$x = 225

, khi đó biến $x nhận được giá trị 255 vì PHP đã cộng 3 với ba số đầu.

Nhưng nếu ta in giá trị của biến $str thì:

echo ($str); //print: “222B Baker Street”

Chú ý rằng các phép toán giữa số và chuỗi chỉ đúng khi ký tự đầu của chuỗi là số.

+ Ta cũng có thể làm thay đổi kiểu giá trị của một biến bằng cách ép kiểu

$a = 11.2; //biến $a có kiểu double

$a = (int)$a; //bây giờ $a có kiểu integer, giá trị là 11

$a = (double)$a; //bây giờ $a lại có kiểu double, giá trị là 11.0

$b = (string)$a; //biến $b có kiểu string, giá trị là “11”

Cũng cần biết rằng PHP tự động chuyển đổi kiểu rất tốt. Nếu thật sự cần thiết chúng ta mới phải dùng cách trên.

Các hàm làm việc với biến:

gettype():

Hàm này trả lại kiểu của một biến nào đó.

Giá trị trả về có thể là “integer”, “double”, “string”, “array”, “object”, “class” hoặc “unknown type” .

Ví dụ:

if(gettype($user_input) == “integer”){

$age = $user_input;

}

settype():

Hàm này ép kiểu cho một biến nào đó. Nếu thành công hàm trả về giá trị 1 (true), ngược lại là 0 (false).

Ví du:

$a = 7.5;

settype($a, “integer”);

if (settype($a, “array”)){

echo (“Conversion succeeded.“);

}

else{

echo (Conversion error.“);

}

isset() và unset():

Hàm isset() kiểm tra một biến đã được gán giá trị hay chưa, hàm unset() sẽ giải phóng bộ nhớ cho một biến nào đó.

Ví dụ:

$id = “323bb”;

if (isset($id)){

echo (“Dữ liệu đã được gán”);

}

else{

echo (“Dữ liệu chưa được gán”);

}

unset($id);

if(!isset($id)){

echo (“Dữ liệu đã được giải phóng”);

}

empty():

Cũng giống hàm isset(), hàm empty() sẽ trả về giá trị 1 (true) nếu một biến là rỗng và 0 (false) nếu ngược lại.

Đối với biến có kiểu số giá trị bằng 0 được coi là rỗng, biến kiểu string được coi là rỗng nếu xâu là xâu rỗng.

Ví dụ:

echo empty($new) ; //true

$new = 1;

echo empty($new); //false

$new = “”;

echo empty($new); //true

$new = 0;

echo empty($new); //true

$new = “So 323”;

echo empty($new); //false

unset($new);

echo empty($new); //true

Phép toán (Operator)

Phép toán số học

Phép cộng: +           .Ví dụ: 6 + 4 = 10

Phép trừ: -              .Ví dụ: 7 - 3 = 4

Phép nhân: *           .Ví dụ: 7 * 3 = 21

Phép chia thực: /      .Ví dụ: 7 / 3 = 2.33333333...

Phép chia dư: %       .Ví dụ: 9 % 2 =1

Phép gán

Ký hiệu: =

Ví dụ:

$x = 1;

$y = $x + 1;

$length = $area / $width;

Phép gán rút gọn:

Ví dụ:

$h += $i  <=>  $h = $h + $i

$h -= $i  <=>  $h = $h - $i

$h *= $i  <=>  $h = $h * $i

$h /= $i  <=>  $h = $h / $i

$h %= $i  <=>  $h = $h % $i

Các phép toán quan hệ (so sánh)

So sánh bằng: ==

So sánh nhỏ hơn: <

So sánh lớn hơn: >

Nhỏ hơn hoặc bằng: <=

Lớn hơn hoặc bằng: >=

So sánh khác: != hoặc <>

Các phép so sánh thường dùng kiểm tra điều kiện trong các câu lệnh điều khiển mà ta sẽ học ở bài sau.

Phép toán logic

Phép toán logic cùng với toán hạng tạo thành biểu thức logic. Biểu thức logic có thể có giá trị là 1 (true) hoặc 0 (false).

Phép &&:

Phép AND logic.

Tuân theo quy tắc:

1&&1=1

1&&0=0

0&&1=0

0&&0=0

Phép ||:

Phép OR logic.

Tuân theo quy tắc:

1||1=1

1||0=1

0||1=1

0||0=0

Phép !:

Phép NOT logic.

Tuân theo quy tắc:

!1=0

!0=1

Phép toán với biến kiểu string

Ta sử dụng dấu chấm (.) để ghép (nối) hai biến kiểu string với nhau.

Ví dụ:

$first = “Phineas”;

$last = “Phop”;

$full = $first . “” . $last;

echo ($full); // $full = “Phineas Phop”;

Ta cũng có thể ghép hai xâu như sau:

echo ($last. “’s Bicycles”); //print: Phop’s Bicycles

Ta cũng có thể đặt biến vào trong chuỗi như ví dụ sau:

echo (“$last’s Bicycles”);

Các phép toán thao tác mức bit (nhị phân)

Các phép toán thao tác mức bit tác động lên từng bit của toán hạng.

Phép &:

Phép AND nhị phân.

Tuân theo quy tắc:

1&1=1

1&0=0

0&1=0

0&0=0

Phép |:

Phép OR nhị phân.

Tuân theo quy tắc:

1|1=1

1|0=1

0|1=1

0|0=0

Phép ^:

Phép XOR nhị phân.

Tuân theo quy tắc:

1^1=0

1^0=1

0^1=1

0^0=0

Phép ~:

Phép NOT nhị phân.

Tuân theo công thức:

~A=-(A+1)

Ví dụ:

~10=-(10+1)=-11

Phép >>:

Phép dịch phải, giá trị của một số sẽ giảm 2 luỹ thừa n lần (lấy phần nguyên) nếu dịch phải n bit.

Bản chất của phép >> là bỏ đi n bit bên phải của số nhị phân.

Ví dụ:

7>>2; //cho kết quả là 1

11 >> 2; //cho kết quả là 2

Phép <<:

Phép dịch trái, giá trị của một số sẽ tăng 2 luỹ thừa n lần nếu dịch trái n bit.

Bản chất của phép << là thêm vào bên phải số nhị phân n bit 0.

Ví dụ: 

2 << 2; //cho kết quả là 8

11 << 2; //cho kết quả là 88

Các phép toán tăng giảm

Phép tăng:

Phép tăng (toán tử tăng) tăng giá trị của toán hạng lên một đơn vị.

$a++: $a được sử dụng rồi mới tăng

++$a: $a tăng rồi mới được sử dụng

Phép giảm:

Tương tự như phép tăng, khác là giá trị bị giảm đi một đơn vị.

$a--: $a được sử dụng rồi mới giảm

--$a: $a giảm rồi mới được sử dụng

Ví dụ:

$a = 10; // $a bằng 10

$b = $a++ ; // $a bằng 11 nhưng $b bằng 10

$a = 10; // $a bằng 10

$b = --$a; // $a bằng 9 và $b bằng 9

Phép toán điều kiện ba ngôi:

Ký hiệu: ?:

Phép toán điều kiện cùng với toán hạng tạo nên biểu thức điều kiện.

Ta ký hiệu e1, e2, e3 là ba toán hạng.

Biểu thức có dạng: e1 ? e2: e3

Nếu e1 != 0 thì giá trị của biểu thức điều kiện là e2

Nếu e1 == 0 thì giá trị của biểu thức điều kiện là e3

Ví dụ:

$max = $a>$b ? $a : $b; // nếu $a>$b thì $max=$a, nếu không thì $max=$b

Phép toán sizeof (đối tượng)

Phép toán sizeof cho biết kích thước (tính bằng byte) ô nhớ mà đối tượng chiếm trong bộ nhớ. Đối tượng ở đây có kiểu là integer, double, string.

Ví dụ:

$a = 10;

echo sizeof($a); //sẽ in ra màn hình là: 4

if-else

Dạng 1

if(Điều_kiện) {

  Khối_lệnh;

}

Ý nghĩa:

+ Nếu Điều_kiện khác không, thì Khối_lệnh được thực hiện.

+ Nếu Điều_kiện bằng không, thì Khối_lệnh không được thực hiện.

Dạng 2

if(Điều_kiện) {

  Khối_lệnh1;

}

else{

  Khối_lệnh2;

}

Ý nghĩa:

+ Nếu Điều_kiện khác không, thì Khối_lệnh1 được thực hiện

+ Nếu Điều_kiện bằng không, thì Khối_lệnh2 được thực hiện.

Chú ý:

Nếu lượng else bằng lượng if thì else thuộc về if gần nhất theo từng cặp từ trong ra ngoài.

Ví dụ:

$a = 10; $b = 10;

$c = 3; $d = 3;

$e = 12; $f = 8;

if($a == $b)

  if($c == $d)

    if($e == $f)

      $max = $e;

    else

      $max = $f;

    else

      $max = $d;

  else    

    $max = $b;

echo $max; //sẽ in ra: max = 8

+ Nếu lượng else ít hơn lượng if thì else thuộc về if ngần nhất theo từng cặp từ trong ra ngoài.

Ví dụ:

<?php

if ($a == $b)

  if ($c == $d)

    $max = 0;

else

  $max = $d;

?>

Tương đương với:

<?php

if ($a == $b) {

  if ($c == $d)

    $max = 0;

}

else

  $max = $b;

?>

* Khối_lệnh2 của dạng 2 là elseif:

Bắt nguồn từ:            Có thể viết lại như sau:

if ( Điều_kiện1 )          if ( Điều_kiện1 )

{                                {

   Khối_lệnh1;               Khối_lệnh1;

}                                }

else                           elseif (Điều_kiện2)

   if ( Điều_kiện2 )       {

   {                               Khối_lệnh2;

      Khối_lệnh2;          }

   }                             elseif (Điều_kiện3)

  else                         {

      if ( Điều_kiện3 )      Khối_lệnh3;

      {                          }

         Khối_lệnh3;         ...

      }                          elseif (Điều_kiệni)

     ...                         {

     else                        Khối_lệnhi;

       if ( Điều_kiệni )    }

         {                         ...

          Khối_lệnhi;       else

         }                       {

       ...                         Khối_lệnhn;

       else                    }

         {

          Khối_lệnhn;

         }

Câu lệnh elseif tạo ra lệnh rẽ nhánh có điều kiện trong đó thực hiện 1 trong n cách khác nhau.

- Nếu Điều_kiệni khác không (i = 1,..n-1) thì thực hiện Khối_lệnhi.

- Nếu Điều_kiệni bằng không (i = 1,..n-1) thì Khối_lệnhn được thực hiện.

switch-case

Cú pháp 

switch (Biểu_thức) {

  case Hằng1:

    Khối_lệnh1;

    break;

  case Hằng2:

    Khối_lệnh2;

    break;

  ...

  case Hằngn:

    Khối_lệnhn;

    break;

  default:

    Khối_lệnh;

}

Câu lệnh switch là câu lệnh rẽ nhánh có điều kiện, trong đó thực hiện 1 trong n mục rẽ nhánh.

+ Nếu giá trị của Biểu_thức = một trong các Hằng thì Khối_lệnh tương ứng dưới Hằng đó sẽ được thực hiện cho đến khi gặp lệnh break.

+ Nếu giá trị của Biểu_thức != tất cả các Hằng mà có nhánh default thì Khối_lệnh sau default sẽ được thực hiện.

+ default là không bắt buộc trong switch-case.

Ví dụ:

<?php

$a = 4;

$b = 5;

$c = 6;

$d = 6;

switch ($d) {

  case $a:

    echo"four";

    break;

  case $b:

    echo"five";

    break;

  case $c:

    echo"six";

    break;

  default:

    echo $d;

}

?>

Điều kiện switch-case ở trên kiểm tra giá trị chứa trong biến $d, nếu nó bằng giá trị chứa trong biến $a thì in ra "four", nếu bằng giá trị chứa trong biến $b thì in ra "five", nếu nó bằng giá trị chứa trong biến $c thì in ra "six", nếu nó không bằng giá trị chứa trong bất kỳ biến nào trong ba biến $a, $b hay $c thì in ra chính giá trị trong $d.

Lưu ý: PHP không bắt buộc bạn phải đặt default ở cuối như cú pháp ở trên, tức là bạn có thể đặt nó ở vị trí đầu tiên. Xét ví dụ dưới đây:

<?php
$a 
'Apple';
switch (
$a) {
    default:
        echo 
'$a không phải là cam<br>';
    case 
'Orange':
        echo 
'$a là cam';
}

?>

Ở đoạn lệnh trên thì default được đặt trước case nhưng không hề phát sinh lỗi. Kết quả của đoạn lệnh trên là:

Apple không phải là cam
Apple là cam

Vòng lặp for

Cú pháp

for(Khởi_tạo; Điều_kiện; Tăng_giảm) {

  Khối_lệnh;

}

Hoạt động

Bước 1: Thực hiện phần Khởi_tạo, phần này sẽ khởi tạo giá trị ban đầu cho biến đếm (hay còn gọi là biến chạy).

Bước 2: Kiểm tra Điều_kiện

- Nếu Điều_kiện đúng thì thực hiện Khối_lệnh và sang Bước 3.

- Nếu Điều_kiện sai thì kết thúc vòng lặp for

Bước 3: Thực hiện Tăng_giảm, phần này sẽ làm thay đổi giá trị của biến đếm theo hướng tăng hoặc giảm giá trị và quay lại Bước 2.

+ Mỗi thành phần Khởi_tạo, Điều_kiện và Tăng_giảm đều có thể gồm nhiều biểu thức. Khi đó mỗi biểu thức được viết cách nhau một dấu phẩy (,).

+ Các biểu thức được tính lần lượt từ trái qua phải

+ Biểu thức trong cùng của phần Điều_kiện quyết định tính đúng sai của Điều_kiện.

Ví dụ:

<?php

for($i = 0; $j = 4,$i < $j; $i++,$j--){

 echo"$i =" . $i. ", j = " . $j. "<br>";

}

?>   

+ Có thể vắng mặt bất kể thành phần nào trong ba thành phần của for. Nếu vắng mặt phần Điều_kiện thì hiểu là điều kiện luôn đúng và vòng lặp for sẽ chạy vô hạn lần. Lưu ý là mặc dù vắng mặt nhưng vẫn phải có dấu chấm phẩy (;).

Ví dụ:

<?php

for( ; ; ) {

  if(my_function() == stop)

    break;

}

?>

+Nếu vắng cả phần Khởi_tạo và phần Tăng_giảm thì:

for( ; Điều_kiện ; ) {

  Khối_lệnh;

}

tương đương với:

while(Điều_kiện) {

  Khối_lệnh;

}

Vòng lặp while

Video

 

Cú pháp:

while(Điều_kiện) {

  Khối_lệnh;

}

while được coi là vòng lặp không xác định, tức là bạn có thể không biết trước được số lần lặp của while.

Hoạt động:

Bước 1: Kiểm tra Điều_kiện.

- Nếu Điều_kiện đúng thì thực hiện Khối_lệnh.

- Nếu Điều_kiện sai, kết thúc vòng while.

Bước 2: Thực hiện Khối_lệnh rồi quay Bước 1.

Chú ý:

+ Điều_kiện có thể bao gồm nhiều Điều_kiện con. Khi đó các Điều_kiện được viết cách nhau một dấu phẩy, và được tính lần lượt từ trái qua phải. Điều_kiện cuối cùng quyết định thực hiện Khối_lệnh.

+ Không được phép vắng mặt Điều_kiện

+ Để tạo chu trình vô tận thì bạn có thể làm như sau:

while(1) {

  ...

  if (Điều_kiện)

    break;

  ...

}

Ví dụ:

$i = 11;

while(--$i) {

  if (my_function($i) == error){

    break;

}

++ $number;

}

Vòng lặp do-while

Video:

Cú pháp:

do{

Khối_lệnh;

}while(Điều_kiện);

do...while cũng được coi là vòng lặp không xác định vì có thể bạn không  biết trước được số lần lặp của nó.

Hoạt động:

Bước 1: Thực hiện Khối_lệnh

Bước 2: Kiếm tra Điều_kiện

- Nếu Điều_kiện đúng thì quay lại Bước 1

- Nếu Điều_kiện sai thì kết thúc vòng lặp.

Ví dụ:

<?php
  echo"<select name='month'>";
  echo"<option hidden>-Select a month-</option>";
  $i=1;
  do{
    echo"<option value='$i'>$i</option>";
  }while($i++<12);
  echo"</select>";
?>

foreach

Cú pháp:

foreach($Tên_mảng as $Tên_biến) {

  Khối_lệnh;

}

foreach được coi là vòng lặp xác định vì bạn có thể biết trước được số lần lặp của nó, số lần lặp của foreach bằng số phần từ của Tên_mảng.

Hoạt động:

Bước 1: Lấy từng phần tử của Tên_mảng gán cho Tên_biến rồi thực hiện Khối_lệnh.

Bước 2: Thực hiện Bước 1 cho đến khi lấy hết các phần tử của Tên_mảng thì kết thúc vòng lặp.

Ví dụ:

<?php

$monhoc=array("HTML5","CSS3","C","HTML","CSS","jQuery","SQL","PHP");

echo ("Các môn học hiện có:<br>");

foreach($monhoc as $tenmonhoc){

echo $tenmonhoc."<br>";

}

?>

break và continue

break

Phiên bản hỗ trợ: (PHP 4, PHP 5, PHP 7)

break dùng để thoát khỏi (hoặc kết thúc sự thực thi của) vòng lặp chứa nó; break áp dụng cho tất cả các loại vòng lặp (forforeachwhiledo-while). Ngoài ra, break còn dùng trong điều kiện hay cấu trúc switch-case để thoát khỏi switch.

break trong PHP còn chấp nhận một đối số tùy chọn là một số nguyên dương (>=1) để báo cho trình dịch biết là sẽ kết thúc những mức lồng vòng lặp hoặc cấu trúc ở mức bao nhiêu. Mức mặc định là 1, tức là dừng vòng lặp hoặc switch trực tiếp chứa nó. Lưu ý là từ bản PHP 5.4.0 thì break sẽ không hỗ trợ đối số tùy chọn là một biến, ví dụ như $n=1; break $n; là sai.

<?php
$arr 
= array('one''two''three''four''stop''five');
while (list(, 
$val) = each($arr)) {
    if (
$val == 'stop') {
        break;    
/* Bạn cũng có thể viết là 'break 1;' */
    
}
    echo 
"$val<br />\n";
}


/* Sử dụng đối số tùy chọn. */

$i 0;
while (++
$i) {
    switch (
$i) {
    case 
5:
        echo 
"At 5<br />\n";
        break 
1;  /* Chỉ thoát khỏi switch (1 mức lồng). */
    
case 10:
        echo 
"At 10; quitting<br />\n";
        break 
2;  /* Thoát khỏi switch và while (2 mức lồng). */
    
default:
        break;
    }
}

?>

Lưu ý:

+ Nếu giá trị của đối số tùy chọn của break lớn hơn số mức lồng ngoài nó thì sẽ cảnh báo lỗi. Ở ví dụ trên, nếu thay break 2; thành break 3; thì sẽ phát sinh lỗi do break chỉ nằm trong 2 mức lồng.

+ break sẽ không làm việc trong tập tin được include, lúc đó kết quả trả về sẽ là lỗi như ví dụ dưới đây:

main.php:
<?php
switch ( $i )
{
  case 
'1'// Làm việc
    
echo "$i";
    break;
  case 
'2'// Làm việc
    
require( 'include1.php' );
    break;
  case 
'3'// Không làm việc
    
require( 'include2.php' );
    break;
  case 
'4'// Cũng không làm việc
    
require( 'include2.php' );
  default: 
// Làm việc
    
echo "$i";
}

?>

include1.php:
<?php
  
echo "$i";
?>

include2.php:
<?php
  
echo "$i";
  break;

?>

continue

Phiên bản áp dụng: PHP 4, PHP 5, PHP 7.

continue được sử dụng bên trong vòng lặp để bỏ qua lần lặp hiện thời, kiểm tra điều kiện cho lần lặp tiếp theo. Theo đó, tất cả các câu lệnh phía sau continue trong khối lệnh của vòng lặp sẽ bị bỏ qua (không thực hiện).

continue cũng chấp nhận một đối số là một số nguyên dương thể hiện việc bỏ qua lần lặp hiện tại của các mức lồng ngoài tương ứng. Giá trị mặc định là 1 và không được lớn hơn số mức lồng ngoài nó.

Ví dụ:

<?php
while (list($key$value) = each($arr)) {
    if (!(
$key 2)) { // bỏ qua số lẻ
        
continue;
    }
    
do_something_odd($value);
}


$i 0;
while (
$i++ < 5) {
    echo 
"Outer<br />\n";
    while (
1) {
        echo 
"Middle<br />\n";
        while (
1) {
            echo 
"Inner<br />\n";
            continue 
3;
        }
        echo 
"This never gets output.<br />\n";
    }
    echo 
"Neither does this.<br />\n";
}

?>

 

Ở đoạn lệnh trên, continue 3; sẽ bỏ qua lần lặp hiện thời của vòng lặp while ở mức 3. Kết quả đoạn mã trên sẽ in ra:

Outer
Middle
Inner
Outer
Middle
Inner
Outer
Middle
Inner
Outer
Middle
Inner
Outer
Middle
Inner

Mảng (Array) một chiều

Mảng trong PHP là một tập hợp bao gồm nhiều phần tử có cùng tên nhưng khác nhau về chỉ số (các chỉ số này là tùy biến). Với ngôn ngữ lập trình C, các phần tử của mảng có cùng kiểu dữ liệu, nhưng với PHP thì mềm dẻo hơn, các phần tử của mảng không nhất thiết phải cùng kiểu.

Khai báo mảng một chiều

Ta có thể khai báo mảng bằng cách gán tên mảng với dấu đóng mở ngoặc vuông không có chỉ số. Chúng ta hãy xét ví dụ sau:

$countries[] = "cr";

$countries[] = "de";

$countries[] = "us";

Ví dụ trên tạo ra một mảng gồm ba phần tử có chỉ số là 0, 1 và 2.

Việc đó cũng tương tự như ta gán:

$countries[0] = "cr";

$countries[1] = "de";

$countries[2] = "us";

Ngoài ra các chỉ số của mảng không nhất thiết phải tăng dần mà có thể được khai báo như sau:

$countries[50] = "cr";

$countries[20] = "de";

$countries[10] = "us";

echo"$countries[20]"; //sẽ in ra: de

Khi đó để thêm một phần tử mới vào mảng chúng ta có thể viết:

$countries[] = "uk"; //chỉ số sẽ là 51

Một phần tử mới được thêm vào với chỉ số là chỉ số lớn nhất của mảng cộng thêm một. Ngoài ra cũng có thể khai báo mảng một chiều bằng câu lệnh array như sau:

$countries = array (“cr”, “de”, “us”);

echo“$countries[2]”; //sẽ in ra: us

Để chỉ số không bắt đầu từ 0 ta có thể khai báo lại như sau:

$countries = array (1 => “cr”, “de”, “us”);

echo"$countries[2]"; //sẽ in ra: de

Toán tử => có thể được sử dụng trước bất kỳ một phần tử nào trong mảng. Ví dụ:

$countries = array (“cr”, 7 => “de”, “us”);

, thì khi đó phần tử có giá trị "cr" có chỉ số là 0 còn phần tử có giá trị "de" và "us" lần lượt là 7 và 8.

Khác với ngôn ngữ lập trình C, chỉ số của mảng một chiều không chỉ là các số nguyên mà còn là xâu ký tự. Ta có thể khai báo như sau:

$countries[“ca”] = “Canada”;

$countries[“cr”] = “Costa Rica”;

$countries[“de”] = “Germany”;

$countries[“uk”] = “United Kingdom”;

$countries[“us”] = “United States”;

echo (“$countries[“ca”]”); // print Canada

Nếu dùng array thì sẽ là:

$countries = array(“ca” => “Canada”,

                   “cr” => “Costa Rica”,

                   “de” => ‘Germany”,

                   “uk” => “United Kingdom”,

                   “us” => “United States”);

Làm việc với các phần tử của mảng

Vòng lặp foreach được coi là thích hợp để có thể tương tác với mảng. Vòng lặp foreach có thể thực hiện với hai cách thức như sau:

Cách thức 1:

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

foreach($arr as $value){

  echo"<br>$value";

}

Ví dụ trên sẽ in ra từng giá trị của các phần tử mảng.

Cách thức 2:

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

foreach($arr as $key=>$value){

  echo"<br>$key=>$value";

}

Ví dụ trên sẽ in ra từng chỉ số và giá trị của từng phần tử mảng.

Ngoài ra, có thể sử dụng vòng lặp for xét từng phần tử của mảng.

$countries = array("cr", "de", "us");

$num_elements = count($countries);

for($i=0; $i<$num_elements; $i++) {

  echo"$countries[$i] <BR>\n";

}

Ví dụ trên sẽ đúng khi chỉ số của các phần tử tăng dần đều. Nếu chỉ số các phần tử không theo một thứ tự nào cả ta có thể sử dụng hàm list() và each().

reset($countries);

while(list($key, $value)=each($countries)) {

  echo"Chỉ số $key, giá trị $value";

}

Để di chuyển con trỏ tới phần tử tiếp theo hoặc trước đó ta cũng có thể dùng hàm next() - hàm next() trả về là 1 (true) nếu phần tử tiếp theo không phải là phần tử cuối cùng, ngược lại là 0 (false) và prev() - hàm prev() cho giá trị trả về là 1 (true) nếu phần tử tiếp theo không phải là phần tử đầu tiên, ngược lại là 0 (false). Hàm key () sẽ cho biết chỉ số và hàm current() sẽ cho biết giá trị của phần tử đó.

$arr=array(3, 4, 5, 6, 7);

do {

  $k=key($arr);

  $val=current($arr);

  echo"Phần tử $k = $val";

}while (next($arr));

Mảng hai chiều

Chúng ta có thể khai báo mảng hai chiều như sau:

$countries=array("Europs"=>array("de", "uk"),

                 "North America"=>array("ca", "cr", "us"));

echo $countries["Europs"][1]); //in ra: "uk"

echo $countries["North America"][2]); //in ra: "us"

Ta có cấu trúc của mảng trên như sau:

$countries["Europs"][0]="de";

$countries["Europs"][1]="uk";

$countries["North America"][0]="ca";

$countries["North America"][1]="cr";

$countries["North America"][2]="us";

Cũng giống như mảng một chiều ta sẽ dùng vòng lặp như for, while, do ... while để duyệt qua các phần tử của mảng.

Ví dụ:

$countries=array("Europs"=>array("de", "uk"),

                 "North America"=>array("ca", "cr", "us"));

while(list($key1)=each($countries)) {

  echo"$key1: <BR>\n";

  while(list($key2, $val)=each($countries["$key1"])) {

    echo" - $val <BR>\n";

  }

}

Khi chạy chương trình sẽ in ra màn hình là:

Europ:

- de

- uk

North America:

- ca

- cr

- us

Phép toán mảng

Các phép toán mảng
Ví dụ Tên Kết quả
$a + $b Gộp Gộp mảng $a và mảng $b.
$a == $b So sánh bằng TRUE nếu $a và $b có cùng cặp key/value.
$a === $b Identity TRUE nếu $a và $b có cùng cặp key/value với cùng thứ tự và cùng kiểu.
$a != $b So sánh khác TRUE nếu $a không bằng $b.
$a <> $b So sánh khác TRUE nếu $a không bằng $b.
$a !== $b Non-identity TRUE nếu $a không giống $b.

Phép toán + trả về mảng bên phải nối vào mảng bên trái; đối với những khóa có sẵn trong cả hai mảng thì các phần tử đó của mảng bên trái sẽ được dùng đến, còn của mảng bên phải sẽ được bỏ qua.

Ví dụ 1: Gộp mảng.

<?php
$a 
= array("a" => "apple""b" => "banana");
$b = array("a" => "pear""b" => "strawberry""c" => "cherry");

$c $a $b// Gộp $a và $b
echo "Union of \$a and \$b: \n";
var_dump($c);

$c $b $a// Gộp $b và $a
echo "Union of \$b and \$a: \n";
var_dump($c);

$a += $b// Gộp $a += $b là $a và $b
echo "Union of \$a += \$b: \n";
var_dump($a);
?>

Khi thực thi thì kịch bản trên sẽ in ra như sau:

Union of $a and $b:
array(3) {
  ["a"]=>
  string(5) "apple"
  ["b"]=>
  string(6) "banana"
  ["c"]=>
  string(6) "cherry"
}
Union of $b and $a:
array(3) {
  ["a"]=>
  string(4) "pear"
  ["b"]=>
  string(10) "strawberry"
  ["c"]=>
  string(6) "cherry"
}
Union of $a += $b:
array(3) {
  'a' =>
  string(5) "apple"
  'b' =>
  string(6) "banana"
  'c' =>
  string(6) "cherry"
}

Các phần tử của mảng được hiểu là bằng nhau nếu chúng có cùng cặp key/value.

Ví dụ 2: So sánh mảng.

<?php
$a 
= array("apple""banana");
$b = array(=> "banana""0" => "apple");

var_dump($a == $b); // bool(true)
var_dump($a === $b); // bool(false)
?>

Xem thêm

Cài đặt AppServ V2.6

Video hướng dẫn cách cài đặt và sửa lỗi AppServ V2.6:

Tạo Database với AppServ

Video hướng dẫn cách tạo DataBase với AppServ:

Tạo Database với SQLyog

Video hướng dẫn cách tạo DataBase và liên kết bảng với SQLyog:

Tạo Site và duyệt trang

Video hướng dẫn cách tạo Site và duyệt trang PHP:

Giao diện bằng HTML5

Video hướng dẫn cách tạo khung giao diện bằng HTML5+CSS3:

Tạo liên kết điều hướng

Video hướng dẫn cách thiết lập liên kết điều hướng:

Connect to Host & DataBase

Video hướng dẫn cách thiết lập liên kết tới Host và DataBase:

Kết nối MySQL Server

PHP cung cấp hai hàm để kết nối với cơ sở dữ liệu MySQL Server là mysql_connect() và mysql_pconnect().

mysql_connect ()

Hàm này sẽ tạo ra một liên kết tới máy chủ MySQL.

Cú pháp:

int mysql_connect(string [hostname [:port] [:/path_to_socket]], string [username], string [password]);

Trong đó:

- hostname: Tên máy chủ cơ sở dữ liệu, nơi trang web sẽ chứa cơ sở dữ liệu. Giá trị ngầm định là “localhost”.

- :port: Địa chỉ cổng, nơi bộ máy cơ sở dữ liệu lắng nghe yêu cầu. Giá trị ngầm định là “:3306”.

- :/path_to_socket: Cũng giống như:port nhưng chỉ cho hệ điều hành UNIX. Giá trị ngầm định là ":/tmp/mysql.sock".

- username: Tên của người sử dụng được phép kết nối vào bộ máy cơ sở dữ liệu. Trên máy cục bộ username có giá trị mặc định là "root".

- password: Mật khẩu của người sử dụng để kết nối vào bộ máy cơ sở dữ liệu.

Hàm này trả về mã số nhận dạng nếu kết nối thành công, giá trị 0 (false) nếu việc kết nối có lỗi. Mã số nhận dạng này sẽ được sử dụng cho tất cả các yêu cầu tới bộ máy cơ sở dữ liệu sau này.

Sự kết nối này sẽ đóng lại khi gọi hàm mysql_close() hoặc kết thúc đoạn PHP script.

Ví dụ:

$ketnoi = mysql_connect("localhost", "root", "1234567");

mysql_pconnect()

Hàm này tạo ra một liên kết bền vững với máy chủ MySQL.

Cú pháp:

int mysql_pconnect(string [hostname [:port] [:/path_to_socket]], string [username], string [password]);

Tham số và giá trị trả về của hàm này cũng giống hàm mysql_connect(). Sự khác biết giữa hai hàm này là liên kết tới máy chủ MySQL không bị đóng lại kể cả khi kết thúc kịch bản (script) PHP hay gọi hàm mysql_close(). Mục đích của hàm này là luôn luôn duy trì liên kết tới máy chủ MySQL do luôn có sự yêu cầu tới máy chủ, tránh cho máy chủ phải tìm kiếm mã số nhận dạng mới từ đó giảm thời gian truy cập.

Chú ý: Hàm này chỉ thực hiện được khi PHP được định cấu hình như là một module của Web Server.

mysql_close()

Hàm này sẽ huỷ bỏ sự kết nối tới máy chủ MySQL.

Cú pháp:

int mysql_close(int [link_identifier]);

Tham số link_identifier là mã số nhận dạng tạo ra bởi hàm mysql_connect(). Hàm trả về là True nếu thành công, ngược lại là False.

 

Hàm thao tác trên DataBase

Các hàm thao tác trên CSDL bao gồm:

mysql_create_db()

Hàm này dùng để tạo cơ sở dữ liệu.

Cú pháp:

int mysql_create_db(string name, int [link_identifier]);

Trong đó:

- name: Tên của cơ sở dữ liệu cần tạo.

- link_identifier: Mã số nhận dạng được cấp bởi hàm mysql_connect(). Chúng ta hoàn toàn có thể gửi câu lệnh SQL để tạo cơ sở dữ liệu thông qua hàm mysql_query().

mysql_drop_db()

Hàm này dùng để xoá cơ sở dữ liệu.

Cú pháp:

int mysql_drop_db(string name, int [link_identifier]);

Trong đó:

- name: Tên của cơ sở dữ liệu cần xoá.

- link_identifier: Mã số nhận dạng được cấp bởi hàm mysql_connect(). Chúng ta hoàn toàn có thể gửi câu lệnh SQL để xoá cơ sở dữ liệu thông qua hàm mysql_query().

mysql_select_db()

Hàm này dùng để chọn cơ sở dữ liệu hoạt động trên website của bạn.

Cú pháp:

int mysql_select_db(string database_name, int [link_identifier]);

Trong đó:

- database_name: Tên của cơ sở dữ liệu mà sau này các hàm API khác của PHP sẽ thực hiện trên đó.

- link_identifier: Mã nhận dạng được cấp bởi hàm mysql_connect(). Câu lệnh này sẽ gắn tên cơ sở dữ liệu với mã nhận dạng, sau này khi làm việc với link_identifier sẽ bao gồm cả cơ sở dữ liệu được chọn.

 

Thao tác trên Dữ liệu (Data)

Dưới đây là danh sách các hàm thao tác trên dữ liệu (data) phổ biến:

mysql_query()

Hàm gửi câu lệnh SQL tới máy chủ MySQL.

Cú pháp:

int mysql_query(string query, [int link_identifier]);

Trong đó:

- query: Câu lệnh SQL cần gửi tới máy chủ MySQL.

- link_identifier: Mã số nhận dạng, nó phải được thực hiện trong hàm mysql_select_db() trước đó.

mysql_db_query()

Hàm gửi câu lệnh SQL tới máy chủ MySQL.

Cú pháp:

int mysql_db_query(string database, string query, int [link_identifier]);

Trong đó:

- database: Tên cơ sở dữ liệu câu lệnh SQL sẽ thực hiện trên đó.

- query: Câu lệnh SQL cần thực hiện.

- link_identifier: Mã số nhận dạng được cấp bởi hàm mysql_connect(). Hàm này chỉ rõ câu lệnh được thực hiện trên cơ sở dữ liệu nào nên trước đó không cần thực hiện hàm mysql_select_db();

mysql_insert_id()

Hàm lấy giá trị được sinh ra từ câu truy vấn INSERT trước.

Cú pháp:

int mysql_insert_id(int [link_identifier]);

, trong đó link_identifier là mã số nhận dạng được cấp bởi hàm mysql_connect(). Hàm này trả về giá trị id được sinh ra trong cột AUTO_INCREMENT bởi câu truy vấn trước đó. Điều này chỉ có tác dụng trên link_identifier được chỉ ra trong hàm, nếu gọi hàm trên mà không chỉ định tham số link_identifier thì liên kết được mở cuối cùng sẽ được chỉ định. Hàm mysql_insert_id() trả về giá trị 0 nếu câu truy vấn trước đó không sinh ra một giá trị AUTO_INCREMENT. Nếu ta muốn giữ lại giá trị cho lần sau, thì phải gọi hàm này ngay sau câu truy vấn sinh ra giá trị.

mysql_fetch_row()

Hàm trả về một mảng là giá trị của một bảng ghi hiện tại với chỉ số là số thứ tự của các trường (chỉ số bắt đầu từ 0). Sau đó hàm sẽ trỏ tới bảng ghi tiếp theo cho tới khi gặp bảng ghi cuối cùng hàm trả về giá trị false. Để truy xuất tới các giá trị của cột ta viết: tên_mảng[số thứ tự].

Cú pháp:

array mysql_fetch_row(int result_identifier);

, trong đó result_identifier là mã số trả về của hàm mysql_query() hoặc mysql_db_query().

Ví dụ:

<?php

$mysql = "select id, name from ds_thanhvien"; //câu lệnh SQL

$link = mysql_connect($host, $user, $password); //lấy mã

mysql_select_db( $database_name, $link);

$result = mysql_query($mysql, $link);

while ($row = mysql_fetch_row($result)){

echo $row[0];

echo $row[1];

}

?>

mysql_fetch_array()

Hàm trả về một mảng là giá trị của một bảng ghi hiện tại, sau đó hàm sẽ trỏ tới bảng ghi tiếp theo cho tới khi gặp bảng ghi cuối cùng hàm trả về giá trị false.

Cú pháp:

array mysql_fetch_array( int result_identifier [, int result_type]);

, trong đó result_identifier là mã số trả về của hàm mysql_query() hoặc mysql_db_query().

Để truy xuất đến các thành phần của cột: tên_biến_mảng["tên_trường"];

result_type là một hằng số có thể nhận các giá trị sau:

- MYSQL_NUM: chỉ trả lại một mảng chứa các chỉ số là số (giống như hàm mysql_fetch_row()).

- MYSQL_ASSOC: chỉ trả lại một mảng liên kết.

- MYSQL_BOTH: trả lại mảng chứa đựng các chỉ số gồm cả các con số và chỉ số liên kết.

Hàm này là sự mở rộng của hàm mysql_fetch_row(). Nó cho phép truy cập trường dữ liệu của mảng kết quả không chỉ thông qua các chỉ số là các số mà chúng có thể là tên của các trường dữ liệu. Điều này làm cho việc lập trình đơn giản và chính xác hơn.

Ví dụ:

<?php

$mysql = “select id, name from ds_thanhvien”;

$link = mysql_connect($host, $user, $password);

$result = mysql_db_query(“php”, $mysql);

while ($row = mysql_fetch_array($result)){

echo “user_id: “. $row[“id”].”<BR>\n”;

echo “user_id: “. $row[0].”<BR>\n”;

echo “user_name: “. $row[“name”].”<BR>\n”;

echo “user_name: “. $row[1].”<BR>\n”;

}

mysql_free_result ($result);

?>

mysql_fetch_object()

Hàm trả về một đối tượng là giá trị của một bảng ghi hiện thời. Sau đó hàm sẽ trỏ tới bảng ghi tiếp theo cho tới khi gặp bảng ghi cuối cùng hàm trả về giá trị false. Để truy xuất tới các giá trị của cột ta viết tên_object->tên_cột.

Cú pháp:

object mysql_fetch_object(int result_identifier);

, trong đó result_identifier là mã số trả về của hàm mysql_query() hoặc mysql_db_query().

Ví dụ:

<?php

$mysql = “select id, name from ds_thanhvien”;

$link = mysql_connect($host, $user, $password);

$result = mysql_db_query(“php”, $mysql);

while ($row = mysql_fetch_object($result)){

echo $row->id;

echo $row->name;

}

?>

mysql_fetch_assoc()

Hàm lấy về một dòng kết quả như là một mảng liên kết.

Cú pháp:

array mysql_fetch_assoc(int result_identifier);

, trong đó result_identifier là mã số trả về của hàm mysql_query() hoặc mysql_db_query().

Hàm trả về một mảng tương ứng với một bản ghi được lấy về và trả lại FALSE nếu không có bản ghi nào. Hàm này tương đương với hàm array mysql_fetch_array() với tham số result_type là: MYSQL_ASSOC.

Ví dụ:

<?php

$mysql = “select id, name from ds_thanhvien”;

$link = mysql_connect($host, $user, $password);

$result = mysql_db_query(“php”, $mysql);

while ($row = mysql_fetch_assoc($result)){

echo $row[“id”];

echo $row[“name”];

}

?>

mysql_data_seek()

Di chuyển con trỏ bên trong “tập kết quả” (có được sau khi câu truy vấn SELECT được thực hiện).

Cú pháp:

bool mysql_data_seek(int result_identifier, int row_number);

, trong đó result_identifier là mã số trả về của hàm mysql_query(), mysql_db_query(), mysql_list_tables(), mysql_list_dbs(), row_number là chỉ số của bản ghi mà cần đặt con trỏ vào.

Hàm trả về true nếu thành công, false nếu lỗi.

Hàm này sẽ di chuyển con trỏ bên trong “tập kết quả” (được chỉ rõ bởi tham đối result_identifier ) đến dòng có mã bằng tham đối row_number. Các dòng trong tập kết quả được bắt đầu từ 0.

Ví dụ:

<?php

$link = mysql_pconnect ($host, $user, $password) or die ("Could not connect”);

$query = “SELECT last_name, first_name FROM friends”;

$result = mysql_db_query (“php”,$query) or die ("Query failedã);

# fetch rows in reverse order

for($i = mysql_num_rows ($result) - 1; $i >=0; $i--){

if (!Mysql_data_seek ($result, $i)){

printf ("Cannot seek to row %d\n”, $i);

continue;

}

if(!($row = mysql_fetch_object ($result)))

continue;

printf ("%s %s<BR>\n”, $row->last_name, $row->first_name);

}

mysql_free_result ($result);

?>

mysql_num_rows()

Trả lại số dòng trong result_identifier (nơi chứa kết quả của câu lệnh SQL đã được thực hiện).

Cú pháp:

mysql_num_rows(int result_identifier);

, trong đó result_identifier là mã số trả về của hàm mysql_query(), mysql_db_query(), mysql_list_tables(), mysql_list_dbs().

mysql_affected_rows()

Cú pháp:

int mysql_affected_rows(int [link_identifier]);

, trong đó link_identifier là mã số nhận dạng, nó phải được thực hiện trong hàm mysql_select_db() trước đó.

Hàm trả về số dòng đã bị tác động bởi một câu truy vấn SQL:INSERT, UPDATE, DELETE trước đó theo tham số link_identifier. Nếu link_identifier không được chỉ định thì mã kết nối trước đó sẽ được chỉ định.

Chú ý:

- Nếu câu lệnh SQL trước đó là DELETE mà không có mệnh đề WHERE thì toàn bộ các bản ghi trong bảng đã bị xoá nhưng hàm mysql_affected_rows() sẽ trả về gián trị 0.

-Hàm này không có tác dụng đối với câu lệnh truy vấn SELECT. Để lấy được số dòng trả về (số dòng đã bị tác động) bởi câu lệnh SELECT ta dùng hàm mysql_num_rows().

mysql_result()

Hàm này dùng để lấy dữ liệu từ result_identifier.

Cú pháp:

mixed mysql_result(int result_identifier, int row, mixed [field]);

, trong đó result_identifier là mã số trả về của hàm mysql_query(), mysql_db_query(), mysql_list_tables(), mysql_list_dbs(), row là bản ghi mà ta sẽ lấy dữ liệu, field là trường trong dòng row mà ta sẽ lấy dữ liệu.

Các tham số result_identifier và row phải có, còn tham field là tùy chọn. Hàm sẽ trả lại các nội dung của dòng row và cột field từ tập kết quả được chỉ định bởi biến result_identifier. Nếu đối số field không được chỉ định rõ thì trường tiếp theo của bản ghi sẽ được trả về.

Ví dụ:

<?php

$mysql = “select id, name from ds_thanhvien”;

$link = mysql_connect($host, $user, $password);

$result = mysql_db_query( php, $mysql);

echo “ mysql_result($result, 0, “id”) <BR>\n”;

echo “ mysql_result($result, 0, “name”) <BR>\n”;

?>

mysql_free_result()

Hàm giải phóng vùng bộ nhớ được liên kết với result_identifier.

Cú pháp:

mysql_free_result(int result_identifier);

, trong đó result_identifier là mã số trả về của hàm mysql_query(), mysql_db_query(), mysql_list_tables(), mysql_list_dbs().

Hàm này chỉ được dùng nếu như bạn đánh giá thấy rằng kịch bản của bạn sử dụng quá nhiều bộ nhớ khi đang chạy. Gọi hàm này trên một trình xử lý kết quả sẽ giải phóng toàn bộ dữ liệu liên kết trong bộ nhớ.

mysql_tablename()

Cú pháp:

mysql_tablename(int result_identifier, int i);

Hàm trả lại tên của bảng/csdl tại chỉ số i trong result_identifier.

mysql_field_name()

Cú pháp:

mysql_field_name(int result_identifier, int field_index);

Hàm trả lại tên của trường tại vị trí field_index trong mã result_identifier.

mysql_list_dbs()

Cú pháp:

mysql_list_dbs([int link_identifier]);

Hàm trả lại một result_identifier là danh sách biến CSDL trên MySQL Server nếu thành công, lỗi trả về false.

mysql_list_tables()

Cú pháp:

mysql_list_tables(string database [, int link_identifier]);

Hàm trả về danh sách tất cả câc bảng trong một CSDL MySQL, thành công trả về một result identifier, giá trị false nếu có lỗi.

mysql_list_fields()

Cú pháp:

mysql_list_fields(string database_name, string table_name [, int link_identifier]);

Hàm trả về thông tin liên quan đến một bảng dữ liệu.

mysql_num_fields()

Cú pháp:

mysql_num_fields(int result_identifier);

Hàm trả về số trường trong tập kết quả.

mysql_num_rows()

Cú pháp:

mysql_num_rows(int result_identifier);

Trả về số bản ghi trong tập kết quả, hàm này chỉ có giá đối với các câu lệnh SELECT, để lấy lại số bản ghi được trả lại từ các lệnh: INSERT, UPDATE hoặc DELETE, dùng mysql_affected_rows().

mysql_field_type()

Cú pháp:

mysql_field_type(int result_identifier, int field_index);

Hàm trả về kiểu dữ liệu của trường tại vị trí field_index trong mã result_identifier.

mysql_field_len()

Cú pháp:

mysql_field_len(int result_identifier, int field_offset);

Hàm trả về độ dài của trường được chỉ định thông qua tham số field_offset.

mysql_fetch_lengths()

Cú pháp:

mysql_fetch_lengths(int result_identifier);

Hàm trả về một mảng tương ứng với các độ dài của mỗi trường trong bản ghi được lấy về bởi hàm mysql_fetch_row() hoặc false nếu có lỗi.

mysql_errno()

Cú pháp:

mysql_errno([int link_identifier]);

Hàm trả về mã lỗi từ hàm thao tác CSDL MySQL trước, trả về giá trị 0 nếu không có lỗi.

mysql_error()

Cú pháp:

mysql_error([int link_identifier]);

Hàm trả về xâu thông báo lỗi từ hàm thao tác CSDL MySQL trước, trả về xâu rỗng nếu không có lỗi.

mysql_fetch_field()

Cú pháp:

mysql_fetch_field(int result_identifier [, int field_offset]);

Hàm dùng để lấy thông tin về trường từ tập kết quả rồi trả lại như một đối tượng.

 

Hàm xử lý chuỗi (String)

Dưới đây là danh sách các hàm xử lý chuỗi phổ biến trong PHP:

Nhóm hàm in thông tin lên trình duyệt:

echo(), print() là 2 hàm thường được sử dụng nhiều nhất để in thông tin (chuỗi, giá trị biến, …) lên trình duyệt.

Ví dụ:

echo 'Welcome to PHP'; //Hoặc echo ('Welcome…');

print 'Welcome to V1Study'; //Hoặc print( 'Welcome…');

Lời khuyên: Nên sử dụng hàm echo() vì echo xử lý nhanh hơn print một chút vì không phải return về giá trị.

Hàm strlen():

Hàm này dùng để đếm tổng số ký tự có trong chuỗi.

Ví dụ:

echo strlen('Welcom to v1study.com');

Kết quả: 21

Hàm str_word_count():

Hàm này dùng để đếm tổng số từ có trong chuỗi

Ví dụ:

echo str_word_count('Welcome to v1study.com');

Kết quả: 3

Hàm addslashes():

Hàm addslashes sẽ thêm vào ký tự \ (back slash) trước các ký tự ‘ và ” trong một chuỗi, có tác dụng tránh lỗi SQL injection khi thêm dữ liệu vào database.

Ví dụ:

$str = 'Chao mung ban den voi "Khoa hoc PHP"';

echo addslashes( $str );

$str = "Mot so ham 'xu ly chuoi' trong PHP";

echo "" . addslashes( $str );

Kết quả:

Chao mung ban den voi \”Khoa hoc PHP\”

Mot so ham \’xu ly chuoi\’ trong PHP

Hàm stripslashes():

Hàm stripslashes có tác dụng ngược lại với addslashed, hàm này sẽ loại bỏ các ký tự \ trong chuỗi ký tự, thường được sử dụng để xử lý chuỗi trước khi hiển thị thông tin lên trình duyệt.

Ví dụ:

$str = "Mot so ham \'xu ly chuoi\' trong PHP";

echo "" . stripslashes( $str );

Kết quả: Mot so ham ‘xu ly chuoi’ trong PHP

Hàm str_repeat():

Cú pháp:

str_repeat($str, $n)

Hàm str_repeate() cho phép lặp lại chuỗi $str theo $n lần.

Ví dụ:

echo str_repeat( ‘Hello’, 5 );

Kết quả: HelloHelloHelloHelloHello

Hàm str_replace():

Cú pháp:

str_replace($chuoi_tim, $chuoi_thay_the, $chuoi_nguon)

Hàm str_replace() cho phép tìm kiếm và thay thế trong chuỗi:

Ví dụ 1:

$str = 'Ban dang tham gia khoa hoc PHP';

$str = str_replace( 'PHP', 'PHP co ban', $str );

echo $str;

Tìm tất cả các cụm từ 'PHP' trong chuỗi $str và thay thế bằng 'PHP co ban'

Kết quả: Ban dang tham gia khoa hoc PHP co ban

Lưu ý rằng $chuoi_tim và $chuoi_thay_the có thể là 1 mảng dữ liệu.

Ví dụ 2:

Loại bỏ tất cả các ký tự !,@,#,$,% ra khỏi chuỗi

$str = 'Scelerisque! porttitor@ #elementum% sed$ cum pellentesque';

$str = str_replace( array('!', '@', '#', '$', '%') , '', $str );

echo $str;

Kết quả: Scelerisque porttitor elementum sed cum pellentesque

Ví dụ 3: Tìm và thay thế bằng và bằng

$str = str_replace( array('', ''), array ('', '') , $str );

echo $str;

Nhóm hàm loại bỏ ký tự ra khỏi chuỗi:

chop($string) : Loại bỏ những khoảng trắng ở cuối chuỗi

trim($string) : Loại bỏ những khoảng trắng ở đầu và cuối của chuỗi.

ltrim($string, $ky_tu_loai_bo) : Loại bỏ các ký tự ở đầu chuỗi, mặc định loại bỏ tất cả khoảng trắng ở đầu chuỗi.

rtrim($string, $ky_tu_loai_bo) : Loại bỏ các ký tự ở cuối chuỗi, mặc định loại bỏ tất cả khoảng trắng ở cuối chuỗi.

Nhóm hàm liên hệ giữa mảng và chuỗi:

explode(‘Chuỗi tách’, $string) : Tách chuỗi thành mảng bởi chuỗi tách

implode(“Chuỗi nối”, $mang) : Nối các phần tử mảng để tạo thành chuỗi.

join("Chuỗi nối", $mang) : Tương tự implode

Xem thêm về implode và explode trong phần: Các hàm xử lý mảng trong PHP

Các hàm mã hóa chuỗi:

Trong php chúng ta có hai phương pháp mã hóa chuỗi thường sử dụng là md5 và sha1

md5($string) : Mã hóa chuỗi dạng md5, chuỗi sẽ được mã hóa thành một chuỗi gồm 32 ký tự hệ 16.

sha1($string) : Mã hóa chuỗi dạng sha1, chuỗi sẽ được mã hóa thành một chuỗi gồm 40 ký tự hệ 16.

Các hàm thao tác với HTML:

PHP cung cấp cho chúng ta một số hàm thao tác với các thẻ HTML:

htmlentities($string) :

Chuyển tất cả các ký tự có thể áp dụng cho các thẻ HTML như <, > sang dạng thực thể của chúng, các thẻ HTML sẽ không còn tác dụng. Thường được xử dụng trong việc xử lý dữ liệu từ người dùng nhập trước khi lưu vào database.

html_entity_decode($string) :

Ngược lại với htmlentities(), hàm html_entity_decode() sẽ chuyển đổi tất cả các thực thể HTML sang những kí tự có thể dùng được của chúng.

Ví dụ về htmlentities và html_entity_decode:

$str = 'The p trong html';

$str = htmlentities($str);

echo 'Entity: ' . $str . '';

echo 'Decode' . html_entity_decode($str);

Kết quả:

The p trong html

Decode

The p trong html

htmlspecialchars($string) :

Tương tự htmlentities().

htmlspecialchars_decode($string) :

Tương tự html_entity_decode

strip_tags($string, $allow_tags) :

Loại bỏ các thẻ HTML hoặc PHP ra khỏi chuỗi, Thường được sử dụng để xử lý dữ liệu do người dùng nhập trước khi lưu trữ database, hiển thị văn bản dạng trích dẫn.

$allow_tags: Các thẻ cho phép giữ lại

Ví dụ: Loại bỏ các thẻ HTML ra khỏi chuỗi $str, cho phép giữ lại thẻ và

$str = strip_tags( $str, '' );

Các hàm tách chuỗi con (sub):

substr($string, $start, $length) :

Tách chuỗi con từ một chuỗi.

$start: Vị trí bắt đầu tách

$length: Chiều dài chuỗi cần tách

Ví dụ:

$str = "Khoa hoc PHP";

$str = substr( $str, 0, 8 );

echo $str;

Kết quả: Khoa hoc

strstr($string, $ky_tu_cho_truoc) :

Tách ra một chuỗi con từ vị trí đầu tiên của chuỗi cho trước cho đến cuối chuỗi.

Ví dụ:

echo strstr( "Khoa hoc PHP co ban", "PHP" );

Kết quả: PHP co ban

strops($str, $chuoi_tim) :

Tìm vì trí xuất hiện đầu tiên của $chuoi_tim trong chuỗi $str.

Ví dụ:

echo strpos( "Khoa hoc PHP", "PHP" );

Kết quả: 9

Một số hàm khác:

strtolower($string) : Chuyển tất cả ký tự sang chữ thường.

strtoupper($string) : Chuyển tất cả ký tự sang chữ in hoa.

ucfirst($string) : Viết hoa kí tự đầu tiên của chuỗi.

ucwords($string) : Viết hoa kí tự đầu tiên của mỗi từ.

Các hàm sắp xếp mảng

PHP cung cấp cho chúng ta một số hàm sắp xếp mảng. Với mỗi loại mảng sẽ có một hàm tương ứng.

sort() và rsort()

Với mảng có chỉ số là kiểu nguyên thì hàm sort() sắp xếp mảng tăng dần, hàm rsort() sắp xếp mảng giảm dần.

Ví dụ:

$countries = array("us","uk","ca","cr","de");

sort($countries);

while(list($key, $value) = each($countries)) {

  echo"Phần tử $key = $value <br>\n";

}

Kết quả là:

Phần tử 0 = ca

Phần tử 1 = cr

Phần tử 2 = de

Phần tử 3 = uk

Phần tử 4 = us

asort() và arsort()

Các hàm này dùng để sắp xếp mảng có chỉ số có kiểu chuỗi, trong đó asort() sắp xếp tăng dần và arsort() sắp xếp giảm dần. Nếu bạn dùng các hàm sort() hay asort() thì các chỉ số kiểu chuỗi sẽ chuyển thành các chỉ số kiểu nguyên.

Ví dụ:

$countries = array("us" => "United States",

                           "uk" => "United Kingdom",

                           "ca" => "Canada",

                           "cr" => "Costa Rica",

                           "de" => "Germany"

);

asort($countries); //sắp xếp tăng dần

while(list($key, $value) = each($countries)) {

  echo"Mã $key là $value";

}

Kết quả:

Mã ca là Canada

Mã cr là Costa Rice

Mã de là Germany

Mã uk là United Kingdom

Mã us là United States

Nhưng nếu thay asort($countries) bằng sort($countries) thì kết quả sẽ là:

Mã 0 là Canada

Mã 1 là Costa Rice

Mã 2 là Germany

Mã 3 là United Kingdom

Mã 4 là United States

ksort() và krsort()

Dùng để sắp xếp mảng tăng hoặc giảm theo chỉ số.

Ví dụ:

$countries = array("e" => "United States",

                           "d" => "United Kingdom",

                           "c" => "Canada",

                           "b" => "Costa Rica",

                           "a" => "Germany"

);

kasort($countries); //sắp xếp tăng dần

while(list($key, $value) = each($countries)) {

  echo"Chỉ số $key là $value";

}

Kết quả:

Chỉ số a là Germany

Chỉ số b là Costa Rice

Chỉ số c là Canada

Chỉ số d là United Kingdom

Chỉ số e là United States

Session & Cookie

Session là gì?

HTTP là giao thức không được xây dựng theo cách để có thể lưu giữ được trạng thái giữa hai lần giao dịch. Khi một người dùng yêu cầu truy nhập một trang Web, rồi sau đó người dùng này lại tiếp tục yêu cầu truy nhập đối với trang Web khác thì HTTP không thể biết được rằng đó là hai yêu cầu từ cùng một người dùng.

Ý tưởng của việc điều khiển phiên làm việc là có thể lưu vết của một người dùng trong suốt một phiên làm việc. Nếu chúng ta làm được điều này thì sẽ dễ dàng cung cấp một truy nhập cho người dùng, từ đó ta có thể lưu vết trạng thái của người dùng và có thể thực hiện việc mua bán trên mạng.

Session trong PHP được điều khiển bởi một giá trị ID duy nhất gọi là “sessionID”, giá trị này sẽ được tự động sinh ra và mã hóa. SessionID được sinh ra bởi PHP và được lưu trữ ở phía client trong suốt một phiên giao dịch. Nó có thể được lưu trữ trên các Cookie ở máy người dùng hay truyền lên các URL. SessionID có tác dụng như một khoá để bạn có thể đăng ký những biến đặc biệt gọi là biến session. Nội dung của những biến này được chứa trên Server. SessionID là những thông tin chỉ thấy được ở phía client. Nếu tại thời điểm nào đó của một kết nối đến trang Web của bạn, sessionID có thể thấy được trên cookie hay URL, bạn có thể truy nhập những biến session chứa trên Server ở phiên làm việc đó.

Cookie là gì?

Cookie là những mẩu tin nhỏ mà trang script có thể chứa trên các máy khách (client). Bạn có thể thiết lập một cookie trên một máy người dùng bằng cách gửi một “HTTP header” có chứa dữ liệu theo dạng sau:

Set-Cookie:Name=VALUE;[expires=DATE;][path=PATH;][domain=DOMAIN_NAME;][secure]

Câu lệnh này sẽ tạo ra một cookie có tên gọi là NAME với giá trị là VALUE.

Trường expires sẽ thiết lập ngày mà cookie sẽ hết hiệu lực, path và domain có thể được sử dụng để chỉ định các URL (nơi mà cookie sẽ được gửi đi). Từ khoá secure có nghĩa là cookie sẽ không gửi đi trên quá một kết nối HTTP chuẩn.

Khi một browser kết nối tới một URL, trước tiên nó kiểm tra các cookie đã được lưu trữ trên máy. Nếu có bất kì một cookie nào có liên quan đến địa chỉ URL vừa được kết nối, chúng sẽ được truyền trở lại cho server.

Thiết lập các cookie từ PHP

Ta có thể thiết lập các cookie trong PHP bằng cách sử dụng hàm:

int setcookie (string name [,string value [,int expire [,string path [,string domain [, int secure]]]]]);

Những tham đối của hàm tương ứng với những tham đối của Set-Cookie header ở trên.

Nếu ta thiết lập cookie như sau:

setcookie ("TestCookie", "Test Value");

, thì khi người dùng đến thăm trang kế tiếp trong site của ta (hoặc reload trang hiện tại) ta sẽ phải truy nhập vào biến với tên là "TestCookie" có chứa giá trị là "Test Value", ta chỉ có thể truy nhập tới nó thông qua biến mảng $HTTP_COOKIE_VARS[] của PHP.

Ta có thể xoá một cookie bằng cách gọi lại hàm setcookie() với tham đối như sau:

tên của cookie là tên của cookie cần xoá và không có trường giá trị.

Sử dụng kết hợp cookie với session

Đối với cookie có một số vấn đề sau đây:

Một vài webrowser không thể truy cập được tới các cookie (không hỗ trợ cookie) và một số người dùng không có các cookie trên browser của họ. Đây là lý do để PHP sử dụng cả hai cách thức:cookie và URL method. Khi sử dụng PHP session, ta sẽ không phải thiết lập các cookie, những hàm session sẽ lưu giữ những thông tin này cho chúng ta. Để xem nội dung của các cookie đã được thiết lập bởi session ta sử dụng hàm:

session_get_cookie_params()

Hàm này sẽ trả về một mảng liên kết mà các phần tử của mảng chứa các thông tin như: lifetime, path, domain,...

Để thiết lập các tham số cho session cookie ta dùng hàm:

void session_set_cookie_params (int lifetime [, string path [, string domain]]);

Lưu giữ sessionID

PHP sẽ sử dụng các cookie mặc định cùng với session. Nếu có thể được, một cookie sẽ được thiết lập chứa SessionID.

Một cách để sử dụng các SessionID trên URL đó là dịch PHP cùng với lựa chọn --enable-tran-sid.

Cách nữa là ta có thể đa sessionID vào trong thẻ link. SessionID được chứa trong hằng SID. Để làm được điều này, ta thêm vào cuối thẻ link hằng SID để dùng nó như là phương thức GET.

Ví dụ:

<A HREF = “link.php?<?=SID?>”>

Hằng SID làm việc được như trên chỉ khi ta cấu hình PHP cùng với --enable-track-vars.

Thực thi những phiên làm việc đơn giản.

Những bước cơ bản của việc sử dụng session:

+ Bước 1: Khởi tạo một Session

+ Bước 2: Đăng ký những biến Session

+ Bước 3: Sử dụng biến Session

+ Bước 4: Huỷ bỏ biến Session và kết thúc Session

Khởi tạo một Session

Để khởi tạo Session bạn dùng hàm sau:

session_start();

Lưu ý rằng hàm này phải được đặt trước các khai báo session, nó sẽ kiểm tra xem đã có một Session ID nào đã được tạo ra hay chưa. Nếu chưa thì nó sẽ tạo ra một Session ID, còn nếu đã tồn tại một Session ID thì thực chất nó chỉ lấy ra những biến Session để ta có thể dùng nó. Hàm trả về giá trị TRUE nếu thành công, ngược lại trả về giá trị FALSE.

Chúng ta cũng có thể bắt đầu một Session bằng cách cấu hình PHP để nó tự động bắt đầu khi có ai đó thăm trang Web của ta. Điều này có thể làm được nếu ta chọn session. auto_start trong file c:\Windows\php.ini

Một Session cũng sẽ được bắt đầu khi ta đăng ký một biến Session.

Đăng ký những biến Session

Để cho một biến có thể lưu dấu thông tin từ một trang script này sang trang script khác, ta cần phải đăng ký nó bằng cách gọi hàm:

bool session_register(mixed VarName [,mixed...]);

Việc đăng ký này sẽ lưu trữ tên biến và ghi giá trị của biến cho đến khi phiên giao dịch kết thúc hoặc khi ta huỷ bỏ (deregister) việc đăng ký biến đó.

Ví dụ: Để đăng ký biến $Var_name ta viết như sau:

$Var_name= 5;

session_register(“Var_name”); // không nên sử dụng ký tự $ trong đăng ký một biến.

Sử dụng biến Session

Để đa một biến Session vào trong phạm vi mà nó có thể được sử dụng, ta cần phải khởi tạo một Session bằng một trong những cách đã nêu trên. Sau đó, ta có thể truy cập được những biến này. Nếu đã đăng ký biến này là toàn cục bằng cách sử dụng hàm register_global(), thì ta có thể truy nhập biến bình thường thông qua tên biến, ví dụ: $Var_name;

Nếu không khai báo biến là toàn cục thì ta phải truy nhập những biến Session thông qua mảng liên kết $HTTP_SESSION_VARS(“Var_name”);

Để kiểm tra xem một biến đã được đăng ký là biến Session hay chưa ta dùng hàm: bool session_is_registered (string name);

Hàm này trả về giá trị TRUE nếu biến đã được đăng ký, ngược lại trả về giá trị FALSE.

Ta cũng có thể kiểm tra một biến có là biến Session bằng cách kiểm tra mảng liên kết $HTTP_SESSION_VARS() về sự tồn tại của biến.

Huỷ bỏ biến Session và kết thúc Session

Khi muốn kết thúc một biến Session, ta có thể huỷ bỏ đăng ký của biến đó bằng hàm: bool session_unregister (string name);

Trong đó: name là tên biến ta muốn huỷ đăng ký (tên này không cần có ký tự $)

Hàm trả về giá trị TRUE nếu thành công, ngược lại trả về giá trị FALSE.

Hàm này chỉ có thể huỷ đăng ký của một biến Session tại một thời điểm.

Để huỷ tất cả các biến Session hiện tại, ta dùng hàm: void session_unset();

Để kết thúc một Session ta dùng hàm: bool session_destroy();

Hàm này sẽ xoá đi SessionID và hủy tất cả những dữ liệu liên quan đến Session này. Hàm trả về giá trị TRUE nếu thành công, ngược lại trả về giá trị FALSE. Ta nên hủy tất cả các biến Session trước khi kết thúc một Session.

Giới thiệu

Trong nhiều năm, PHP đã bị coi là một ngôn ngữ nghèo nàn, và đứng thứ hạng thấp trong bảng xếp hạng ngôn ngữ lập trình bởi ví nó không hỗ trợ tính hướng đối tượng. Đến năm 2004, phiên bản PHP 5 ra đời đã tạo ra bước ngoặc mới cho ngôn ngữ lập trình PHP, giúp PHP bắt kịp với xu thế và trở thành một trong những đối thủ nặng ký so với các ngôn ngữ lập trình khác. Vậy thì hướng đối tượng là gì? và tại sao nó lại đóng một vai trò to lớn như vậy?

Theo như định nghĩa của Wikipedia thì:

Object-oriented programming as a programming paradigm that represents concepts as "objects" that have data fields and associated procedures known as "methods".

Hướng đối tượng là một mô hình lập trình phân tách nội dụng của chương trình theo hướng cổ điển (thủ tục) và nhóm các thuộc tính, phương thức (properties, methods) giống nhau thành một đối tượng (class), giúp rút ngắn, tránh việc dư thừa, và giữ vững được nguyên lý DRY – DONT REPEAT YOURSELF, dễ dàng trong vấn đề báo trì, tăng hiệu quả công việc.

Hãy thử hình dung bạn xây dựng một website hoặc một hệ thống lên cả nghìn, thậm chí hàng triệu dòng code, các mã lệnh đươc viết theo hướng cổ điển, một trang web (page) chứa cả code html, php, js, xử lý xen lẫn với nhau. Và thế là mỗi lần xuất hiện lỗi, gặp phải một vấn đề nào đó hay chỉ đơn thuần là sửa vài chỗ nhỏ khi có thay đổi yêu cầu thì bạn phải lục tung cả mớ code, đi sửa từng chỗ này chỗ kia vì các đoạn code trùng lặp, điều này quả thật là một cơn ác mộng đối với một lập trình viên. Chính vì thế OOP ra đời nhằm giúp bạn giải quyết vấn đề này.

Hàm (Function)

Cú pháp định nghĩa hàm

function tên_hàm(Khai_báo_các_đối_số_nhận_dữ_liệu) {

    Khối_lệnh;

    [return giá_trị];

}

+ Trong PHP việc định nghĩa hay khai báo một hàm thì không có kiểu trả về.

+ Với PHP bạn có quyền định nghĩa hàm nằm trong thân hàm khác mà nhưng việc sử dụng một hàm không khác nhau giữa xây dựng hàm trong thân một hàm và ngoài mọi hàm.

+ tên_hàm không được trùng với từ khóa và phải tuân theo quy tắc đặt tên chung.

+ Hàm có thể có giá trị trả về hoặc không.

+ Các câu lệnh được quyền gọi bất kỳ hàm nào đã được khai báo và đã được định nghĩa.

+ return:

- Trả một giá trị về cho nơi gọi hàm, hàm có thể trả về bất kỳ giá trị có kiểu gì.

- Là nơi báo kết thúc hàm.

Lời gọi hàm

+ Lưu ý: Hàm phải được định nghĩa hoặc khai báo trước khi gọi.

+ Cú pháp: Tên_hàm(Các_dữ_liệu_truyền_đi);

Biến tổng thể và biến cục bộ

Biến tổng thể (global) là biến được khai báo ngoài tất cả các hàm.

Biến cục bộ (local) là biến được khai báo trong một hàm nào đó.

Biến cục bộ chỉ có tác dụng đối với hàm chứa nó.

Biến tổng thể có thể được sử dụng trong tất cả các hàm.

Để gọi biến tổng thể từ một hàm nào đó, ta sử dụng quy cách sau:

$GOLOBALS['Tên_biến_tổng_thể']

Hoặc:

global $Tên_biến_tổng_thể;

Ví dụ:

$position = "m";

function change_pos(){

    $position = "s";

}

change_pos();

echo"$position"; // print "m"

Ta thấy biến $position có giá trị không đổi sau khi gọi hàm change_pos(), vì vậy ta cần phải viết lại như sau:

$position = "m";

function change_pos(){

    global $position;

    $position = "s";

}

change_pos();

echo ("$position"); // print "s"

Hoặc:

$position = "m";

function change_pos() {

    $GOLOBALS[$position] = "s";

}

change_pos();

echo"$position"); // print "s"

Class và Object (Lớp và Đối tượng)

Trong bài viết này ta sẽ tìm hiểu các phần:

Định nghĩa Lớp và Đối tượng

Lớp nghĩa là một khung kịch bản của một đối tượng, hoặc bạn có thể hiểu đối tượng được tạo ra từ một lớp. Trong lớp nó sẽ có các biến mà biến này ta gọi là các thuộc tính (properties), và lớp nó có thể chứa các hàm mà các hàm này chúng ta gọi nó là phương thức (method).

Mình có ví dụ sau, chiếc xe là lớp, trong chiếc xe đó nó có các thuộc tính như màu đỏ, 1 cầu 2 cầu, và các hành động như chạy, lùi, thắng ta xem như một phương thức.

Định nghĩa của Class và Object. Ảnh: phpenthusiast

Định nghĩa của Class và Object. Ảnh: phpenthusiast

Bây giờ chúng ta cùng viết một lớp tên là meeting như sau:

<?
class meeting {
    public $name = 'Thach';
    function hello() {
        return $this->name . ' saying hello';
    }
    function goodbye() {
        return $this->name . ' saying goodbye';
    }
}
?>

Trong đó, ta tạo ra một thuộc tính $name trong lớp meeting, biến này ta có đặt từ khoá là public, nó sẽ được giải thích ở phía dưới.

Kế đó ta tạo thêm một phương thức tên hello() trong lớp và nó sẽ trả về là giá trị của thuộc tính $name kèm theo một đoạn chữ. Lưu ý rằng khi ta viết code trong một lớp mà nếu ta muốn sử dụng một thuộc tính nào đó có trong lớp thì sẽ sử dụng từ khoá $this->tên_thuộc_tính.

Bây giờ chúng ta đã có 2 phương thức và một thuộc tính trong lớp. Chúng ta sẽ sử dụng nó bằng cách tạo ra một biến để hứng lớp này.

$say = new meeting;

Nghĩa là khi sử dụng lớp, chúng ta cần cho biến nào hứng dữ liệu của lớp thì sẽ có từ khoá new đằng trước tên lớp cần sử dụng.

Bây giờ bạn dump cái biến $say, bạn sẽ thấy nó có kiểu dữ liệu là Object.

echo '<pre>';
var_dump($say);

Kết quả:

object(meeting)#117 (1) {
  ["name"]=>
  string(5) "Thach"
}

Bạn thấy, nó trả về dữ liệu kiểu đối tượng và cho ta thấy đối tượng đó có một thuộc tính tên là name. Bây giờ chúng ta có đối tượng $say rồi, chúng ta muốn sử dụng thuộc tính name trong đó thì chỉ cần viết là $say->name là nó sẽ ra.

Và nếu cần gọi một phương thức trong lớp thì chỉ cần viết $this->hello() hoặc$this->goodbye() là nó ra. Lưu ý là khi gọi phương thức và thuộc tính, sử khác biệt của nó là thuộc tính không có ký tự () phía sau như phương thức.

$say = new meeting;
echo $say->name . '</br>';
echo $say->hello() . '</br>';
echo $say->goodbye() . '</br>';

Truyền tham số vào lớp

Như ở ví dụ trên, chúng ta có thuộc tính $name có giá trị sẵn là 'Thach'. Vậy chúng ta cần tự thiết lập giá trị này khi tạo đối tượng thì làm sao? Trước hết, chúng ta phải tạo ra cho nó thêm một phương thức nào đó mà nó sẽ có nhiệm vụ truyền tham số đã được khai báo khi tạo ra đối tượng.

class meeting {
    public $name;
    public function set_name( $ten ) {
        $this->name = $ten;
    }
 
    public function hello() {
        return $this->name . ' saying hello';
    }
}
 

Trong đoạn mã trên, phương thức tên set_name() với tham số là $ten sẽ nhận giá trị mà người dùng nhập vào.

Trong phương thức này, ta sẽ chỉ định cho thuộc tính $name của lớp sẽ sử dụng tham số truyền vào là $ten.

Cuối cùng là ở phương thức hello(), ta sẽ return lại giá trị mà thằngset_name() đã truyền vào với từ khoá $this->name.

Và khi sử dụng, chúng ta sẽ thiết lập tham số ở phương thức set_name().

01
02
03
$say new meeting;
$say->set_name('Super Man');
echo $say->hello();

Phương thức khởi tạo ( __construct() )

Phương thức khởi tạo này nghĩa là một phương thức mà nó sẽ được tự động thực thi khi chúng ta tạo ra một đối tượng mới, và các tham số trong phương thức này chúng ta có thể truyền nó vào ngay lúc tạo ra đối tượng.

Bây giờ quay lại ví dụ của bài truyền tham số, chúng ta dùng phương thứcset_name() để truyền cái $name vào. Nhưng nếu bạn không muốn làm bước này, muốn truyền một tham số gì đó toàn cục trong lớp thì nên sử dụng phương thức __construct.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
<?php
    class meeting {
        public $name;
        public $skill;
        function __construct($ten$kynang)
        {
            $this->name = $ten;
            $this->skill = $kynang;
        }
 
        function hello()
        {
            return "Hello, my name is $this->name, my skill is $this->skill";
        }
    }
     
    $say new meeting('Thach''WordPress');
    echo $say->hello();

Nhưng bạn nhớ rằng công dụng của __construct() là sẽ thực hiện cái gì đó mỗi khi ta tạo ra một đối tượng từ lớp nên bạn đừng hiểu là nó chỉ có chức năng truyền tham số vào lớp nhé.

Kế thừa lớp

Kế thừa lớp nghĩa là bạn tạo ra một lớp con mới sẽ kế thừa lại một lớp nào đó với các thuộc tính và phương thức có sẵn, từ đó bạn có thể tuỳ biến lại code bên trong một phương thức hoặc thuộc tính nào đó.

Ví dụ, ta có lớp Car được gọi là lớp mẹ, trong đây sẽ có sẵn các thuộc tính và phương thức của một chiếc xe như màu sắc, chạy, lùi,…Sau đó ta tạo ra một lớp khác con tên BMW và nó sẽ kế thừa lại lớp Car này vì BMW nó cũng cần màu sắc, cũng cần chạy, lùi mà.

Trước hết chúng ta tạo lớp Car và khai báo thuộc tính cũng như các phương thức của nó.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
<?php
    class Car {
        public $name;
        public $color;
        public $type;
 
        public function car_info()
        {
            // Chỉ là tránh lỗi 'Undefined variable'
            (!isset($output)) ? $output = null : '';
 
            $output .= '<ul>';
            $output .= "<li>Name: $this->name </li>";
            $output .= "<li>Color: $this->color </li>";
            $output .= "<li>Type: $this->type </li>";
            $output .= "</ul>";
            return $output;
        }
    }

Sau đó chúng ta tạo ra lớp BMW và nó sẽ kế thừa lại lớp Car.

01
02
03
04
05
class BMW extends Car {
    public $name 'BMW';
    public $color 'Red';
    public $type 'Sport';
}

Lúc này lớp BMW sẽ sử dụng được các thuộc tính và phương thức của lớp Car. Nếu cần tinh chỉnh lại thuộc tính hay phương thức nào thì cứ việc khai báo lại bên trong nó, như ví dụ trên là ta khai báo giá trị của các thuộc tính trong lớpBMW.

Bây giờ chúng ta thử sử dụng phương thức car_info() của lớp Car và vào lớp BMW nhé.

01
02
$bmw new BMW;
echo $bmw->car_info();

Visibility (tầm vực) trong lớp

Ở các ví dụ trên, bạn có thể thấy ta sử dụng từ khoá public khi khai báo thuộc tính và phương thức. Và từ khoá này được gọi là từ khoá visibility. Hiện tại trong lớp, bạn sẽ sử dụng 3 từ khoá phổ biến nhất hiện tại như:

  • public – Nếu phương thức hoặc thuộc tính nào sử dụng từ khoá này thì nghĩa là chúng ta có thể sử dụng nó ở bất cứ đâu, tức là có thể gọi ra bên trong một lớp hoặc bên ngoài một lớp, hoặc sử dụng trong một lớp con (lớp được kế thừa).
  • private – Phương thức/Thuộc tính nào sử dụng từ khoá này thì nó chỉ được truy cập bên trong một lớp của chính nó, không thể sử dụng cho lớp khác hoặc không thể gọi ra bên ngoài. Ví dụ bạn có thể sử dụng $this->name bên trong lớp như không thể gọi ra với $object->name ở bên ngoài lớp.
  • protected – Phương thức/Thuộc tính nào sử dụng từ khoá này là nó sẽ có thể được truy cập bên trong class hoặc các class kế thừa.

Ví dụ về public

01
02
03
04
05
06
07
08
09
10
11
12
<?php
    class pub_class {
        public $name 'Thach';
         
        public function show()
        {
            return $this->name;
        }
    }
    $pub new pub_class;
    echo $pub->name . '</br>'// Hiển thị 'Thach'
    echo $pub->show(); // Cũng hiển thị 'Thach'

Ví dụ về private

01
02
03
04
05
06
07
08
09
10
11
12
<?php
    class pri_class {
        private $name 'Thach';
 
        public function show()
        {
            return $this->name;
        }
    }
    $pri new pri_class;
    echo $pri->name; // Lỗi 'Fatal error: Cannot access private property pri_class::$name'
    echo $pri->show(); // Hợp lệ vì show() là public

Ví dụ về protected

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
<?php
 
    class tp_parent {
        protected $name 'Thach';
    }
 
    class tp_child extends tp_parent {
        public function show()
        {
            return $this->name;
        }
    }
 
$child new tp_child;
echo $child->show(); // Hợp lệ vì phương thức này sử dụng thuộc tính $name của class mẹ

Lớp trừu tượng (Abstraction Class)

Một lớp trừu tượng nghĩa là nó có một hoặc nhiều phương thức là trừu tượng. Phương thức trừu tượng thì nghĩa là nó phải bắt buộc được khai báo ở các lớp con. Bạn nên lưu ý rằng dù lớp của bạn có bao nhiêu phương thức trừu tượng thì lớp đó vẫn là lớp trừu tượng.

Để khai báo lớp trừu tượng thì chúng ta chỉ việc thêm từ khoá abstract đằng trước tên class và tên phương thức mà ta muốn làm trừu tượng. Lưu ý là phương thức khai báo trừu tượng sẽ không chứa bất cứ cái gì, ngoại trừ tham số.

01
02
03
04
05
06
07
08
09
10
11
12
<?php
 
    abstract class tp_parent {
        protected $args;
 
        abstract protected function set_args(); // Phương thức trừu tượng không được chứa cái quần gì cả
 
        public function show_args()
        {
            return $this->set_args();
        }
    }

Code ở trên là chúng ta tạo ra một lớp tên tp_parent và nó là trừu tượng vì có từ khoá abstract ở trước. Bên trong nó ta có thuộc tính $args là dạngprotected để ta có thể sử dụng nó ở các lớp con nhưng không cho phép truy cập từ bên ngoài.

Sau đó chúng ta có phương thức trừu tượng tên set_args(), tức là phương thức này sẽ phải được bắt buộc khai báo ở lớp con. Cuối cùng là ta có phương thức public là show_args() để có thể sử dụng nó bên ngoài cho mục đích lấy dữ liệu hiển thị, và chức năng của phương thức này là hiển thị kết quả trả về của phương thức set_args() sau khi nó xử lý.

Bây giờ chúng ta tạo ra một lớp con kế thừa lại lớp mẹ và thử không khai báo phương thức set_args() cho nó xem cái gì xảy ra nhé.

01
02
03
04
class tp_child extends tp_parent {}
 
$child new tp_child;
echo print_r ( $child->show_args() );

Lúc này bạn sẽ nhận được lỗi này:

Fatal error: Class tp_child contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (tp_parent::set_args)

Như vậy, bạn phải khai báo phương thức set_args() thì mới được. Ta sửa lại như sau:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
<?php
 
class tp_child extends tp_parent {
    protected function set_args()
    {
        $this->args = array(
            'name'    => 'Thach Pham',
            'age'    => 23
        );
        return $this->args;
    }
}
 
$child new tp_child;
echo print_r ( $child->show_args() );

Kết quả nó sẽ trả về mảng của set_args().

Download AppServ 2.5.9

Link download tại ĐÂY.

private, protected và public

Tầm vực của thuộc tính hay phương thức có thể được định nghĩa bằng cách đặt phía trước tên thuộc tính từ khóa publicprotected hoặc private. Các thành phần lớp được khai báo là public có thể được truy cập ở mọi nơi. Các thành phần protected chỉ có thể được truy cập trong lớp chứa chúng và trong lớp con của lớp đó. Các thành phần private chỉ có thể được truy cập từ lớp chứa chúng.

Tầm vực của thuộc tính

Các thuộc tính của lớp được khai báo kèm từ khóa public, private hoặc protected. Nếu thuộc tính nào được khai báo sử dụng từ khóa var thì thuộc tính đó mặc định có tầm vực là public.

Ví dụ 1: Khai báo thuộc tính.

<?php
/**
 * Định nghĩa MyClass
 */

class MyClass
{
    public 
$public 'Public';
    protected 
$protected 'Protected';
    private 
$private 'Private';

    function 
printHello()
    {
        echo 
$this->public;
        echo 
$this->protected;
        echo 
$this->private;
    }
}


$obj = new MyClass();
echo 
$obj->public// Làm việc
echo $obj->protected// Lỗi
echo $obj->private// Lỗi
$obj->printHello(); // Hiển thị Public, Protected and Private


/**
 * Định nghĩa MyClass2
 */

class MyClass2 extends MyClass
{
    
// Ta có thể khai báo lại phương thức public và protected, nhưng không được private
    
protected $protected 'Protected2';

    function 
printHello()
    {
        echo 
$this->public;
        echo 
$this->protected;
        echo 
$this->private;
    }
}


$obj2 = new MyClass2();
echo 
$obj2->public// Làm việc
echo $obj2->protected// Lỗi
echo $obj2->private// Không định nghĩa
$obj2->printHello(); // Hiển thị Public, Protected2, Undefined

?>

 Lưu ý: PHP 4 vẫn hỗ trợ việc khai báo biến với từ khóa var. PHP 5 trước 5.1.3 thì việc sử dụng var sẽ phát sinh cảnh báo E_STRICT.

Tầm vực của phương thức

Các phương thức của lớp có thể được định nghĩa là public, private hoặc protected. Những phương thức khai báo mà không có từ khóa tầm vực sẽ mặc định là public.

Ví dụ 2: Khai báo phương thức.

<?php
/**
 * Định nghĩa MyClass
 */

class MyClass
{
    
// Định nghĩa hàm tạo public
    
public function __construct() { }

    
// Định nghĩa phương thức public
    
public function MyPublic() { }

    
// Định nghĩa phương thức protected
    
protected function MyProtected() { }

    
// Định nghĩa phương thức private
    
private function MyPrivate() { }

    
// Phương thức này sẽ có tầm vực là public
    
function Foo()
    {
        
$this->MyPublic();
        
$this->MyProtected();
        
$this->MyPrivate();
    }
}


$myclass = new MyClass;
$myclass->MyPublic(); // OK
$myclass->MyProtected(); // Lỗi
$myclass->MyPrivate(); // Lỗi
$myclass->Foo(); // Public, Protected và Private


/**
 * Định nghĩa MyClass2
 */

class MyClass2 extends MyClass
{
    
// public
    
function Foo2()
    {
        
$this->MyPublic();
        
$this->MyProtected();
        
$this->MyPrivate(); // Fatal Error
    
}
}


$myclass2 = new MyClass2;
$myclass2->MyPublic(); // OK
$myclass2->Foo2(); // Public và Protected làm việc, Private thì không

class Bar 
{
    public function 
test() {
        
$this->testPrivate();
        
$this->testPublic();
    }

    public function 
testPublic() {
        echo 
"Bar::testPublic\n";
    }
    
    private function 
testPrivate() {
        echo 
"Bar::testPrivate\n";
    }
}

class 
Foo extends Bar 
{
    public function 
testPublic() {
        echo 
"Foo::testPublic\n";
    }
    
    private function 
testPrivate() {
        echo 
"Foo::testPrivate\n";
    }
}


$myFoo = new Foo();
$myFoo->test(); // Bar::testPrivate 
                // Foo::testPublic

?>

Tầm vực của những đối tượng khác nhau

Các đối tượng có cùng kiểu có thể truy cập tới các thành phần private và protected mặc dù chúng không cùng thể hiện. Lý do là bởi vì việc thực thi những chi tiết cụ thể luôn được biết đến khi ở bên trong các đối tượng đó.

Ví dụ 3: Truy cập các thành phần private của các đối tượng cùng kiểu.

<?php
class Test
{
    private 
$foo;

    public function 
__construct($foo)
    {
        
$this->foo $foo;
    }

    private function 
bar()
    {
        echo 
'Accessed the private method.';
    }

    public function 
baz(Test $other)
    {
        
// Ta có thể thay đổi giá trị của thuộc tính private:
        
$other->foo 'hello';
        
var_dump($other->foo);

        
// Ta cũng có thể gọi được phương thức private:
        
$other->bar();
    }
}


$test = new Test('test');

$test->baz(new Test('other'));
?>

Ví dụ trên output như sau:

string(5) "hello"
Accessed the private method.

Hàm tạo (Constructor) và hàm hủy (Destructor)

Constructor ¶

Cú pháp: void __construct ([ mixed $args = "" [, $... ]] )

Từ phiên bản PHP 5  cho phép các nhà phát triển khai báo các hàm tạo cho lớp. Hàm tạo sẽ có nhiệm vụ khởi tạo giá trị cho các thuộc tính của đối tượng của lớp đó trước khi đối tượng được đem sử dụng.

Lưu ý: Các hàm tạo của lớp cha sẽ không được gọi ngầm định nếu lớp con có định nghĩa hàm tạo. Lúc này, nếu bạn muốn thực thực thi hàm tạo của lớp cha thì ở trong hàm tạo của lớp con ta sẽ thực hiện câu lệnh parent::__construct().  Nếu lớp con không định nghĩa hàm tạo thì nó có thể được thừa kế hàm tạo từ lớp cha.

Ví dụ 1: Ví dụ về hàm tạo.

<?php
class BaseClass {
   function 
__construct() {
       print 
"Trong hàm tạo của lớp BaseClass\n";
   }
}

class 
SubClass extends BaseClass {
   function 
__construct() {
       
parent::__construct();
       print 
"Trong hàm tạo của lớp SubClass\n";
   }
}

class 
OtherSubClass extends BaseClass {
    
// Lớp này sẽ thừa kế hàm tạo của lớp BaseClass
    // do không định nghĩa hàm tạo

}

// Gọi tới hàm tạo của lớp BaseClass
$obj = new BaseClass();

// Câu lệnh này sẽ gọi tới hàm tạo của cả lớp BaseClass và SubClass
$obj = new SubClass();

// Gọi tới hàm tạo của lớp BaseClass
$obj = new OtherSubClass();
?>

Không giống với phương thức thông thường, PHP sẽ không phát sinh lỗi khi hàm tạo __construct() được ghi đè với sự khác nhau về tham số so với hàm tạo __construct của lớp cha.

Lưu ý là từ phiên bản PHP 5.3.3 thì những phương thức có tên trùng với tên của lớp nằm trong namespace sẽ không còn được coi là hàm tạo của lớp đó nữa. Đương nhiên là những lớp không nằm trong namespace sẽ không chịu ảnh hưởng bởi điều này.

Ví dụ 2: Hàm tạo của lớp nằm  trong namespace.

<?php
namespace Foo;
class 
Bar {
    public function 
Bar() {
        
// được hiểu là hàm tạo ở bản PHP 5.3.0-5.3.2
        // điểu là phương thức chính quy từ bản PHP 5.3.3
    
}
}

?>

Đương nhiên là PHP cũng cho phép bạn tải chồng (overloading) hàm tạo.

Ví dụ 3: Tải chồng hàm tạo.

<?php 
class 

    function 
__construct() 
    { 
        
$a func_get_args(); 
        
$i func_num_args(); 
        if (
method_exists($this,$f='__construct'.$i)) { 
            
call_user_func_array(array($this,$f),$a);
        } 
    } 
    
    function 
__construct1($a1
    { 
        echo(
'__construct with 1 param called: '.$a1.PHP_EOL); 
    } 
    
    function 
__construct2($a1,$a2
    { 
        echo(
'__construct with 2 params called: '.$a1.','.$a2.PHP_EOL); 
    } 
    
    function 
__construct3($a1,$a2,$a3
    { 
        echo(
'__construct with 3 params called: '.$a1.','.$a2.','.$a3.PHP_EOL); 
    } 

$o = new A('sheep');
$o = new A('sheep','cat'); 
$o = new A('sheep','cat','dog');

// Sẽ in ra: 
// __construct with 1 param called: sheep 
// __construct with 2 params called: sheep,cat 
// __construct with 3 params called: sheep,cat,dog 

?>

Hàm hủy (Destructor)

void __destruct ( void )

Từ phiên bản PHP 5 trở đi cung cấp cho ta khái niệm về hàm hủy giống như những ngôn ngữ lập trình hướng đối tượng khác như Java, C#, C++. Hàm hủy sẽ được gọi đến nếu như một đối tượng nào đó không còn được tham chiếu đến nữa, hoặc chương trình đang trong quá trình tự tắt.

Ví dụ 3: Ví dụ về hàm tạo.

<?php
class MyDestructableClass {
   function 
__construct() {
       print 
"Trong hàm tạo\n";
       
$this->name "MyDestructableClass";
   }

   function 
__destruct() {
       print 
"Đang hủy " $this->name "\n";
   }
}


$obj = new MyDestructableClass();
?>

Cũng giống như hàm tạo, các hàm hủy ở lớp cha sẽ không được gọi ngầm định, để thực hiện thì tạo cần lời gọi tường minh là parent::__destruct() trong thân của hàm hủy lơp con. Và cũng tương tự như hàm tạo thì lớp con có thể thừa kế hàm hủy của lớp cha nếu lớp con không khai báo hàm hủy nào.

Hàm hủy sẽ được gọi ngay cả khi chương trình đang được dừng thông qua lời gọi hàm exit(). Nếu ta đặt lời gọi hàm exit() trong một hàm hủy thì hàm exit() sẽ không được thực thi.

Lưu ý:

Ta không thể ném một ngoại lệ từ hàm tạo, điều này sẽ phát sinh lỗi.

 

Hằng (Constant) của lớp

Ta có thể định nghĩa hằng giá trị trong một lớp. Hằng được sử dụng như những biến thông thường của lớp, nhưng không sử dụng ký hiệu $ để tạo.

Giá trị mà một hằng chứa có thể là một biểu thức hằng, không là một biến, một thuộc tính hay một lời gọi hàm.

Phiên bản PHP 5.3.0, hằng sẽ tham chiếu tới lớp như việc sử dụng biến, tức là giá trị của biến không thể là một từ khóa (ví dụ như selfparent và static).

Ví dụ 1: Định nghĩa và sử dụng một hằng

<?php
class MyClass
{
    const 
CONSTANT 'constant value';

    function 
showConstant() {
        echo  
self::CONSTANT "\n";
    }
}

echo 
MyClass::CONSTANT "\n";

$classname "MyClass";
echo 
$classname::CONSTANT "\n"// As of PHP 5.3.0

$class = new MyClass();
$class->showConstant();

echo 
$class::CONSTANT."\n"// As of PHP 5.3.0
?>

Ví dụ 2: Dữ liệu tĩnh

<?php
class foo {
    
// As of PHP 5.3.0
    
const BAR = <<<'EOT'
bar
EOT;
    
// As of PHP 5.3.0
    
const BAZ = <<<EOT
baz
EOT;
}

?>

Lưu ý:

Việc hỗ trợ khởi tạo hằng với cú pháp Heredoc và Nowdoc được thêm vào phiên bản PHP 5.3.0.

Ví dụ 3: Ví dụ về biểu thức hằng

<?php
const ONE 1;

class 
foo {
    
// As of PHP 5.6.0
    
const TWO ONE 2;
    const 
THREE ONE self::TWO;
    const 
SENTENCE 'The value of THREE is '.self::THREE;
}

?>

Có thể cung cấp một biểu thức vô hướng liên quan đến các hoặc số và hằng chuỗi và/hoặc các hằng trong lớp.

Lưu ý:

Biểu thức hằng được hỗ trợ tại phiên bản PHP 5.6.0.

Hằng của interface

Interface cũng có hằng, hằng của nó làm việc giống như hằng của lớp ngoại trừ việc hằng không thể bị ghi đè bởi lớp/interface thừa kế interface đó.

Ví dụ sau thể hiện việc sử dụng hằng trong interface.

<?php
interface a
{
    const 
'Interface constant';
}


// In ra: Interface constant
echo a::b;

// Điều sau đây sẽ không được thực hiện bởi vì không cho phép ghi đè hằng.
class implements a
{
    const 
'Class constant';
}

?>

Tải chồng (Overloading)

Tải chồng trong PHP mang nghĩa tạo các thuộc tính và phương thức động. Những thành phần động này được xử lý thông qua các magic method được thiết lập trong một lớp với các kiểu hành động khác nhau.

Các phương thức tải chồng được gọi khi tương tác với các thuộc tính và phương thức không được khai báo hay không xuất hiện trong lớp hiện thời. Bài viết này sẽ sử dụng khai niệm "thuộc tính không thể truy cập" và "phương thức không thể truy cập" để tham chiếu tới sự kết hợp của khai báo và tầm vực.

Tất các các phương thức tải chồng phải được khai báo là public.

Chú ý:

Các tham số của các phương thức magic không được truyền bằng tham chiếu.

Khái niệm "tải chồng" của PHP khác so với phần lớn các ngôn ngữ lập trình hướng đối tượng khác. Khai niệm tải chồng truyền thống là cho phép nhiều phương thức cùng tên trong một lớp nhưng khác nhau về số lượng và kiểu của tham số.

Tải chồng thuộc tính

public void __set ( string $name , mixed $value )

public mixed __get ( string $name )

public bool __isset ( string $name )

public void __unset ( string $name )

__set() được thực thi khi ghi dữ liệu tới thuộc tính không thể truy cập.

__get() được thực thi khi đọc dữ liệu từ thuộc tính không thể truy cập.

__isset() được kích hoạt bằng cách gọi isset() hoặc empty() ở những thuộc tính không thể truy cập.

__unset() được gọi đến khi unset() được sử dụng ở nhưng thuộc tính không thể truy cập.

Tham số $name là tên của thuộc tính muốn tương tác. Tham số $value của phương thức __set() xác định giá trị của thuộc tính $name được thiết lập.

Tải chồng thuộc tính chỉ làm việc với đối tượng. Những magic methods này sẽ không được kích hoạt trong trường hợp static context. Do đó những phương thức này không được khai báo là static. Ở phiên bản PHP 5.3.0 thì một cảnh báo sẽ được đưa ra nếu một sự tải chồng của magic method nào đó được khai báo là static.

Chú ý:

Giá trị trả về của __set() bị bỏ qua bởi cách thức PHP xử lý toán tử gán. Tương tự như vậy thì phương thức __get() sẽ không bao giờ được gọi khi ta thực hiện việc gán liên tiếp dạng như sau:

$a = $obj->b = 8;

Dưới đây là ví dụ về tải chồng thuộc tính thông qua các phương thức __get(), __set(), __isset() và __unset()

<?php
class PropertyTest
{
    
/**  Nơi tải chồng dữ liệu.  */
    
private $data = array();

    
/**  Tải chồng không sử dụng thuộc tính đã khai báo.  */
    
public $declared 1;

    
/**  Tải chồng chỉ sử dụng khi truy cập ngoài lớp.  */
    
private $hidden 2;

    public function 
__set($name$value)
    {
        echo 
"Thiết lập '$name' = '$value'\n";
        
$this->data[$name] = $value;
    }

    public function 
__get($name)
    {
        echo 
"Lấy '$name'\n";
        if (
array_key_exists($name$this->data)) {
            return 
$this->data[$name];
        }

        
$trace debug_backtrace();
        
trigger_error(
            
'Không định nghĩa thuộc tính thông qua __get(): ' $name .
            
' trong ' $trace[0]['file'] .
            
' tại dòng ' $trace[0]['line'],
            
E_USER_NOTICE);
        return 
null;
    }

    
/**  Phiên bản PHP 5.1.0  */
    
public function __isset($name)
    {
        echo 
"'$name' được thiết lập?\n";
        return isset(
$this->data[$name]);
    }

    
/**  Phiên bản PHP 5.1.0  */
    
public function __unset($name)
    {
        echo 
"Không thiết lập '$name'\n";
        unset(
$this->data[$name]);
    }

    
/**  Đây không phải là magic method.  */
    
public function getHidden()
    {
        return 
$this->hidden;
    }
}


echo 
"<pre>\n";

$obj = new PropertyTest;

$obj->1;
echo 
$obj->"\n\n";

var_dump(isset($obj->a));
unset(
$obj->a);
var_dump(isset($obj->a));
echo 
"\n";

echo 
$obj->declared "\n\n";

echo 
"Thử nghiệm với phương thức private có tên 'hidden':\n";
echo 
"Private xuất hiện trong lớp, nên __get() không được sử dụng...\n";
echo 
$obj->getHidden() . "\n";
echo 
"Private không xuất hiện ngoài lớp, nên __get() được sử dụng...\n";
echo 
$obj->hidden "\n";
?>

Output của ví dụ trên:

Thiết lập 'a' = '1'
Lấy 'a'
1

'a' được thiết lập?
bool(true)
Không thiết lập 'a'
'a' được thiết lập?
bool(false)

1

Thử nghiệm với phương thức private có tên 'hidden':
Private xuất hiện trong lớp, nên __get() không được sử dụng...
2
Private không xuất hiện ngoài lớp, nên __get() được sử dụng...
Lấy 'hidden'

Notice:  Thuộc tính không định nghĩa thông qua __get(): hidden trong <file> tại dòng 70 trong <file> tại dòng 29

Tải chồng phương thức

public mixed __call ( string $name , array $arguments )

public static mixed __callStatic ( string $name , array $arguments )

__call() được kích hoạt khi gọi phương thức không thể truy cập của đối tượng.

__callStatic() được kích hoạt khi gọi phương thức không thể truy cập trong phạm vi static.

Tham số $name là tên của phương thức được gọi. Tham số $arguments là một mảng chứa các tham số được truyền tới phương thức có tên $name.

Ví dụ sau nói về các phương thức tải chồng __call() và __callStatic()

<?php
class MethodTest
{
    public function 
__call($name$arguments)
    {
        
// Lưu ý: giá trị của $name là phân biệt hoa/thường.
        
echo "Gọi phương thức '$name' "
             
implode(', '$arguments). "\n";
    }

    
/**  PHP 5.3.0  */
    
public static function __callStatic($name$arguments)
    {
        
// Lưu ý: giá trị của $name phân biệt hoa/thường.
        
echo "Gọi phương thức static '$name' "
             
implode(', '$arguments). "\n";
    }
}


$obj = new MethodTest;
$obj->runTest('trong đối tượng');

MethodTest::runTest('trong trường hợp static');  // PHP 5.3.0
?>

Output của đoạn mã trên:

Gọi phương thức 'runTest' trong đối tượng
Gọi phương thức tĩnh 'runTest' trong trường hợp static

Toán tử ::

Toán tử (::) dùng để truy cập các thành phần static và hằng, nó cũng có tác dụng ghi đè các thuộc tính và phương thức của lớp.

Khi sử dụng toán tử này ngoài lớp thì ta đi kèm với tên của lớp đó.

Phiên bản PHP 5.3.0 cho phép tham chiếu tới lớp bằng cách sử dụng một biến, trong đó giá trị của biến không được là một từ khóa (selfparent và static).

Ví dụ 1: Sử dụng :: bên ngoài định nghĩa lớp.

<?php
class MyClass {
    const 
CONST_VALUE 'A constant value';
}


$classname 'MyClass';
echo 
$classname::CONST_VALUE// PHP 5.3.0

echo MyClass::CONST_VALUE;
?>

Ba từ khóa đặc biệt selfparent và static được dùng để truy cập các thuộc tính hoặc phương thức từ bên trong định nghĩa lớp.

Ví dụ 2: Sử dụng :: bên trong định nghĩa lớp.

<?php
class OtherClass extends MyClass
{
    public static 
$my_static 'static var';

    public static function 
doubleColon() {
        echo 
parent::CONST_VALUE "\n";
        echo 
self::$my_static "\n";
    }
}


$classname 'OtherClass';
echo 
$classname::doubleColon(); // PHP 5.3.0

OtherClass::doubleColon();
?>

Khi lớp con ghi đè một phương thức của lớp cha thì PHP sẽ không gọi phương thức của lớp cha. Điều này có nghĩa từ lớp con có thể gọi hoặc không gọi được phương thức của lớp cha. Điều này cũng được áp dụng cho Hàm tạo và Hàm hủy, Tải chồng, và Magic methods.

Ví dụ 3: Gọi phương thức của lớp cha.

<?php
class MyClass
{
    protected function 
myFunc() {
        echo 
"MyClass::myFunc()\n";
    }
}

class 
OtherClass extends MyClass
{
    
// Ghi đè phương thức của lớp cha
    
public function myFunc()
    {
        
// Nhưng vẫn có thể gọi phương thức đó của lớp cha
        
parent::myFunc();
        echo 
"OtherClass::myFunc()\n";
    }
}


$class = new OtherClass();
$class->myFunc();
?>

Từ khóa final

Từ bản PHP 5 trở đi có giới thiệu về từ khóa final, từ khóa này sẽ ngăn cản không cho lớp con ghi đè phương thức bằng cách đặt trước định nghĩa phương thức đó từ khóa final. Nếu bản thân lớp được định nghĩa là final thì nó không cho phép kế thừa.

Ví dụ 1: Ví dụ về phương thức final

<?php
class BaseClass {
   public function 
test() {
       echo 
"BaseClass::test() called\n";
   }
   
   final public function 
moreTesting() {
       echo 
"BaseClass::moreTesting() called\n";
   }
}

class 
ChildClass extends BaseClass {
   public function 
moreTesting() {
       echo 
"ChildClass::moreTesting() called\n";
   }
}

// Kết quả là lỗi Fatal: Không thể ghi đè phương thức final BaseClass::moreTesting()
?>

Ví dụ 2: Ví dụ về lớp final

<?php
final class BaseClass {
   public function 
test() {
       echo 
"BaseClass::test() called\n";
   }

   
// Bạn có thể khai báo phương thức trong lớp final là final hoặc không
   
final public function moreTesting() {
       echo 
"BaseClass::moreTesting() called\n";
   }
}

class 
ChildClass extends BaseClass {
}

// Kết quả là lỗi Fatal: Lớp ChildClass không thể thừa kế lớp final (BaseClass)
?>

Lưu ý: Thuộc tính không thể được khai báo là final, chỉ áp dụng được điều này cho lớp và phương thức.

Interface

Đối tượng interface (giao diện) cho phép bạn tạo mã lệnh để xác định những phương thức mà một lớp phải thực thi, bạn không được định nghĩa những phương thức trong interface mà chỉ được khai báo chúng.

Việc định nghĩa interface cũng giống như định nghĩa một lớp chỉ khác là ta dùng từ khóa interface thay cho từ khóa class và không có bất kỳ một phương thức nào được định nghĩa trong đó.

Tất cả các phương thức trong interface đều phải là public (đây là tầm vực duy nhất sử dụng được trong interface).

Thực thi interface

Để thực thi một interface thì ta sử dụng toán tử implements. Tất cả các phương thức trong interface phải được thực thi trong lớp class nếu không sẽ phát sinh lỗi. Mỗi lớp có quyền thực thi nhiều interface, khi đó ta dùng dấu phẩy (,) để phân cách các interface.

Lưu ý:

Trước PHP 5.3.9, một lớp không được phép thực thi hai interface mà có chứa phương thức cùng tên vì điều này sẽ gây ra sự mơ hồ. Các phiên bản hiện tại cho phép điều này miễn là các phương thức cùng tên phải có cùng signature.

Interface cũng có quyền mở rộng giống như lớp bằng cách sử dụng từ khóa extends.

Lớp thực thi interface thì phải sử dụng đúng phương thức của interface đó với tên và signature y như đã được khai báo ở interface.

Hằng

Interface được quyền chứa các hằng. Các hằng của interface làm việc như là các hằng của lớp ngoại trừ chúng không thể được ghi đè bởi lớp/interface thừa kế.

Ví dụ

Ví dụ 1: Ví dụ Interface

<?php

// Khai báo interface 'iTemplate'
interface iTemplate
{
    public function 
setVariable($name$var);
    public function 
getHtml($template);
}


// Thực thi interface
class Template implements iTemplate
{
    private 
$vars = array();
  
    public function 
setVariable($name$var)
    {
        
$this->vars[$name] = $var;
    }
  
    public function 
getHtml($template)
    {
        foreach(
$this->vars as $name => $value) {
            
$template str_replace('{' $name '}'$value$template);
        }
 
        return 
$template;
    }
}


// Phát sinh lỗi: lớp BadTemplate không thực thi đầy đủ các phương thức của interface
class BadTemplate implements iTemplate
{
    private 
$vars = array();
  
    public function 
setVariable($name$var)
    {
        
$this->vars[$name] = $var;
    }
}

?>

Ví dụ 2: Mở rộng interface

<?php
interface a
{
    public function 
foo();
}

interface 
extends a
{
    public function 
baz(Baz $baz);
}


class implements b
{
    public function 
foo()
    {
    }

    public function 
baz(Baz $baz)
    {
    }
}


// Phát sinh lỗi: signature của phương thức baz() không giống với khai báo ở interface b
class implements b
{
    public function 
foo()
    {
    }

    public function 
baz(Foo $foo)
    {
    }
}

?>

Ví dụ 3: Thừa kế nhiều interface

<?php
interface a
{
    public function 
foo();
}

interface 
b
{
    public function 
bar();
}

interface 
extends ab
{
    public function 
baz();
}

class 
implements c
{
    public function 
foo()
    {
    }

    public function 
bar()
    {
    }

    public function 
baz()
    {
    }
}

?>

Ví dụ 4: Hằng trong interface.

<?php
interface a
{
    const 
'Interface constant';
}


// In ra: Interface constant
echo a::b;

// Phát sinh lỗi: không được ghi đè hằng của interface.
class implements a
{
    const 
'Class constant';
}

?>

Ngoại lệ (Exception)

PHP 5 có mô hình ngoại lệ tương tự như những ngôn ngữ lập trình khác. Ngoại lệ có thẻ được ném (throw) và bắt (catch) trong PHP. Mã lệnh có thể được đặt trong khối try để thuận tiên cho việc phát hiện ngoại lệ. Mỗi khối try phải có ít nhật một khối catch hoặc finally.

Đối tượng được ném ra phải là một thể hiện của lớp Exception hoặc lớp con của nó. Việc cố ném một đối sẽ không có kết quả trong PHP Fatal Error.

catch

Khối nhiều catch có thể được sử dụng để bắt các lớp ngoại lệ khác nhau. Ngoại lệ thông thường (khi không có ngoại lệ nào được ném từ khối try) sẽ tiếp tục sau khối catch cuối cùng được định nghĩa. Ngoại lệ cũng có thể được ném (hoặc ném lại) trong khối catch.

Khi một ngoại lệ được ném thì mã lệnh phía sau trong khối đó sẽ không được thực thi, và PHP sẽ cố tìm khối catch đầu tiên phù hợp với ngoại lệ đó. Nếu ngoại lệ nào đó không bắt được thì PHP Fatal Error sẽ đưa ra thông điệp "Uncaught Exception ..." khi một bộ xửl ý được định nghĩa với phương thức set_exception_handler().

finally

Từ phiên bản PHP 5.5, một khối finally cũng có thể được đặt sau hoặc thay thế cho khối catch. Mã lệnh trong khối finally sẽ luôn luôn được thực thi sau khối try và catch, ngay cả khi ngoại lệ được ném hay không.

Lưu ý

Các hàm trong PHP chủ yếu sử dụng thông báo lỗi, chỉ những phần mở rộng hướng đối tượng hiện đại mới sử dụng ngoại lệ. Tuy nhiên thì các lỗi có thể được chuyển đơn giản sang ngoại lệ với ErrorException.

Gợi ý

Standard PHP Library (SPL) cung cấp một số lượng các ngoại lệ được xây dựng sẵn rất hữu ích.

Ví dụ

Ví dụ ném một ngoại lệ:

<?php
function inverse($x) {
    if (!
$x) {
        throw new 
Exception('Division by zero.');
    }
    return 
1/$x;
}

try {
    echo 
inverse(5) . "\n";
    echo 
inverse(0) . "\n";
} catch (
Exception $e) {
    echo 
'Caught exception: ',  $e->getMessage(), "\n";
}


// Tiếp tục thực thi
echo "Hello World\n";
?>

Đoạn mã trên sẽ in ra:

0.2
Caught exception: Division by zero.
Hello World

Ví dụ 2: Xử lý ngoại lệ với khối finally

<?php
function inverse($x) {
    if (!
$x) {
        throw new 
Exception('Division by zero.');
    }
    return 
1/$x;
}

try {
    echo 
inverse(5) . "\n";
} catch (
Exception $e) {
    echo 
'Caught exception: ',  $e->getMessage(), "\n";
finally {
    echo 
"First finally.\n";
}

try {
    echo 
inverse(0) . "\n";
} catch (
Exception $e) {
    echo 
'Caught exception: ',  $e->getMessage(), "\n";
finally {
    echo 
"Second finally.\n";
}


// Tiếp tục thực thi
echo "Hello World\n";
?>

Ví dụ trên sẽ in ra:

0.2
First finally.
Caught exception: Division by zero.
Second finally.
Hello World

Ví dụ 3: Ngoại lệ lồng

<?php

class MyException extends Exception { }

class 
Test {
    public function 
testing() {
        try {
            try {
                throw new 
MyException('foo!');
            } catch (
MyException $e) {
                
// ném lại nó
                
throw $e;
            }
        } catch (
Exception $e) {
            
var_dump($e->getMessage());
        }
    }
}


$foo = new Test;
$foo->testing();

?>

 Ví dụ trên sẽ in ra:

string(4) "foo!"

Xem thêm

Thừa kế ngoại lệ 

Thừa kế Ngoại lệ

Ta có thể định nghĩa một lớp ngoại lệ riêng bằng cách thừa kế lớp Exception. Các thành phần và thuộc tính phía dưới đây cho thấy khả năng truy cập trong lớp con được dẫn xuất từ lớp Exception.

Ví dụ 1: Lớp Exception

<?php
class Exception
{
    protected 
$message 'Unknown exception';   // Thông báo ngoại lệ
    
private   $string;                          // đệm __toString
    
protected $code 0;                        // Mã lệnh ngoại lệ do người dùng định nghĩa
    
protected $file;                            // file nguồn của ngoại lệ
    
protected $line;                            // dòng nguồn của ngoại lệ
    
private   $trace;                           // backtrace
    
private   $previous;                        // ngoại lệ trước nếu có ngoại lệ lồng

    
public function __construct($message null$code 0Exception $previous null);

    final private function 
__clone();           // Không có phép nhân bản ngoại lệ.

    
final public  function getMessage();        // thông báo của ngoại lệ
    
final public  function getCode();           // mã lệnh của ngoại lệ
    
final public  function getFile();           // file nguồn
    
final public  function getLine();           // dòng nguồn
    
final public  function getTrace();          // mảng backtrace()
    
final public  function getPrevious();       // ngoại lệ trước
    
final public  function getTraceAsString();  // chuỗi định dạng để theo dõi

    // Có thể ghi đè
    
public function __toString();               // chuỗi định dạng để hiển thị
}
?>

Nếu một lớp dẫn xuất từ lớp Exception và định nghĩa lại hàm tạo thì bạn nên sử dụng parent::__construct() để đảm bảo rằng tất cả các dữ liệu cho phép sẽ được gán giá trị hợp lệ. Phương thức __toString() có thể được ghi đè để cung cấp một đầu ra tùy chỉnh khi đối tượng được thể hiện dưới dạng chuỗi.

Lưu ý:

Ngoại lệ không thể được sao chép. Việc cố gắng sao chép một ngoại lệ sẽ dẫn tới lỗi E_ERROR.

Ví dụ 2: Dẫn xuất từ lớp Exception (PHP 5.3.0+)

<?php
/**
 * Định nghĩa một lớp ngoại lệ tùy chỉnh
 */

class MyException extends Exception
{
    
// Định nghĩa lại ngoại lệ nên thông báo không phải là một lựa chọn
    
public function __construct($message$code 0Exception $previous null) {
        
// code
    
        // đảm bảo mọi thứ được gán đúng giá trị
        
parent::__construct($message$code$previous);
    }

    
// chuỗi tùy chỉnh thể hiện lại đối tượng
    
public function __toString() {
        return 
__CLASS__ ": [{$this->code}]: {$this->message}\n";
    }

    public function 
customFunction() {
        echo 
"Một hàm tùy chỉnh A custom function for this type of exception\n";
    }
}



/**
 * Create a class to test the exception
 */

class TestException
{
    public 
$var;

    const 
THROW_NONE    0;
    const 
THROW_CUSTOM  1;
    const 
THROW_DEFAULT 2;

    function 
__construct($avalue self::THROW_NONE) {

        switch (
$avalue) {
            case 
self::THROW_CUSTOM:
                
// throw custom exception
                
throw new MyException('1 is an invalid parameter'5);
                break;

            case 
self::THROW_DEFAULT:
                
// throw default one.
                
throw new Exception('2 is not allowed as a parameter'6);
                break;

            default: 
                
// No exception, object will be created.
                
$this->var $avalue;
                break;
        }
    }
}



// Example 1
try {
    
$o = new TestException(TestException::THROW_CUSTOM);
} catch (
MyException $e) {      // Will be caught
    
echo "Caught my exception\n"$e;
    
$e->customFunction();
} catch (
Exception $e) {        // Skipped
    
echo "Caught Default Exception\n"$e;
}


// Continue execution
var_dump($o); // Null
echo "\n\n";


// Example 2
try {
    
$o = new TestException(TestException::THROW_DEFAULT);
} catch (
MyException $e) {      // Doesn't match this type
    
echo "Caught my exception\n"$e;
    
$e->customFunction();
} catch (
Exception $e) {        // Will be caught
    
echo "Caught Default Exception\n"$e;
}


// Continue execution
var_dump($o); // Null
echo "\n\n";


// Example 3
try {
    
$o = new TestException(TestException::THROW_CUSTOM);
} catch (
Exception $e) {        // Will be caught
    
echo "Default Exception caught\n"$e;
}


// Continue execution
var_dump($o); // Null
echo "\n\n";


// Example 4
try {
    
$o = new TestException();
} catch (
Exception $e) {        // Skipped, no exception
    
echo "Default Exception caught\n"$e;
}


// Continue execution
var_dump($o); // TestException
echo "\n\n";
?>

Lưu ý:

Các phiên bản PHP 5 trước PHP 5.3.0 không hỗ trợ ngoại lệ lồng. Đoạn mã sau đây có thể được sử dụng như một lớp MyException thay thế nếu bạn muốn chạy ví dụ này.

<?php
/**
 * Define a custom exception class
 */

class MyException extends Exception
{
    
// Redefine the exception so message isn't optional
    
public function __construct($message$code 0) {
        
// some code
    
        // make sure everything is assigned properly
        
parent::__construct($message$code);
    }

    
// custom string representation of object
    
public function __toString() {
        return 
__CLASS__ ": [{$this->code}]: {$this->message}\n";
    }

    public function 
customFunction() {
        echo 
"A custom function for this type of exception\n";
    }
}

?>

set_exception_handler

Phiên bản PHP áp dụng: PHP 5, PHP 7.

set_exception_handler() dùng để thiết lập một hàm xử lý ngoại lệ do người dùng định nghĩa.

Mô tả

callable set_exception_handler ( callable $exception_handler )

Thiết lập bộ xử lý ngoại lệ mặc định nếu một ngoại lệ nào đó không được bắt trong khối try/catch. Việc thực thi sẽ dừng lại sau khi tham số exception_handler được gọi.

Tham số

exception_handler

Tên của hàm được gọi khi không bắt được ngoại lệ. Chức năng xử lý này cần có một tham số đố đối tượng ngoại lệ được ném. Dưới đây là bộ xử lý trước PHP 7:

void handler ( Exception $ex )

Từ PHP 7 thì phần lớn lỗi được thông báo bằng cách ném các ngoại lệ Error, bộ xử lý sẽ bắt những ngoại lệ này tốt hơn. Cả Error và Exception đều thực thi giao diện Throwable. Còn đây là bộ xử lý từ PHP 7:

void handler ( Throwable $ex )

NULL có thể được truyền thay thế cho Throwable để thiết lập lại bộ xử lý này thành trạng thái mặc dịnh của nó.

Cảnh báo

Cần lưu ý rằng việc cung cấp một kiểu Exception tường minh cho tham số $ex trong callback sẽ gặp phải vấn đề do sự thay đổi cấu trúc ngoại lệ trong PHP 7.

Giá trị trả về

Trả về tên của bộ xử lý ngoại lệ đã định nghĩa trước đó, hoặc NULL khi gặp lỗi hoặc nếu không định nghĩa bộ xử lý nào trước đó.

Changelog

Phiên bản Mô tả
7.0.0 Kiểu của tham số truyền vào exception_handler đã thay đổi từ Exception thành Throwable
5.5.0 Trước đó, nếu NULL được truyền thì hàm này trả về TRUE. Nó trả về bộ xử lý trước đó từ phiên bản PHP 5.5.0.

Ví dụ:

Dưới đây là ví dụ về set_exception_handler()

<?php
function exception_handler($exception) {
  echo 
"Ngoại lệ không được bắt: " $exception->getMessage(), "\n";
}


set_exception_handler('exception_handler');

throw new 
Exception('Ngoại lệ không được bắt');
echo 
"Không thực thi\n";
?>

ErrorException

Phiên bản PHP hỗ trợ: (PHP 5 >= 5.1.0, PHP 7)

Đây là loại lớp thừa kế từ lớp Exception. Nội dung tổng quan của lớp này được thể hiện như dưới đây:

ErrorException extends Exception {
/* Các thuộc tính */
protected int $severity ;
/* Các thuộc tính thừa kế */
protected string $message ;
protected int $code ;
protected string $file ;
protected int $line ;
/* Các phương thức */
public __construct ([ string $message = "" [, int $code = 0 [, int $severity = E_ERROR [,string $filename = __FILE__ [, int $lineno = __LINE__ [, Exception $previous = NULL ]]]]]] )
final public int getSeverity ( void )
/* Các phương thức thừa kế */
final public string Exception::getMessage ( void )
final public Exception Exception::getPrevious ( void )
final public mixed Exception::getCode ( void )
final public string Exception::getFile ( void )
final public int Exception::getLine ( void )
final public array Exception::getTrace ( void )
final public string Exception::getTraceAsString ( void )
public string Exception::__toString ( void )
final private void Exception::__clone ( void )

}

Thuộc tính

severity

Thuộc tính này thể hiện mức độ nghiêm trọng của ngoại lệ.

Ví dụ

Ví dụ sau sử dụng phương thức set_error_handler() để thay đổi thông báo lỗi của ErrorException.

<?php
function exception_error_handler($severity$message$file$line) {
    if (!(
error_reporting() & $severity)) {
        
// Đoạn mã lỗi này không nằm trong thông báo lỗi
        
return;
    }
    throw new 
ErrorException($message0$severity$file$line);
}

set_error_handler("exception_error_handler");

/* Kích hoạt ngoại lệ */
strpos();
?>

 Output của ví dụ trên có dạng như sau:

Fatal error: Uncaught exception 'ErrorException' with message 'strpos() expects at least 2 parameters, 0 given' in /home/bjori/tmp/ex.php:12
Stack trace:
#0 [internal function]: exception_error_handler(2, 'strpos() expect...', '/home/bjori/php...', 12, Array)
#1 /home/bjori/php/cleandocs/test.php(12): strpos()
#2 {main}
  thrown in /home/bjori/tmp/ex.php on line 12

Clone đối tượng

Việc tạo một bản sao của một đối tượng với đầy đủ các thuộc tính được sao chép đôi khi là điều cần thiết. Một ví dụ là sự cần thiết phải sao chép các hàm tạo là nếu bạn có một đối tượng thể hiện một cửa sổ GTK và đối tượng đó chứa tài nguyên của cửa sổ GTK, khi bạn tạo bản sao bạn có thể muốn tạo một cửa sổ mới với các thuộc tính tương tự và có đối tượng mới chứa tài nguyên của cửa sổ mới. Một ví dụ khác là nếu đối tượng của bạn chứa một tham chiếu tới đối tượng khác và khi bạn nhân bản đối tượng cha bạn muốn tạo một thể hiện mới của đối tượng khác này để việc nhân bản có bản copy độc lập của chính nó.

Một đối tượng được sao chép được tạo bằng cách sử dụng từ khóa clone (điều này sẽ gọi tới phương thức __clone() của đối tượng nếu cần thiết). Phương thức __clone() của đối tượng không thể được gọi trực tiếp. Ví dụ,

$copy_of_object = clone $object;

Khi một đối tượng được nhân bản thì PHP 5 sẽ tạo một bản copy mức thấp các thuộc tính của đối tượng. Bất kỳ thuộc tính nào tham chiếu tới các biến khác nhau sẽ đều được giữ giam chiếu. Cú pháp của phương thức __clone() như sau:

void __clone ( void )

Sau khi nhân bản hoàn chỉnh thì phương thức __clone() sẽ được định nghĩa, khi đó phương thức __clone() của đối tượng mới được tạo sẽ được gọi, và nó cho phép bất kỳ thuộc tính cần thiết nào cũng có thể thay đổi được.

Ví dụ 1: Nhân bản đối tượng

<?php
class SubObject
{
    static 
$instances 0;
    public 
$instance;

    public function 
__construct() {
        
$this->instance = ++self::$instances;
    }

    public function 
__clone() {
        
$this->instance = ++self::$instances;
    }
}

class 
MyCloneable
{
    public 
$object1;
    public 
$object2;

    function 
__clone()
    {
        
// Tạo bản sao của this->object, nếu không
        // nó sẽ trỏ đến cùng một đối tượng.
        
$this->object1 = clone $this->object1;
    }
}


$obj = new MyCloneable();

$obj->object1 = new SubObject();
$obj->object2 = new SubObject();

$obj2 = clone $obj;


print(
"Original Object:\n");
print_r($obj);

print(
"Cloned Object:\n");
print_r($obj2);

?>

 Output của ví dụ trên:

Original Object:
MyCloneable Object
(
    [object1] => SubObject Object
        (
            [instance] => 1
        )

    [object2] => SubObject Object
        (
            [instance] => 2
        )

)
Cloned Object:
MyCloneable Object
(
    [object1] => SubObject Object
        (
            [instance] => 3
        )

    [object2] => SubObject Object
        (
            [instance] => 2
        )

)

So sánh đối tượng

Khi sử dụng phép toán so sánh (==), thì các biến đối tượng được so sánh theo một nghĩa đơn giản: Hai thể hiện đối tượng bằng nhau nếu chúng có cùng các thuộc tính và giá trị, và chúng thuộc cùng một lớp.

Khi tử dụng phéo toán identity (===), thì các biến đối tượng là giống hệt nhau nếu và chỉ nếu chúng tham chiếu tới cùng một thể hiện của lớp.

Ví dụ sau đây sẽ làm rõ quy tắc trên.

<?php
function bool2str($bool)
{
    if (
$bool === false) {
        return 
'FALSE';
    } else {
        return 
'TRUE';
    }
}

function 
compareObjects(&$o1, &$o2)
{
    echo 
'o1 == o2 : ' bool2str($o1 == $o2) . "\n";
    echo 
'o1 != o2 : ' bool2str($o1 != $o2) . "\n";
    echo 
'o1 === o2 : ' bool2str($o1 === $o2) . "\n";
    echo 
'o1 !== o2 : ' bool2str($o1 !== $o2) . "\n";
}

class 
Flag
{
    public 
$flag;

    function 
Flag($flag true) {
        
$this->flag $flag;
    }
}

class 
OtherFlag
{
    public 
$flag;

    function 
OtherFlag($flag true) {
        
$this->flag $flag;
    }
}


$o = new Flag();
$p = new Flag();
$q $o;
$r = new OtherFlag();

echo 
"Two instances of the same class\n";
compareObjects($o$p);

echo 
"\nTwo references to the same instance\n";
compareObjects($o$q);

echo 
"\nInstances of two different classes\n";
compareObjects($o$r);
?>

Output của ví dụ trên:

Two instances of the same class
o1 == o2 : TRUE
o1 != o2 : FALSE
o1 === o2 : FALSE
o1 !== o2 : TRUE

Two references to the same instance
o1 == o2 : TRUE
o1 != o2 : FALSE
o1 === o2 : TRUE
o1 !== o2 : FALSE

Instances of two different classes
o1 == o2 : FALSE
o1 != o2 : TRUE
o1 === o2 : FALSE
o1 !== o2 : TRUE

Trừu tượng (Abstract)

Tổng quan

Từ phiên bản PHP 5 thì PHP giới thiệu các khái niệm lớp trừu tượngphương thức trừu tượng. Những lớp được định nghĩa là trừu tượng thì không được có thể hiện (không tạo được thể hiện hay đối tượng của lớp trừu tượng), và bất kỳ lớp nào chứa ít nhất một phương thức trừu tượng thì phải là lớp trừu tượng. Đối với phương thức trừu tượng thì ta chỉ khai báo mà không được định nghĩa.

Các lớp khác có quyền thừa kế từ lớp trừu tượng. Khi thừa kế từ lớp trừu tượng thì tất cả các phương thức trừu tượng của lớp cha phải được lớp con thực thi (định nghĩa); một điểm nữa là những phương thức này phải được định nghĩa với tầm vực tương tự (không thấp hơn) hoặc cao hơn. Ví dụ như nếu phương thức trừu tượng được định nghĩa là protected thì việc thực thi phương thức này ở lớp con cũng phải được định nghĩa là protected hoặc cao hơn (public). Tuy vậy, bạn lại không cần thực thi phương thức ở lớp con với các dấu hiệu (signature) phải y hệt như của phương trừu tượng ở lớp cha, tức là bạn có quyền đưa thêm đối số tùy chọn vào phương thức thực thi ở lớp con nếu bạn muốn. Đặc điểm này cũng được áp dụng cho các hàm tạo.

Để định nghĩa một lớp nào đó là trừu tượng ta thêm từ khóa abstract vào trước từ khóa class của lớp đó.

Còn để khai báo một phương thức nào đó là trừu tượng ta thêm từ khóa abstract vào trước từ khóa function hoặc trước tầm vực (nếu có) của phương thức đó. Dưới đây là những ví dụ về cách sử dụng abstract.

Ví dụ 1:

<?php
abstract class AbstractClass
{
    
// Những phương thức trừu tượng này phải được thực thi ở lớp thừa kế
    
abstract protected function getValue();
    abstract protected function 
prefixValue($prefix);

    
// Phương thức thông thường
    
public function printOut() {
        print 
$this->getValue() . "\n";
    }
}

class 
ConcreteClass1 extends AbstractClass
{
    protected function 
getValue() {
        return 
"ConcreteClass1";
    }

    public function 
prefixValue($prefix) {
        return 
"{$prefix}ConcreteClass1";
    }
}

class 
ConcreteClass2 extends AbstractClass
{
    public function 
getValue() {
        return 
"ConcreteClass2";
    }

    public function 
prefixValue($prefix) {
        return 
"{$prefix}ConcreteClass2";
    }
}


$class1 = new ConcreteClass1;
$class1->printOut();
echo 
$class1->prefixValue('FOO_') ."\n";

$class2 = new ConcreteClass2;
$class2->printOut();
echo 
$class2->prefixValue('FOO_') ."\n";
?>

Ví dụ trên sẽ in ra:

ConcreteClass1
FOO_ConcreteClass1
ConcreteClass2
FOO_ConcreteClass2

Ví dụ 2:

<?php
abstract class AbstractClass
{
    
// Phương thức trừu tượng này có một đối số
    
abstract protected function prefixName($name);
}

class 
ConcreteClass extends AbstractClass
{
    
// Ta có quyền thực thi phương thức trừu tượng ở lớp con với đối số tùy chọn
    // mà không có trong phương thức trừu tượng của lớp cha
    
public function prefixName($name$separator ".") {
        if (
$name == "Pacman") {
            
$prefix "Mr";
        } elseif (
$name == "Pacwoman") {
            
$prefix "Mrs";
        } else {
            
$prefix "";
        }
        return 
"{$prefix}{$separator} {$name}";
    }
}


$class = new ConcreteClass;
echo 
$class->prefixName("Pacman"), "\n";
echo 
$class->prefixName("Pacwoman"), "\n";
?>

Ví dụ trên sẽ in ra:

Mr. Pacman
Mrs. Pacwoman

Cách lấy ngẫu nhiên bản ghi bằng hàm RAND()

Trong trường hợp ta cần phải chọn lựa dữ liệu ngẫu nhiên từ các bảng trong database, ví dụ như chọn một số bài viết ngẫu nhiên từ trang blog hoặc chọn ngẫu nhiên một số sản phẩm và hiển thị chúng trên các sidebar, chọn lựa hình ảnh ngẫu nhiên từ gallery, ...

Cách chọn lựa dữ liệu ngẫu nhiên từ MySQL SelectMySQL không có bất kỳ một câu lệnh nào giúp ta lấy dữ liệu ngẫu nhiên, nhưng chúng ta sẽ tận dụng hàm RAND(). Đoạn mã sau sẽ giúp các bạn lấy ngẫu nhiên 1 bản ghi từ bảng sanpham.

SELECT * FROM sanpham ORDER BY RAND() LIMIT 1;

Trong đoạn truy vấn bên trên, ORDER BY sẽ sắp xếp kết quả theo thứ tự ngẫu nhiên, và LIMIT 1 sẽ chỉ lấy 1 bản ghi.

Nếu muốn lấy N bản ghi (N là một số nguyên dương) thì ta làm như sau:

SELECT * FROM tên_bảng ORDER BY RAND()  LIMIT N

Vi dụ như nếu muốn lấy 5 sản phẩm ngẫu nhiên, chúng ta viết câu truy vấn như sau:

SELECT productName FROM sanpham ORDER BY RAND() LIMIT 5;

Cách chọn lựa dữ liệu ngẫu nhiên từ MySQL Select

Lưu ý: kỹ thuật này chỉ thích hợp cho những bảng có ít dữ liệu, nếu không thì nó sẽ tốn nhiều thời gian cho việc lấy ngẫu nhiên, do đó kết quả trả về sẽ chậm.

Trong trường hợp bảng nào có cột ID với giá trị trải dài từ 1 đến N lần thi chúng ta có thể sử dụng kỹ thuật như sau:

- Đầu tiên, chúng ta sẽ chọn ngẫu nhiên số lượng trong khoảng từ 1 đến N

- Kế tiếp, chúng ta sẽ lấy dữ liệu ngẫu nhiên dựa trên số lượng ngẫu nhiên này.

Để dễ hiểu, ta xét đoạn truy vấn sql sau:

SET @ID = FLOOR(RAND( )* N) + 1;

SELECT *  FROM table WHERE ID >= @ID LIMIT 1

Kỹ thuật này sẽ trả về kết quả nhanh hơn bởi vì:

- Nó sử dụng cột ID để đánh dấu chỉ mục.

- MySQL không cần phải sắp xếp lại toàn bộ table.

declare

Phiên bản: PHP 4, PHP 5, PHP 7.

Cấu trúc declare được sử dụng để thiết lập các chỉ thị thực hiện cho khối mã lệnh. Cú pháp của declare tương tự như cú pháp của các cấu trúc điều khiển khác:

declare (directive)
    statement

Phần directive cho phép thiết lập hành vi của khối declare. Hiện tại thì chỉ có ba chỉ thị sau được chấp nhận là chỉ thị ticks, chỉ thị encoding và chỉ thị strict_types.

Phiên bản Mô tả
5.3.0 Thêm chỉ thị encoding
7.0.0 Thêm chỉ thị strict_types directive

Các chỉ thị được xử lý giống như file được biên dịch, chỉ có các literal là được chấp nhận như là các giá trị của chỉ thị, còn biến và hằng thì không thể được sử dụng. Dưới đây là ví dụ minh họa:

<?php
// This is valid:
declare(ticks=1);

// This is invalid:
const TICK_VALUE 1;
declare(
ticks=TICK_VALUE);
?>

Phần statement của khối declare sẽ được thực thi - nó thực thi thế nào và xảy ra hiệu ứng gì trong quá trình thực thi có thể phụ thuộc vào tập chỉ thị trong khối directive.

Cấu trúc declare cũng có thể được sử dụng ở phạm vi global, điều này sẽ ảnh hưởng đến mã lệnh sau nó (tuy nhiên nếu đưa vào tập tin có chứa declare thì nó sẽ không ảnh hưởng đến tập tin cha).

<?php
// these are the same:

// you can use this:

declare(ticks=1) {
    
// entire script here
}

// or you can use this:
declare(ticks=1);
// entire script here
?>

Tick

Mỗi tick là một sự kiện xảy ra cho mỗi N câu lệnh có khả năng đánh dấu là mức thấp bởi bộ truyền trong khối declare. Giá trị của N được xác định bằng cách sử dụng ticks=N trong phần directive của khối declare.

Không phải tất cả các câu lệnh đều có khả năng đánh dấu. Thông thường thì những biểu thức điều kiện và biểu thức tham số không có khả năng đánh dấu.

Sự kiện xảy ra trên mỗi tick được xác định bằng cách sử dụng hàm register_tick_function(). Cần lưu ý rằng có thể có nhiều hơn một sự kiện xảy ra cho mối tick.

Ví dụ 1: Sử dụng tick.

<?php

declare(ticks=1);

// A function called on each tick event
function tick_handler()
{
    echo 
"tick_handler() called\n";
}


register_tick_function('tick_handler');

$a 1;

if (
$a 0) {
    
$a += 2;
    print(
$a);
}


?>

Ví dụ 2: Sử dụng nhiều tick.

<?php

function tick_handler()
{
  echo 
"tick_handler() called\n";
}


$a 1;
tick_handler();

if (
$a 0) {
    
$a += 2;
    
tick_handler();
    print(
$a);
    
tick_handler();
}

tick_handler();

?>

Encoding ¶

Mỗi encoding của kịch bản có thể được xác định bằng cách sử dụng chỉ thị encoding.

Ví dụ 3: Khai báo một encoding cho kịch bản.

<?php
declare(encoding='ISO-8859-1');
// code here
?>

Cảnh báo

Khi biên dịch với namespace thì chỉ có cú pháp hợp lệ của declare là declare(encoding='...'); , trong đó ... là giá trị encoding. declare(encoding='...') {} sẽ bị lỗi parse khi biên dịch trong namespace.

Giá trị khai báo encoding bị bỏ qua đối với phiên bản PHP 5.3 trừ khi mã lệnh php được biên dich với --enable-zend-multibyte.

Lưu ý rằng PHP không tường minh rằng liệu --enable-zend-multibyte có được sử dụng để biên dịch PHP hay không bằng phpinfo().

return

Câu lệnh return dùng để trả về giá trị từ hàm hay phương thức. PHP cho phép hàm có thể trả về bất kỳ giá trị gì, bảo gồm cả đối tượng cũng như mảng. Khi đó tất cả các câu lệnh phía sau return sẽ đều bị bỏ qua và hàm sẽ kết thúc việc thực thi.

Lưu ý:

Nếu không có câu lệnh return thì hàm sẽ trả về giá trị NULL.

Sử dụng return

Ví dụ 1: Cách sử dụng return.

<?php
function square($num)
{
    return 
$num $num;
}
echo 
square(4);   // in ra: 16
?>

Một hàm không thể trả về nhiều hơn một giá trị, nhưng ta có thể thay thế bằng việc cho nó trả về một mảng.

Ví dụ 2: Trả về một mảng.

<?php
function small_numbers()
{
    return array (
012);
}
list (
$zero$one$two) = small_numbers();
?>

Để trả về một tham chiếu từ hàm thì ta sử dụng toán tử tham chiếu & trong cả phần định nghĩa hàm và khi gọi hàm.

Ví dụ 3: Trả về tham chiếu từ hàm.

<?php
function &returns_reference()
{
    return 
$someref;
}


$newref =& returns_reference();
?>

Các khai báo kiểu trả về

PHP 7 bổ sung tính năng hỗ trợ khai báo kiểu trả về. Tương tự như khai báo kiểu đối số, khai báo kiểu trả về sẽ xác định kiểu của giá trị sẽ trả về từ hàm. Các kiểu giống nhau sẽ sẽ cho phép khai báo kiểu trả về trong phần đối số của khai báo.

Kiểu strict của được phép áp dụng khai báo kiểu trả về. Theo cách thông thường thì giá trị trả về sẽ được ép sang kiểu mong muốn nếu nó không cùng kiểu. Còn trong trường hợp định kiểu mạnh thì giá trị trả về phải có kiểu đúng, nếu không lỗi TypeError sẽ được ném.

Lưu ý:

Khi ghi đè một phương thức của lớp cha thì phương thức của lớp con phải tương thích với khai báo kiểu trả về của lớp cha. Nếu ở phương thức của lớp cha không khai báo kiểu trả về thì phương thức của lớp con cũng có thể làm như vậy.

Ví dụ 4: Khai báo kiểu trả về cơ bản

<?php
function sum($a$b): float {
    return 
$a $b;
}


// Lưu ý rằng một số thực sẽ được trả về.
var_dump(sum(12));
?>

Đoạn mã trên sẽ in ra:

float(3)

Ví dụ 5: Chế độ strick

<?php
declare(strict_types=1);

function 
sum($a$b): int {
    return 
$a $b;
}


var_dump(sum(12));
var_dump(sum(12.5));
?>

Ví dụ trên sẽ in ra:

int(3)

Fatal error: Uncaught TypeError: Return value of sum() must be of the type integer, float returned in - on line 5 in -:5
Stack trace:
#0 -(9): sum(1, 2.5)
#1 {main}
  thrown in - on line 5

Ví dụ 6: Trả về một đối tượng.

<?php
class {}

function 
getC(): {
    return new 
C;
}


var_dump(getC());
?>

Ví dụ trên sẽ in ra:

object(C)#1 (0) {
}

Thừa kế (Inheritance)

Thừa kế là một nguyên tắc lập trình tuyệt vời, và PHP sử dụng nguyên tắc này trong mô hình đối tượng của nó. Nguyên tắc này sẽ ảnh hưởng tới cách mà nhiều lớp và đối tượng liên quan đến nhau.

Ví dụ, khi bạn mở rộng (thừa kế) một lớp thì lớp con này thừa kế tất cả các thành phần public và protected của lớp cha. Ngoại trừ những phương thức bị ghi đè thì lớp con sẽ giữ lại nguyên gốc những chức năng của các phương thức của lớp cha.

Điều này là hữu dụng để định nghĩa và trừu tượng hóa chức năng, và cho phép bổ sung các chức năng cho đối tượng đó mà không cần phải thực hiện lại tất cả các chức năng đã được chia sẻ.

Lưu ý:

Ngoại việc sử dụng autoloading, thì các lớp phải được định nghĩa trước khi chúng được sử dụng. Nếu một lớp mở rộng từ lớp khác thì lớp cha phải được khai báo trước khi định nghĩa lớp con. Quy tắc này áp dụng cho các lớp thừa kế lớp và interface khác.

Ví dụ 1: Ví dụ về thừa kế.

<?php

class Foo
{
    public function 
printItem($string)
    {
        echo 
'Foo: ' $string PHP_EOL;
    }
    
    public function 
printPHP()
    {
        echo 
'PHP is great.' PHP_EOL;
    }
}

class 
Bar extends Foo
{
    public function 
printItem($string)
    {
        echo 
'Bar: ' $string PHP_EOL;
    }
}


$foo = new Foo();
$bar = new Bar();
$foo->printItem('baz'); // Output: 'Foo: baz'
$foo->printPHP();       // Output: 'PHP is great' 
$bar->printItem('baz'); // Output: 'Bar: baz'
$bar->printPHP();       // Output: 'PHP is great'

?>

include

Phiên bản: PHP 4, PHP 5, PHP 7.

Câu lệnh include dùng để đưa vào tập tin hiện tại một tập tin cụ thể.

Phần trình bày dưới đây cũng áp dụng cho requre.

Các tập tin được đưa vào dựa trên đường dẫn tập tin đã cho, hoặc nếu không cho đường dẫn tập tin thì tập tin sẽ được xác định thông qua include_path. Nếu tập tin không tìm thấy trong include_path, thì include sẽ kiểm tra trong chính thư mục được chỉ định và thư mục hiện tại trước khi thất bại. Cấu trúc include sẽ đưa ra một cảnh báo nếu nó không thể tìm thấy tập tin; hành vi này khác với require (đưa ra một fatal error).

Nếu đường dẫn được định nghĩa - có thể là tuyệt đối hoặc tương đối tới thứ mục hiện tại (bắt đầu bằng . hoặc ..) - thì include_path sẽ được bỏ qua. Ví dụ, nếu một tập tin bắt đầu với ../, thì bộ parser sẽ tìm tập tin yêu cầu trong thư mục cha.

Khi một tập tin được đưa vào thì nó sẽ thừa kế các biến nằm trên dòng mà tập tin đó được đưa vào. Bất kỳ một biến nào có sẵn trong tập tin gọi thì đều sử dụng được ở tập tin được gọi. Tuy nhiên, tất cả các hàm và lớp định nghĩa trong tập tin được gọi sẽ đều có phạm vi là global.

Ví dụ 1: Cách dùng include cơ bản.

//vars.php
<?php

$color 
'green';
$fruit 'apple';

?>


//test.php
<?php

echo "A $color $fruit"// A

include 'vars.php';

echo 
"A $color $fruit"// A green apple

?>

Nếu việc gọi tập tin xảy ra bên trong một hàm thì tất cả mã lệnh trong tập tin được gọi sẽ cư xử như nó đã được định nghĩa trong hàm đó. Do đó, nó sẽ theo sau phạm vi biến của hàm đó. Một ngoại lệ cho quy tắc này là hằng số ma thuật (magic constant) sẽ được lượng giá bởi bộ parser trước khi đưa vào tập tin.

Ví dụ 2: Đưa tập tin vào hàm.

<?php

function foo()
{
    global 
$color;

    include 
'vars.php';

    echo 
"A $color $fruit";
}


/* vars.php nằm trong hàm foo() *
* nên $fruit không sử dụng được bên ngoài hàm này. *
* $color thì được vì nó được khai báo là global. */


foo();                    // A green apple
echo "A $color $fruit";   // A green

?>

Khi đưa vào tập tin thì việc phân tích sẽ ra khỏi chế độ PHP và vào chế độ HTML tại vị trí bắt đầu của tập tin gốc, và lại tiếp tục lại ở cuối. Lý do của vấn đề này là vì bất kỳ đoạn mã nào bên trong tập tin đích đều phải được thực thi giống như đoạn mã PHP phải được đặt trong thẻ mở và đóng PHP.

Nếu "URL include wrappers" được phép trong PHP thì ta có thể xác định tập tin được đưa vào bằng cách sử dụng URL (thông qua HTTP hoặc bộ wrapper khác) thay cho đường dẫn cục bộ. Nếu server đích thông dịch tập tin đích thành mã PHP thì các biến có thể truyền tới tập tin được đưa vào bằng cách sử dụng một URL để yêu cầu chuỗi sử dụng với HTTP GET. Điều này không hẳn đúng cho những trường hợp tương tự khi đưa vào tập tin và nó thừa kế phạm vi biến của tập tin cha, nhưng kịch bản thực sự lại đang chạy trên remote server và kết quả lại được đưa vào kịch bản cục bộ.

Ví dụ 3: include qua HTTP

<?php

/* Ví dụ này giả sử rằng www.example.com được cấu hình để phân tích các tập tin .php
* mà không phải là các tập tin .txt. Do đó, sự thực thi ở đây có nghĩa rằng các biến
* $foo và $bar sử dụng được trong tập tin được đưa vào. */

// Không làm việc, tập tin .txt không được xử lý bởi www.example.com thành PHP

include 'http://www.example.com/file.txt?foo=1&bar=2';

// Không làm việc, tìm kiếm tập tin có tên 'file.php?foo=1&bar=2' trên máy cục bộ.
include 'file.php?foo=1&bar=2';

// Làm việc.
include 'http://www.example.com/file.php?foo=1&bar=2';

$foo 1;
$bar 2;
include 
'file.txt';  // Works.
include 'file.php';  // Works.

?>

Cảnh báo bảo mật

Tập tin remote có thể được xử lý tại server remote (phụ thuộc vào đuôi mở rộng của tập tin và thực tế server remote chạy PHP hay không) nhưng nó vẫn phải tạo ra một kịch bản PHP hợp lệ vì nó không được xử lý tài server cục bộ. Nếu tập tin từ server remote phải xử lý những điều này và chỉ output, thì hàm readfile() cần được sử dụng. Nếu không thì ta cần đặc biệt quan tâm đến việc đảm bảo kịch bản remote sẽ tạo ra một đoạn mã hợp lệ và có giá trị.

Xử lý giá tri trả về: include trả về FALSE nếu thất bại và đưa ra một cảnh báo. Nếu đưa vào thành công, trừ khi khi đè tập tin đã được đưa vào trước đó, thì nó sẽ trả về 1. Ta có thể thực hiện câu lệnh return trong tập tin đã đưa vào để ngắt xử lý trong tập tin đó và trả về kịch bản trong tập tin đó. Bạn có thể đưa một giá trị vào lời gọi giống như một hàm thông thường. Tuy nhiên, ta không thể đưa vào những tập tin remote trừ khi output của nó có chứa các thẻ PHP bắt đầu và kết thúc hợp lệ. Ta cũng có thể khai báo những biến cần thiết trong những thẻ này và chúng sẽ được sử dụng vào những vị trí tương ứng với tập tin đã được đưa vào.

include cho phép bỏ đi cặp ngoặc tròn bao ngoài đối số của nó, do vậy bạn hãy cẩn thận khi so sánh giá trị trả về của nó.

Ví dụ 4: So sanh giá trị trả về của include

<?php
// sẽ không làm việc, do bạn viết include(('vars.php') == TRUE)
if (include('vars.php') == TRUE) {
    echo 
'OK';
}


// làm việc
if ((include 'vars.php') == TRUE) {
    echo 
'OK';
}

?>

Ví dụ 5: include và câu lệnh return.

//return.php
<?php

$var 
'PHP';

return 
$var;

?>


//noreturn.php
<?php

$var 
'PHP';

?>


//testreturns.php
<?php

$foo 
= include 'return.php';

echo 
$foo// in ra 'PHP'

$bar = include 'noreturn.php';

echo 
$bar// in ra 1

?>

$bar chứa gá trị 1 vì đưa vào thành công. Bạn hãy lưu ý về sự khác nhau giữa các ví dụ trong đoạn mã trên. Đâu tiên việc sử dụng return trong tập tin đã đưa vào trong khi tập tin khác lại không hoạt động. Nếu tập tin không thể được đưa vào thì sẽ trả về FALSE đưa ra cảnh báo E_WARNING.

Nếu có các hàm được định nghĩa trong tập tin đưa vào thì chúng có thể được sử dụng trong tập tin chính mà không phụ thuộc vào việc chúng nằm trước hay sau. Nếu tập tin được đưa vào hai lần thi PHP 5 sẽ đưa ra lỗi fatal dó các hàm đã được định nghĩa rồi lại định nghĩa lại, còn PHP 4 vẫn chấp nhận những hàm được định nghĩa sau câu lệnh return. Lưu ý rằng nên sử dụng include_once để kiểm tra nếu như tập tin đã được đưa vào trước đó và trả về điều kiện trong tập tin đưa vào.

Một cách khác để đưa một tập tin PHP vào một biến là bắt phần output bằng cách sử dụng Các hàm điều khiển output với include. Ví dụ 6 dưới đây mô tả điều này.

Ví dụ 6: Sử dụng bộ đệm output để đưa tâp tin PHP vào một chuỗi.

<?php
$string 
get_include_contents('somefile.php');

function 
get_include_contents($filename) {
    if (
is_file($filename)) {
        
ob_start();
        include 
$filename;
        return 
ob_get_clean();
    }
    return 
false;
}


?>

Để tự động đưa các tập tin vào trong các kịch bản thì ta có thể xem các tùy chọn cấu hình  auto_prepend_file và auto_append_file trong tập tin php.ini.

Lưu ý: Do là một cấu trúc ngôn ngữ mà không phải là một hàm, cho nên include không thể được gọi bằng cách sử dụng các biến hàm.

Xem thêm:

include_once

Phiên bản PHP: PHP 4, PHP 5, PHP 7

include_once dùng để đưa vào và lượng giá tập tin cụ thể trong quá trình thực thi kịch bản. Điều này tương tự như include, chỉ khác là nếu đoạn mã từ tập tin đã có trước đó rồi thì nó sẽ không được đưa vào lại nữa, và include_once sẽ trả về TRUE. Như vậy theo đúng như tên của nó, include_once sẽ chỉ đưa tập tin vào một lần duy nhất.

include_once còn có thể được sử dụng trong trường hợp tập tin tương tự có thể được đưa vào và lượng giá hơn một lần trong khi thực thi một kịch bản cụ thể nào đó, do đó trong trường hợp này thì nó có thể giúp tránh được những vấn đề như là định nghĩa lại hàm, gán lại giá trị cho biến, ...

Lưu ý:

Với PHP 4, chức năng _once khác với hệ điều hành phân biệt hoa/thường khác (Windows chẳng hạn). Ví dụ,

<?php
include_once "a.php"// sẽ đưa vào a.php
include_once "A.php"// cũng sẽ đưa vào a.php (PHP 4)
?>

Hành vi trên đã thay đổi trong  PHP 5, theo đó với Windows thì đường dẫn được chuẩn hóa đầu tiên, tức là ví dụ C:\PROGRA~1\A.php sẽ tương tự C:\Program Files\a.php và tập tin chỉ được đưa vào môt lần.

print

Cú pháp

int print ( string $arg )

print thực tế không phải là một hàm thực thụ, nó là một cấu trúc ngôn ngữ, vậy nên ta không cần sử dụng cặp ngoặc tròn ().

Tham số

$arg

Dữ liệu đầu vào.

Giá trị trả về

Luôn luôn trả về 1.

Ví dụ

<?php
print("Hello World");

print 
"print() cũng làm việc mà không cần cặp ngoặc ().";

print 
"Nội dung
này co thể được đặt trên nhiều dòng
à không bị sai cú pháp.
Nhưng output chuỗi này vẫn chỉ nằm trên một dòng"
;

print 
"Chuỗi này\nsẽ được in ra\ntrên nhiều dòng\nvì sử dụng \\n.";

print 
"escaping characters là dấu \\.";

// Có thể dùng biến trong chuỗi của hàm print
$foo "foobar";
$bar "barbaz";

print 
"foo is $foo"//in ra: foo is foobar

// Ta cũng có quyền sử dụng mảng

$bar = array("value" => "foo");

print 
"this is {$bar['value']} !"//in ra: this is foo !

// Dùng cặp nháy đơn sẽ in ra tên biến mà không phải giá trị của biến

print 'foo is $foo'//in ra: foo is $foo

// Nếu không sử dụng bất kỳ ký tự nào thì thì sẽ in ra giá trị của biến

print $foo;  //in ra: foobar

print <<<END
Nếu muốn in dữ liệu trên nhiều dòng như mong muốn

thì sử dụng cú pháp này!
END;
?>

Lưu ý

+ Do là một cấu trúc ngôn ngữ chứ không phải là một hàm, nên ta không thể thực hiện lời gọi tới print.

+ Thực tế thì việc sử dụng cặp ngoặc tròn () cho print có thể gây ra nhầm lẫn rằng đó là hàm, vì vậy ta không nên sử dụng.

Ví dụ, thay vì ta viết:
<?php
    
if (print("foo") && print("bar")) {
        
// "foo" và "bar" được in ra
    
}
?>

Thì ta nên viết như sau:

<?php
    
if ((print "foo") && (print "bar")) {
        
// "foo" và "bar" được in ra
    
}
?> 

Bài tập 1

Mục tiêu

Sau bài thực hành này, sinh viên sẽ học được các kỹ năng sau:

1. Làm quen với NetBeans IDE

2. Làm quen với viết mã PHP

3. Biết cách kiểm thử và gỡ lỗi ứng dụng PHP

4. Truyền và lấy dữ liệu từ HTTP Request

Bài 1

Tạo project PHP với NetBeans (Sinh viên có thể tham khảo case study 1 để làm)

Sử dụng phần mềm NetBeans để tạo một project mới với các thông số như sau:

- Tên project: Lab01_Project

- Source folder: C:\xampp\htdocs\Lab1_Project

- PHP Version: 5.3

- Default Encoding: UTF-8

- Chạy trên localhost

- Project URL: http://localhost/Lab1_Project/

Bài 2

a. Bật file index.php của Lab1_Project

Viết chú thích(comment) với nội dung thông tin như sau:

Tên sinh viên: <Tên SV>

Lớp: <Lớp>

Môn học: Lập trình web với PHP

Viết mã PHP để hiển thị chuỗi “Hello World 1” bằng cách viết trực tiếp HTML (đặt trong tag <p>)

Viết mã PHP để hiển thị chuỗi “Hello World 2” bằng cách viết nhúng mã PHP vào HTML (sử dụng một biến PHP và lệnh echo, đặt trong tag <p>)

b. Chạy thử project với chế độ gỡ lỗi (debug) và chụp ảnh màn hình kết quả thành file lab1_Bai2.jpg

(Các thao tác trên thực hiện trong phần body của file index.php)

Bài 3

a. Viết một form HTML trong file index.php như sau:

<form action="lab1.php" method="post">
    <h3>Mã sinh viên: </h3><input type="text" name="masv" />
    <h3>Họ tên: </h3><input type="text" name="hoten" />
    <h3>Địa chỉ: </h3><input type="text" name="diachi" />
    
    <input type="submit" name="ok" value="OK" />
</form>

Tương tự thêm 3 trường input text cho form trên với tên và name lần lượt như sau:

Tên: Giới tính, thuộc tính name="GioiTinh"

Tên: Quốc gia, thuộc tính name="QuocGia"

Tên: Tuổi, thuộc tính name="Tuoi"

b. Tạo một file PHP mới tên là lab1.php nằm cùng thư mục với file index.php. Trong file này viết mã PHP để hiển thị ra màn hình thông tin tên và địa chỉ thu được từ phương thức POST ở bài 3a

Chú ý: để trang web hiển thị được tiếng Việt thì phải thêm thẻ sau vào đầu trang:

<meta charset="utf-8" />

c. Chạy project, điền thông tin họ tên và tuổi vào form HTML rồi nhấn nút OK.

Bài tập 2

Mục tiêu

Sau bài thực hành này, sinh viên sẽ học được các kỹ năng sau:

1. Làm quen với cơ sở dữ liệu trong môi trường MySQL

2. Làm quen với phpMyAdmin

3. Biết cách sử dụng PHP với MySQL

Bài 1 – Tạo cơ sở dữ liệu MySQL

Sử dụng phpMyAdmin tạo một cơ sở dữ liệu mới tên là QLSV.

Lưu ý: phải đặt collation là utf8_general_ci để mysql lưu được dữ liệu tiếng Việt

Sau đó tạo bảng sau bằng cách sử dụng giao diện của phpMyAdmin:

Trường Loại dữ liệu Độ dài
SinhVien (Sinh viên)
MaSV (Mã sinh viên) int  
TenSV (Tên sinh viên) varchar 30
Diachi (Địa chỉ) varchar 50
Tuoi (Tuổi) varchar 3
GioiTinh (Giới tính) tinyint 1
QuocGia (Quốc gia) varchar 3

Bài 2 – Hướng dẫn nhập dữ liệu

Bật file lab1.php của Lab1_Project.

Điền đoạn mã sau để kết nối tới cơ sở dữ liệu QLSV:

$dns = "mysql:host=localhost;dbname=QLSV";

$db = new PDO($dns, "root", "");

Điền đoạn mã sau để lấy dữ liệu truyền từ form HTML của file index.php bằng phương thức POST và lưu vào các biến PHP tương ứng:

//Lấy giá trị truyền từ phương thức POST lưu vào các biến tương ứng
$MaSV = $_POST['MaSV'];

$HoTen = $_POST['HoTen'];

$DiaChi = $_POST['DiaChi'];

$GioiTinh = $_POST['GioiTinh'];

$QuocGia = $_POST['QuocGia'];

$Tuoi = $_POST['Tuoi'];

Tiếp theo là điền đoạn mã sau để điền dữ liệu vào cơ sở dữ liệu:

//Thực thi câu truy vấn điền dữ liệu
$sql = "INSERT INTO SinhVien VALUES ('$MaSV', n'HoTen', n'$DiaChi', '$Tuoi', '$GioiTinh', '$QuocGia')";

$result = $db->exec($sql);

Cuối cùng, chạy project và điền thông tin về một sinh viên mới như sau vào form HTML rồi nhấn nút OK:

o Họ tên: Nguyễn Văn A

o Mã SV: 1

o Địa chỉ: Hà Nội

o Tuổi: 21

o Giới tính: 1

o Quốc gia: VN

Bài 3 – Thiết kế truy vấn

Sinh viên áp dụng tương tự bài 2 để thực hiện:

a. Điền thêm thông tin về hai sinh viên khác như sau:

o Họ tên: Lê Đức Thọ
o Mã SV: 2
o Địa chỉ: 63 Trường Chinh
o Tuổi: 19
o Giới tính: 1
o Quốc gia: VN

o Họ tên: Lê Quỳnh Như
o Mã SV: 3
o Địa chỉ: 103 Trường Chinh
o Tuổi: 21
o Giới tính: 0
o Quốc gia: VN

b. Thay đổi thông tin về sinh viên mã số 2 thành:

o Họ tên: Lê Thị Hiền
o Mã SV: 2
o Địa chỉ: 63 Trường Chinh, Hà Nội
o Tuổi: 20
o Giới tính: 0
o Quốc gia: US

c. Xóa dữ liệu về sinh viên có mã sv là 1 vừa nhập ở bài 2.

Bài tập 3

Mục tiêu

Buổi thực hành số 3, sinh viên sẽ học được những kỹ năng:

1.  Viết câu lệnh điều khiển trong PHP

2.  Khởi tạo và sử dụng các hàm trong PHP

Bài 1 – Viết câu lệnh điều khiển

Để biểu diễn thông tin của khách hàng có các biến PHP như sau:

- $GioiTinh (Giới tính): (bool: Nam là 1, Nữ là 0)

- $SoLuong (Số lượng hàng mua): (int)

- $ChietKhau (Mức chiết khấu): (float)

Viết cấu trúc lựa chọn với các biến trên để biểu diễn luật chiết khấu sau:

-  Nếu  khách  hàng  có  giới  tính  Nam,  số  lượng  hàng  mua  <  5  thì  có  mức  chiết  khấu  là  3%,  số hàng >= 5 và <= 10 thì chiết khấu 5%, số hàng > 10 thì chiết khấu 10%.

-  Nếu khách hàng có giới tính Nữ, số hàng < 7 thì chiết khấu 3%, số hàng >= 7 và <= 15 thì chiết khấu 7%, số hàng > 15 thì chiết khấu 10%.

Bài 2 – Xây dựng hàm

a.  Xây dựng hàm ConvertSign1 để biến số âm thành số dương và ngược lại (tham số theo kiểu tham trị và có giá trị mặc định là NULL).

Xây  dựng  hàm  ConvertSign2  để  biến  số  âm  thành  số  dương  và  ngược  lại  (tham  số  theo  kiểu chiếu và có giá trị mặc định là NULL).

Viết mã PHP để truyền biến toàn cục $a có giá trị khởi tạo là 2 vào hai hàm trên, sau khi thực hiện thì hiển thị giá trị của biến $a ra màn hình để so sánh sự khác biệt giữa hai hàm đó.

b.  Cho hai biến toàn cục $c = 2 và $d = 3. Xây dựng hàm Sumcd để tính tổng $c + $d, biết rằng hàm này không có tham số mà bên trong hàm truy cập tới hai biến toàn cục $c, $d theo 2 cách như sau:

o Truy cập tới $c bằng cách dùng từ khóa global

o Truy cập tới $d bằng cách dùng mảng $GLOBALS

Bài 3 – Xây dựng hàm với số lượng tham số biến đổi

a.  Viết  lại  bài  2a  sử  dụng  phương  pháp  danh  sách  tham  số  có  độ  dài  biến  đổi  (các  hàm func_get_arg thay vì dùng cụ thể đối số truyền vào).

b.  Lưu bài 2a thành file thư viện  Lib.php  và gọi hàm Sumcd từ thư viện này để tính tổng hai biến toàn cục $m = -5 và $n = 7.

Bài tập 4

Mục tiêu

Bài tập này sinh viên sẽ học được những kỹ năng về lập trình hướng đối tượng trong PHP.

Bài tập

Tạo file php tên là lab3.php trong đó viết mã PHP để thực hiện các công việc sau:

1.  Xây dựng lớp Person với các thuộc tính và phương thức như sau:

o Thuộc tính public là Name (tên)

o Thuộc tính private là Gender (giới tính)

o Thuộc tính tĩnh là Country (quốc gia)

o Thuộc tính protected là Address (địa chỉ)

o Hai hằng là MALE = ‘1’, FEMALE = ‘0’

o  Phương  thức  khởi  tạo  có  1  tham  số  kiểu  tham  trị:  gán  giá  trị  của  tham  số  cho  thuộc  tính Name.

o Phương thức public setGender có 1 tham số kiểu tham trị: nếu giá trị tham số bằng với giá trị của một trong các hằng trên thì gán giá trị đó cho thuộc tính Gender.

o Phương thức public showAll không có tham số: đưa ra tất cả thông tin có thể về đối tượng lớp Person (các thuộc tính).

b.  Xây dựng lớp Employee kế thừa lớp Person với các thuộc tính và phương thức thêm như sau:

Name = …, Gender = …, Country = …, Address = …, Age = …

header()

Phiên bản áp dụng: PHP 4, PHP 5, PHP 7.

Cú pháp

void header ( string $string [, bool $replace = true [, int $http_response_code ]] )

Mục đích: header() dùng để gửi một header HTTP ở dạng thô.

Cần nhớ rằng header() phải được gọi trước khi gửi bất kỳ điều gì tới output như các thẻ HTML, dòng trắng trong một file, hoặc từ PHP. Đây là một lỗi rất phổ biến khi đọc code với include hay require, các hàm hoặc hàm truy cập file, và có những khoảng trống hay các dòng trắng ở đầu ra trước khi header() được gọi. Vấn đề tương tự cũng được bắt gặp khi sử dụng tập tin PHP/HTML.

Ví dụ:

<html>
<?php
/* Ở đây sẽ phát sinh lỗi vì xuất hiện thẻ <html>
 * trước lời gọi header() */

header('Location: http://www.example.com/');
exit;

?>

Các tham số

string

Chuỗi header.

Có hai lời gọi header đặc biệt. Trường hợp thứ nhất là chuỗi chứa "HTTP/" (không nhiều), trường hợp này sẽ được dùng để cấu hình ngoài mã trạng thái HTTP để gửi. Ví dụ như nếu bạn cấu hình Apache để sử dụng kịch bản PHP để xử lý các yêu cầu đối với việc thiếu các tập tin (dùng chỉ thị ErrorDocument) thì bạn có thể muốn đảm bảo rằng kịch bản của bạn tạo ra mã trạng thái thích hợp. Ví dụ:

<?php
header
("HTTP/1.0 404 Not Found");
?>

Trường hợp đặc biệt thứ hai là chuỗi có chứa "Location:". Chỉ thị này không những gửi header trở lại trình duyệt mà còn trả về cho trình duyệt mã trạng thái REDIRECT (302) trừ khi mã trạng thái 201 hoặc 3xx đã được thiết lập từ trước. Ví dụ:

<?php
header
("Location: http://www.example.com/"); /* Gửi trực tiếp tới trình duyệt */

/* Cần đảm bảo rằng đoạn mã bên dưới không được thực thi khi ta điều hướng. */

exit;
?>

replace

Tham số tùy chọn này chỉ ra header nên thay thế header tương tự trước đó, hoặc thêm header thứ hai cùng loại. Mặt định thì nó sẽ thay thế, nhưng nếu truyền giá tri FALSE vào đối số này thì ta có thể thiết lập nhiều header khác cùng loại. Ví dụ:

<?php
header
('WWW-Authenticate: Negotiate');
header('WWW-Authenticate: NTLM'false);
?>

http_response_code

Tham số này tạo mã phản hồi HTTP với giá trị xác định. Lưu ý rằng tham số này chỉ có tác dụng nếu tham số string không trống.

Giá trị trả về

header() không có giá trị trả về.

Changelog

Phiên bản Mô tả
5.1.2 Phiên bản hiện tại có thể ngăn cản không có phép cùng lúc gửi nhiều header nhằm mục đích bảo vệ chống lại những cuộc tấn công injection đối với header.

Ví dụ

Ví dụ 1: Tải xuống hộp thoại

Nếu bạn muốn nhắc người dùng rằng cần lưu dữ liệu bạn đang gửi, ví dụ như tập tin PDF chẳng hạn, thì bạn sử dụng header Content-Disposition để cung cấp tên file khuyến nghị và yêu cầu trình duyệt hiển thị hộp thoại lưu trữ.

<?php
// Output một file PDF
header('Content-Type: application/pdf');

// Gọi file downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');

// PDF nguồn là original.pdf
readfile('original.pdf');
?>

Ví dụ 2: Các chỉ thị bộ nhớ đệm

Các kịch bản PHP thường tạo nội dung động nhưng không được đệm ở trình duyệt client hoặc bất kỳ bộ nhớ đệm proxy nào giữa trình duyệt client và server. Nhiều proxy and client có thể bị ép buộc cấm sử dụng bộ nhớ đệm bằng cách thức như sau:

<?php
header
("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Ngày hết hạn
?>

Lưu ý là bạn có thể nhận thấy rằng các trang của bạn không được đệm mặc dù bạn không hề sử dụng các header trên. Có một số tùy chọn mà người dùng có thể cho phép thiết lập đối với trình duyệt để có thể mặc định thực hiện việc đệm trang. Bằng cách gửi các header ở trên thì ta cần ghi đè các cài đặt nhằm mục đích trang của ta được đệm trên bộ nhớ cache của trình duyệt.

Ngoài ra thì việc sử dụng hàm session_cache_limiter() và việc thiết lập cấu hình session.cache_limiter có thể được sử dụng để tự động tạo các header đệm chuẩn khi ta sử dụng các session.

Các lưu ý khi sử dụng header()

- Các header sẽ chỉ có thể được truy cập và sử dụng khi một SAPI hỗ trợ chúng đang được sử dụng.

- Ta có thể sử dụng bộ đệm đầu ra để thực hiện vấn đề này bằng chi phí của tất cả các đầu ra của bạn tới trình duyệt được đệm trong server cho tới khi bạn gửi nó. Ta có thể thực hiện điều này bằng cách gọi các hàm ob_start() và ob_end_flush() trong kịch bản, hoặc thiết lập chỉ thị cấu hình output_buffering trong tập tin php.ini hoặc các tập tin cấu hình server.

- Dòng header trạng thái HTTP sẽ luôn luôn được gửi tới client đầu tiên bất kể là ta có gọi hàm actualheader() đầu tiên hay không. Trạng thái có thể được ghi đè bằng cách gọi header() với một dòng trạng thái mới bất kỳ lúc nào trừ khi các header HTTP đã được gửi rồi.

- Nếu chế độ safe mode được kích hoạt thì uid của kịch bản sẽ được thêm vào phần realm của header WWW-Authenticate nếu bạn thiết lập header này (sử dụng cho HTTP Authentication).

- Hầu hết khách hàng hiện nay đều chập nhận các URI tương đối là đối số của Location, nhưng có một số khách có thể yêu cầu URI tuyệt đối bao gồm scheme, hostname và đường dẫn tuyệt đối. Do vậy, ta có thể sử dụng $_SERVER['HTTP_HOST']$_SERVER['PHP_SELF'] và dirname() để tạo URI tuyệt đối từ như sau:

<?php
/* Chuyển hướng đến một trang khác trong thư mục hiện tại đã được yêu cầu */
$host  $_SERVER['HTTP_HOST'];
$uri   rtrim(dirname($_SERVER['PHP_SELF']), '/\\');
$extra 'mypage.php';
header("Location: http://$host$uri/$extra");
exit;

?>

- Session ID không được truyền đi khi dùng header Location ngay cả khi session.use_trans_sid được kích hoạt, mà nó phải được truyền bằng cách sử dụng hằng SID.

Late Static Bindings

Từ phiên bản PHP 5.3.0, PHP có một đặc điểm gọi là "Late static bindings" được dùng để tham chiếu tới lớp được gọi trong trường hợp thừa kế tĩnh.

Cụ thể hơn, late static bindings làm việc bằng cách lưu trữ tên lớp trong "lời gọi không chuyển tiếp" cuối. Trong trường hợp gọi phương thức tĩnh thì đó là tên tường minh của chuỗi (thường nó nằm bên trái của toán tử ::); trong trường hợp gọi phương thức không tĩnh thì đó là lớp của đối tượng. Một "lời gọi chuyển tiếp" là một lời gọi tĩnh như self::parent::static::, hoặc lời gọi tới phương thức forward_static_call(). Phương thức get_called_class() có thể được sử dụng để truy xuất một chuỗi với tên lớp được gọi và sử dụng static::.

Gọi là "late static bindings" là bởi vì xuất phát từ thực tế rằng static:: sẽ không được giải quyết bằng cách sử dụng lớp mà trong đó phương thức được định nghĩa thay thế cho việc tính toán sử dụng thông tin runtime. Nó cũng được gọi là "static binding" bởi vì nó có thể được sử dụng (không giới hạn) cho việc gọi phương thức tĩnh.

Giới hạn của self:: ¶

static tham chiếu tới lớp hiện tại như self:: hay __CLASS__ được giải quyết bằng cách sử dụng lớp chứa phương thức tương ứng được định nghĩa:

Ví dụ 1: Sử dụng self::

<?php
class {
    public static function 
who() {
        echo 
__CLASS__;
    }
    public static function 
test() {
        
self::who();
    }
}

class 
extends {
    public static function 
who() {
        echo 
__CLASS__;
    }
}


B::test();
?>

Ví dụ trên sẽ in ra:

A

Sử dụng Late Static Binding

Late static bindings sẽ cố gắng khắc phục giới hạn bằng cách sử dụng một từ khóa để tham chiếu tới lớp khởi tạo được gọi khi runtime. Về cơ bản thì từ khóa  này cho phép bạn tham chiếu tới lơp B từ phương thức test() ở ví dụ trên bằng cách không sử dụng từ khóa new mà sử dụng static.

Ví dụ 2: Sử dụng static::

<?php
class {
    public static function 
who() {
        echo 
__CLASS__;
    }
    public static function 
test() {
        static::
who(); // Here comes Late Static Bindings
    
}
}

class 
extends {
    public static function 
who() {
        echo 
__CLASS__;
    }
}


B::test();
?>

Ví dụ trên sẽ in ra:

B

Lưu ý:

Trong trường hợp non-static thì lớp được gọi sẽ là lớp tương ứng với đối tượng thể hiện. Vì $this-> sẽ cố gắng gọi các phương thức private nên việc sử dụng static:: có thể cho những kết quả khác nhau. Một điều nữa là static:: chỉ có thể tham chiếu tới những thuộc tính tĩnh.

Ví dụ 3: Sử dụng static:: trong trường hợp non-static

<?php
class {
    private function 
foo() {
        echo 
"success!\n";
    }
    public function 
test() {
        
$this->foo();
        static::
foo();
    }
}

class 
extends {
   
/* foo() will be copied to B, hence its scope will still be A and
    * the call be successful */

}

class 
extends {
    private function 
foo() {
        
/* original method is replaced; the scope of the new one is C */
    
}
}


$b = new B();
$b->test();
$c = new C();
$c->test();   //fails
?>

Ví dụ trên sẽ in ra:

success!
success!
success!


Fatal error:  Call to private method C::foo() from context 'A' in /tmp/test.php on line 9

Lưu ý:

Phạm vi giải quyết của Late static bindings sẽ dừng lại sau khi giải quyết hoàn chỉnh một lời gọi tĩnh mà không có fallback. Mặt khác, lời gọi tĩnh sử dụng từ khóa như parent:: hoặc self:: sẽ chuyển tiếp tới thông tin gọi.

Ví dụ 4: Lời gọi chuyển tiếp và không chuyển tiếp.

<?php
class {
    public static function 
foo() {
        static::
who();
    }

    public static function 
who() {
        echo 
__CLASS__."\n";
    }
}

class 
extends {
    public static function 
test() {
        
A::foo();
        
parent::foo();
        
self::foo();
    }

    public static function 
who() {
        echo 
__CLASS__."\n";
    }
}
class 
extends {
    public static function 
who() {
        echo 
__CLASS__."\n";
    }
}


C::test();
?>

Ví dụ trên sẽ in ra:

A
C
C

Kết nối Host + Database trong PHP

Kết nối MySQL

$ketnoi=mysql_connect("Tên_host","Tên_đăng_nhập_mysql","Mật_khẩu") or die(mysql_error()); //Kết nối tới Host

mysql_select_db("Tên_database",$ketnoi); //Kết nối tới Database

mysql_query("SET NAMES 'UTF8'",$ketnoi); //Yêu cầu hỗ trợ chữ có dấu cho cơ sở dữ liệu hiển thị trên trang web

Ví dụ:

$ketnoi=mysql_connect("localhost","root","1234567") or die(mysql_error());

mysql_select_db("dbphp",$ketnoi);

mysql_query("SET NAMES 'UTF8'",$ketnoi);

Kết nối MySQLi

$ketnoi=mysqli_connect("Tên_host","Tên_đăng_nhập_mysql","Mật_khẩu","Tên_database") or die(mysqli_error()); //Kết nối tới Host + Database

$ketnoi->query("SET NAMES 'UTF8'",$ketnoi); //Yêu cầu hỗ trợ chữ có dấu cho cơ sở dữ liệu hiển thị trên trang web

Ví dụ:

$ketnoi=mysqli_connect("localhost","root","1234567","dbphp");

$ketnoi->query("SET NAMES 'UTF8'",$ketnoi);

Các hàm truy vấn áp dụng cho MySQLi các bạn thêm i vào, ví dụ như mysqli_num_rows(), mysqli_fetch_array(), ...

Kết nối MySql bằng PDO

$dns = "mysql:host=Tên_host;dbname=Tên_database";

$username = "Tên_đăng_nhập_mysql";

$password = "Mật_khẩu";

$db = new PDO($dns, $username, $password);

Ví dụ:

$dns = "mysql:host=localhost;dbname=dbphp";

$username = "root";

$password = "";

$db = new PDO($dns, $username, $password);

Key cho Sublime Text 2.x, 3.x (Win, Mac và Linux)

Tất cả các key dưới đây đều đã được kiểm tra (vào ngày 12/05/2016) và đều hoạt động được với các phiên bản Sublime Text 2.x và 3.x (từ bản 2221; 3062~3126) trên tất cả các nền tảng Windows, Mac OS X và Linux. Bạn hãy vào Help > Enter License để tiến hành đăng ký bằng cách copy phần chuỗi nằm giữa —– BEGIN LICENSE —– và —— END LICENSE ——.

Sublime Text 2.x (tất cả các bản)

—– BEGIN LICENSE —–
Andrew Weber
Single User License
EA7E-855605
813A03DD 5E4AD9E6 6C0EEB94 BC99798F
942194A6 02396E98 E62C9979 4BB979FE
91424C9D A45400BF F6747D88 2FB88078
90F5CC94 1CDC92DC 8457107A F151657B
1D22E383 A997F016 42397640 33F41CFC
E1D0AE85 A0BBD039 0E9C8D55 E1B89D5D
5CDB7036 E56DE1C0 EFCC0840 650CD3A6
B98FC99C 8FAC73EE D2B95564 DF450523
—— END LICENSE ——

Sublime Text 3.x (trước 309x)

—– BEGIN LICENSE —–
Andrew Weber
Single User License
EA7E-855605
813A03DD 5E4AD9E6 6C0EEB94 BC99798F
942194A6 02396E98 E62C9979 4BB979FE
91424C9D A45400BF F6747D88 2FB88078
90F5CC94 1CDC92DC 8457107A F151657B
1D22E383 A997F016 42397640 33F41CFC
E1D0AE85 A0BBD039 0E9C8D55 E1B89D5D
5CDB7036 E56DE1C0 EFCC0840 650CD3A6
B98FC99C 8FAC73EE D2B95564 DF450523
—— END LICENSE ——

—– BEGIN LICENSE —–
K-20
Single User License
EA7E-940129
3A099EC1 C0B5C7C5 33EBF0CF BE82FE3B
EAC2164A 4F8EC954 4E87F1E5 7E4E85D6
C5605DE6 DAB003B4 D60CA4D0 77CB1533
3C47F579 FB3E8476 EB3AA9A7 68C43CD9
8C60B563 80FE367D 8CAD14B3 54FB7A9F
4123FFC4 D63312BA 141AF702 F6BBA254
B094B9C0 FAA4B04C 06CC9AFC FD412671
82E3AEE0 0F0FAAA7 8FA773C9 383A9E18
—— END LICENSE ——

—– BEGIN LICENSE —–
J2TeaM
2 User License
EA7E-940282
45CB0D8F 09100037 7D1056EB A1DDC1A2
39C102C5 DF8D0BF0 FC3B1A94 4F2892B4
0AEE61BA 65758D3B 2EED551F A3E3478C
C1C0E04E CA4E4541 1FC1A2C1 3F5FB6DB
CFDA1551 51B05B5D 2D3C8CFE FA8B4285
051750E3 22D1422A 7AE3A8A1 3B4188AC
346372DA 37AA8ABA 6EB30E41 781BC81F
B5CA66E3 A09DBD3A 3FE85BBD 69893DBD
—— END LICENSE ——

Sublime Text 3.x (sau 309x)

—– BEGIN LICENSE —–
MinBan
Single User License
EA7E-806395
318133A3 8F202A61 B0DBB8EB 21E17D2E
97D540E6 34079344 54620650 71E47589
9EF87857 345F5042 0D728DD1 8D8C979D
6A4F4DD2 67BB0345 746CA297 515BDA91
6CEAB381 4DB56700 D77DCD14 977BD326
1AC309ED 0EB414B8 4730DA10 99DBD291
FC88E0EF DCC7E3A9 56E4FFED 7629746B
E529AECA 92A96B60 72AE8928 8A240AAC
—— END LICENSE ——

—– BEGIN LICENSE —–
Michael Barnes
Single User License
EA7E-821385
8A353C41 872A0D5C DF9B2950 AFF6F667
C458EA6D 8EA3C286 98D1D650 131A97AB
AA919AEC EF20E143 B361B1E7 4C8B7F04
B085E65E 2F5F5360 8489D422 FB8FC1AA
93F6323C FD7F7544 3F39C318 D95E6480
FCCC7561 8A4A1741 68FA4223 ADCEDE07
200C25BE DBBC4855 C4CFB774 C5EC138C
0FEC1CEF D9DCECEC D3A5DAD1 01316C36
—— END LICENSE ——

—– BEGIN LICENSE —–
Free Communities Consultoria em Informática Ltda
Single User License
EA7E-801302
C154C122 4EFA4415 F1AAEBCC 315F3A7D
2580735A 7955AA57 850ABD88 72A1DDD8
8D2CE060 CF980C29 890D74F2 53131895
281E324E 98EA1FEF 7FF69A12 17CA7784
490862AF 833E133D FD22141D D8C89B94
4C10A4D2 24693D70 AE37C18F 72EF0BE5
1ED60704 651BC71F 16CA1B77 496A0B19
463EDFF9 6BEB1861 CA5BAD96 89D0118E
—— END LICENSE ——

—– BEGIN LICENSE —–
Nicolas Hennion
Single User License
EA7E-866075
8A01AA83 1D668D24 4484AEBC 3B04512C
827B0DE5 69E9B07A A39ACCC0 F95F5410
729D5639 4C37CECB B2522FB3 8D37FDC1
72899363 BBA441AC A5F47F08 6CD3B3FE
CEFB3783 B2E1BA96 71AAF7B4 AFB61B1D
0CC513E7 52FF2333 9F726D2C CDE53B4A
810C0D4F E1F419A3 CDA0832B 8440565A
35BF00F6 4CA9F869 ED10E245 469C233E
—— END LICENSE ——

—– BEGIN LICENSE —–
Anthony Sansone
Single User License
EA7E-878563
28B9A648 42B99D8A F2E3E9E0 16DE076E
E218B3DC F3606379 C33C1526 E8B58964
B2CB3F63 BDF901BE D31424D2 082891B5
F7058694 55FA46D8 EFC11878 0868F093
B17CAFE7 63A78881 86B78E38 0F146238
BAE22DBB D4EC71A1 0EC2E701 C7F9C648
5CF29CA3 1CB14285 19A46991 E9A98676
14FD4777 2D8A0AB6 A444EE0D CA009B54
—— END LICENSE ——

—– BEGIN LICENSE —–
Alexey Plutalov
Single User License
EA7E-860776
3DC19CC1 134CDF23 504DC871 2DE5CE55
585DC8A6 253BB0D9 637C87A2 D8D0BA85
AAE574AD BA7D6DA9 2B9773F2 324C5DEF
17830A4E FBCF9D1D 182406E9 F883EA87
E585BBA1 2538C270 E2E857C2 194283CA
7234FF9E D0392F93 1D16E021 F1914917
63909E12 203C0169 3F08FFC8 86D06EA8
73DDAEF0 AC559F30 A6A67947 B60104C6
—— END LICENSE ——

—– BEGIN LICENSE —–
Peter Halliday
Single User License
EA7E-855988
3997BFF0 2856413A 7A555954 67069B78
06D8CE12 63EAF079 AD039757 79E16D13
C555AD90 465CBE53 10F6DFC4 D3A3C611
411106F8 0CFEB15F 0A7BB891 111F5ED2
C6AA8429 77913528 FA6291A9 B88D4550
F1D6AB13 BF9153BC 91B4DFFE D296CFE0
C1D8EB22 13D5F14E 75A699EC 49EDDC23
D89D0F9B D240B10A A3712467 09DE7870
—— END LICENSE ——

—– BEGIN LICENSE —–
Fred Zirdung
Single User License
EA7E-844672
6089C0EC 22936E1A 1EADEBE2 B8654BBA
5C98FFA6 C0FD1599 0364779B 071C74FB
EEFE9EAB 92B3D867 CD1B32FE D190269F
6FC08F8F 8D24191D 32828465 942CE58E
AECE5307 08B62229 D788560A 6E0AAC4B
48A2D9EE 24FD8CAA 07BEBDF2 28EA86D4
CCB96084 6C34CAD2 E8A04F39 3B5A3CBC
3B668BB7 C94D0B4B 847D6D7F 4BC07375
—— END LICENSE ——

—– BEGIN LICENSE —–
Wixel
Single User License
EA7E-848235
103D2969 8700C7ED 8173CF61 537000C0
EB3C7ECB 5E750F17 6B42B67C A190090B
7669164F C6F371A8 5A1D88D5 BDD0DA70
C065892B 7CC1BB2B 1C8B8C7C F08E7789
7C2A5241 35F86328 4C8F70D9 C023D7C2
11245C36 59A730DB 72BDB9A7 D5B20304
90E90E72 9F08CA25 73F49C20 179D938E
5BC8BEDA 13457A69 39E6265F 233767F9
—— END LICENSE ——

—– BEGIN LICENSE —–
Daniel Russel
Single User License
EA7E-917420
9327EC62 44020C2A 45172A68 12FE13F1
1D22245B 680892EE F551F8EB C183D032
8B4EDB4B 479CB7E4 07E42EDD A780021D
56BADF42 AC05238B 023B47B1 EBA1B7DE
6DF9A383 159F32AE 04EBE100 1278B1D2
52E81B60 C68AA2E8 F84A20BE FE7990EB
5D44E4B6 16369263 1DDAACBC 280FF19E
86CF4319 0B8615A8 4FF0512E B123B8EC
—— END LICENSE ——

—– BEGIN LICENSE —–
Peter Eriksson
Single User License
EA7E-890068
8E107C71 3100D6FC 2AC805BF 9E627C77
72E710D7 43392469 D06A2F5B F9304FBD
F5AB4DB2 7A95F172 FE68E300 42745819
E94AB2DF C1893094 ECABADC8 71FEE764
20224821 3EABF931 745AF882 87AD0A4B
33C6E377 0210D712 CD2B1178 82601542
C7FD8098 F45D2824 BC7DFB38 F1EBD38A
D7A3AFE0 96F938EA 2D90BD72 9E34CDF0
—— END LICENSE ——

—– BEGIN LICENSE —–
Ryan Clark
Single User License
EA7E-812479
2158A7DE B690A7A3 8EC04710 006A5EEB
34E77CA3 9C82C81F 0DB6371B 79704E6F
93F36655 B031503A 03257CCC 01B20F60
D304FA8D B1B4F0AF 8A76C7BA 0FA94D55
56D46BCE 5237A341 CD837F30 4D60772D
349B1179 A996F826 90CDB73C 24D41245
FD032C30 AD5E7241 4EAA66ED 167D91FB
55896B16 EA125C81 F550AF6B A6820916
—— END LICENSE ——

Nguồn: http://appnee.com/sublime-text-3-universal-license-keys-collection-for-win-mac-linux/

Tạo thuộc tính mới cho thể hiện của lớp

Bạn vẫn có thể tạo thuộc tính mới cho đối tượng (thể hiện) của lớp mặc dù thuộc tính đó không phải là thuộc tính của lớp.

Ví dụ:

<?php
    class A{
        static $a=10;
        function demo(){
        echo self::$a;
        }
    }
    $b=new A();
    $b->a=20;
    $b->b=30;
    $b->c=40;
    echo $b->a; // In ra: 20
    echo $b->b; // In ra: 30
    echo $b->c; // In ra: 40
?>

 

Phạm vi của biến

Phạm vi của biến là bối cảnh trong đó nó được định nghĩa. Đa số các biến PHP chỉ có một phạm vi duy nhất. Phạm vi này bao gồm cả các file được include và require tương ứng. Ví dụ:

<?php
$a 
1;
include 
'b.inc';
?>

Ở ví dụ trên thì biến $a sẽ sử dụng được trong file b.inc. Tuy nhiên, trong các hàm do người dùng định nghĩa thì ta không sử dụng được biến khai báo ngoài hàm một cách thông thường. Ví dụ:

<?php
$a 
1/* phạm vi toàn cục */ 

function test()

    echo 
$a/* không sử dụng được biến toàn cục $a như thế này */ 


test();
?>

Ở đoạn mã trên thì ta không thể sử dụng được biến $a trong hàm test() như vậy, lúc này biến $a trong hàm test() lại được hiểu là biến cục bộ của chính hàm test() đó. Để khắc phục điều này thì ta cần phải sử dụng đến từ khóa global.

Từ khóa global

Ta xét một ví dụ sử dụng từ khóa global như sau:

Ví dụ 1: Sử dụng global

<?php
$a 
1;
$b 2;

function 
Sum()
{
    global 
$a$b;

    
$b $a $b;


Sum();
echo 
$b;
?>

Đoạn mã trên sẽ in ra 3. $a$b là các biến global vì chúng được khai báo ngoài hàm, và chúng được sử dụng trong hàm Sum() bằng cách khai báo lại và đặt từ khóa global để trình dịch hiểu chúng là các biến toàn cục. Một hàm có quyền sử dụng bất kỳ biến global nào và với số lượng tùy ý.

Ở ví dụ dưới đây thể hiện một cách khác để sử dụng biến toàn cục, đó là sử dụng mảng $GLOBALS được định nghĩa sẵn trong PHP:

Ví dụ 2: Sử dụng $GLOBALS thay cho global

<?php
$a 
1;
$b 2;

function 
Sum()
{
    
$GLOBALS['b'] = $GLOBALS['a'] + $GLOBALS['b'];


Sum();
echo 
$b;
?>

Mảng $GLOBALS là mảng kết hợp với tên của biến toàn cục với giá trị mà biến toàn cục chứa, theo đó, mỗi biến toàn cục sẽ được hiểu là một phần tử của mảng này, với chỉ số của phần tử mảng chính là tên của biến toàn cục, còn giá trị của phần tử đó chính là giá trị của biến toàn cục. Lưu ý ta có thể sử dụng $GLOBALS ở bất kỳ đâu, đó là bởi vì nó là siêu biến toàn cục (superglobal). Dưới đây là một ví dụ demo về khả năng của siêu biến toàn cục:

Ví dụ 3: Demo khả năng của siêu biến toàn cục

<?php
function test_global()
{
    
// Phần lớn các biến được định nghĩa không phải là "super" và yêu cầu
    // sử dụng 'global' để dùng được trong hàm.
    
global $HTTP_POST_VARS;
    
    echo 
$HTTP_POST_VARS['name'];
    
    
// Siêu biến toàn cục sử dụng được ở mọi nơi và không yêu cầu từ khóa
    // 'global'. Tuy nhiên, hiện nay thì siêu biến toàn cục dạng như
    // HTTP_POST_VARS không còn được khuyến khích sử dụng.
    
echo $_POST['name'];
}

?>

Lưu ý:

Không được sử dụng từ khóa global bên ngoài hàm, khi đó sẽ phát sinh lỗi. Tuy nhiên, ta có thể sử dụng điều này nếu nó nằm trong tập tin được gọi từ hàm.

Sử dụng biến static

Một đặc tính khác của phạm vi biến là biến static. Biến tĩnh chỉ dùng được trong hàm, tuy nhiên thì giá trị của nó không bị mất đi sau khi hàm được thực thi xong. Xét ví dụ sau:

Ví dụ 4: demo sự cần thiết của biến static

<?php
function test()
{
    
$a 0;
    echo 
$a;
    
$a++;
}

?>

Ở hàm trên thì câu lệnh $a++; tỏ ra không có tác dụng mỗi khi hàm được gọi, bởi vì mỗi khi được gọi thì giá trị của biến $a lại được đặt thành 0. Để khắc phục điều này thì ta chỉ cần khai báo biến $a là biến tĩnh:

Ví dụ 5: sử dụng biến tĩnh

<?php
function test()
{
    static 
$a 0;
    echo 
$a;
    
$a++;
}

?>

Ở ví dụ trên, giá trị của biến $a vẫn được giữ lại, vì thế mỗi khi gọi hàm test() thì giá trị của $a lại tăng một đơn vị.

Biến tĩnh cũng cung cấp một cách để đối phó với hàm đệ quy. Hàm đệ quy là hàm có đặc điểm nó gọi đến chính nó. Cần hết sức cẩn thận khi sử dụng hàm đệ quy bởi vì nó có khả năng đệ quy vĩnh viễn. Bạn phải đảm bảo rằng bạn đã cung cấp cách để dừng đệ quy cho hàm. Ví dụ sau đây sẽ đếm từ 1 đến 10 sử dụng biến tĩnh $count:

Ví dụ 6: Biến tĩnh với hàm đệ quy

<?php
function test()
{
    static 
$count 0;

    
$count++;
    echo 
$count;
    if (
$count 10) {
        
test();
    }
    
$count--;
}

?>

Lưu ý:

Từ bản PHP 5.6 ta có thể gán giá trị cho biến tĩnh là kết quả của một biểu thức, nhưng không được gán cho biến tĩnh là lời gọi tới hàm nào đó.

Ví dụ 7: Khai báo biến tĩnh

<?php
function foo(){
    static 
$int 0;          // đúng
    
static $int 1+2;        // đúng (PHP 5.6)
    
static $int sqrt(121);  // sai (vì gán lời gọi hàm cho biến tĩnh)

    
$int++;
    echo 
$int;
}

?>

Lưu ý:

Những biến tĩnh được được giải quyết trong thời gian biên dịch.

Tham chiếu với các biến globalstatic

Zend Engine 1 và PHP 4 thực thi các bổ từ staticglobal theo hình thức là các tham chiếu. Ví dụ như một biến toàn cục được đưa vào trong một hàm với từ khóa global thì bản chất là tạo ra một tham chiếu tới biến toàn cục. Điều này có thể dẫn đến hành vi bất ngờ đối với các địa chỉ như ví dụ sau:

<?php
function test_global_ref() {
    global 
$obj;
    
$obj = &new stdclass;
}

function 
test_global_noref() {
    global 
$obj;
    
$obj = new stdclass;
}


test_global_ref();
var_dump($obj);
test_global_noref();
var_dump($obj);
?>

Ví dụ trên sẽ in ra:

NULL
object(stdClass)(0) {
}

Hành vi tương tự cũng được áp dụng cho câu lệnh static. Khi đó các tham chiếu sẽ không được lưu trữ dưới dạng tĩnh:

<?php
function &get_instance_ref() {
    static 
$obj;

    echo 
'Static object: ';
    
var_dump($obj);
    if (!isset(
$obj)) {
        
// Gán một tham chiếu tới biến tĩnh
        
$obj = &new stdclass;
    }
    
$obj->property++;
    return 
$obj;
}

function &
get_instance_noref() {
    static 
$obj;

    echo 
'Static object: ';
    
var_dump($obj);
    if (!isset(
$obj)) {
        
// Gán một đối tượng cho biến tĩnh
        
$obj = new stdclass;
    }
    
$obj->property++;
    return 
$obj;
}


$obj1 get_instance_ref();
$still_obj1 get_instance_ref();
echo 
"\n";
$obj2 get_instance_noref();
$still_obj2 get_instance_noref();
?>

Ví dụ trên sẽ in ra:

Static object: NULL
Static object: NULL

Static object: NULL
Static object: object(stdClass)(1) {
["property"]=>
int(1)
}

Ví dụ trên cho thấy khi ta gán một tham chiếu tới biến tĩnh thì nó không hề được lưu lại khi ta gọi hàm &get_instance_ref() lần thứ hai.

Cách upload nhiều file cùng lúc

Trước tiên ta tạo một FORM như sau:

<form action="demo_upload.php" enctype="multipart/form-data" method="POST">

<input type="file" name="file[]" multiple />

<p><input type="submit" name="upload" value="Upload File"/></p>

</form>


Giải thích FORM:

  • enctype=”multipart/form-data”: dữ liệu được chia ra làm nhiều phần, dùng để upload file.
  • method=”POST”: phương thức gửi dữ liệu là post.
  • Một input có type = "file" và có tên là một mảng file[], lưu ý là phải có thuộc tính multiple để cho phép chọn nhiều file cùng một lúc.
  • Nút lệnh Submit để gửi dữ liệu.

Còn đây là đoạn code của file demo_upload.php:

if (isset($_POST[‘submit’])){
    $name = array();
    $tmp_name = array();
    $error = array();
    $ext = array();
    $size = array();
    foreach ($_FILES[‘file’][‘name’] as $file) {
        $name[] = $file;                            
    }
    foreach ($_FILES[‘file’][‘tmp_name’] as $file){
        $tmp_name[] = $file;
    }
    foreach ($_FILES[‘file’][‘error’] as $file){
        $error[] = $file;
    }
    foreach ($_FILES[‘file’][‘type’] as $file){
        $ext[] = $file;
    }
    foreach ($_FILES[‘file’][‘size’] as $file){
        $size[] = round($file/1024,2);
    } //Phần này lấy giá trị ra từng mảng nhỏ
    echo “Tổng số file được tải lên: “.count($name).”<br>”;
    echo “<table style=’color: white;’>\n<thead>\n<th>Tên file</th>\n<th>Loại</th>\n<th>Kích thước</th>\n<th>Thư mục</th>”;
    for ($i=0;$i<count($name);$i++){
        if ($error[$i] > 0){
            echo “Lỗi: ” . $error[$i];
        }elseif ($ext[$i]!=’application/save’) {
             echo “File không được hổ trợ”.$ext[$i];
         }else {
             $temp = preg_split(‘/[\/\\\\]+/’, $name[$i]);
             $filename = $temp[count($temp)-1];
             $upload_dir = “../download/”;
             $upload_file = $upload_dir . $filename;
             if (file_exists($upload_file)) {
                 echo ‘File đã tồn tại’;
             } else {
                 if ( move_uploaded_file($tmp_name[$i], $upload_file) ) {
                     echo “<tr>\n<td>”.$name[$i].”</td>\n”;
                     echo ‘<td>’.$ext[$i].”</td>\n”;
                     echo ‘<td>’.$size[$i].” kB</td>\n”;
                     echo ‘<td>’.$upload_file.”</td>\n</tr>”;
                     $date = date(“d-m-Y”);
                     @mysqli_connect(‘stringhost’, ’stringUsername’, ’stringPass’, ’stringDatabase’);
                     @mysqli_query($conn, ”INSERT INTO `tablename` VALUES (null,'{$name[$i]}’,'{$size[$i]}’,’$upload_dir’,’$date’,0)”) or die(“Bi loi them du lieu”.mysqli_error($conn));
                     @mysqli_close($conn);
                 } else echo ‘loi’;
             }
         }//End khoi cau lenh up file va them vao CSDL;
     }//End vong lap for cho tat ca cac file;
    echo ‘</table>’;  
}

Giải thích đoạn mã:

  • Trước tiên ta lấy từng mảng nhỏ trong mảng $_FILES[‘file’] ra thành các mảng nhỏ là $name[], $tmp_name[], $type[], $size[] và $error[].
  • Tiếp theo ta tạo một vòng lặp cho các phần tử của mảng vừa mới tạo, biến chạy $i chạy từ 0 tới count($name)-1;
  • Từ đây ta sẽ viết tiếp lệnh up file và thêm dữ liệu vào CSDL:
    • $temp = preg_split(‘/[\/\\\\]+/’, $name[$i]); $filename = $temp[count($temp)-1]: hai câu lệnh này dùng để lấy tên file;
    • $upload_dir = “../download/”: thư mục upload của mình là ../upload (chỉnh sửa để phù hợp với trường hợp của bạn);
    • move_uploaded_file($tmp_name[$i], $upload_file): dòng lệnh này dùng để up file lên host;
    • và cuối cùng là ghi dữ liệu vào CSDL mySQL với khối lệnh sau: @mysqli_connect(‘stringhost’,’stringUsername’,’stringPass’,’stringDatabase’);
      @mysqli_query($conn,”INSERT INTO `tablename` VALUES (null,'{$name[$i]}’,'{$size[$i]}’,’$upload_dir’,’$date’,0)”) or die(“Bi loi them du lieu”.mysqli_error($conn));
      @mysqli_close($conn);
  • Và để tiện quan sát kết quả ta sẽ cho hiển thị dưới dạng bảng với khối lệnh:

echo “<table>”;

echo “<tr>\n<td>”.$name[$i].”</td>\n”;

echo ‘<td>’.$ext[$i].”</td>\n”;

echo ‘<td>’.$size[$i].” kB</td>\n”;

echo ‘<td>’.$upload_file.”</td>\n</tr>”;

Cách hiển thị dữ liệu có dấu chuẩn

Để hiển thị dữ liệu có dấu, đặc biệt là dữ liệu load từ AJAX ta làm dạng như sau:
$connect=new MySQLi('tên_host','username','password','database');
mysqli_set_charset($connect,'utf8');
Ví dụ:
                 $connect=new MySQLi('localhost','root','','db1');
mysqli_set_charset($connect,'utf8');                 

is_array() trong PHP

Phương thức is_array() Dùng để kiểm tra xem 1 biến nào đó có phải là một mảng hay không.

Phương thức này trả về TRUE nếu biến là mảng, FALSE nếu biến không phải là mảng.

Ví dụ:

<?php
$yes 
= array('this''is''an array');

echo 
is_array($yes) ? 'Array' 'not an Array';
echo 
"\n";

$no 'this is a string';

echo 
is_array($no) ? 'Array' 'not an Array';
?>

Kết quả của ví dụ:

Array
not an Array

gettype() trong PHP

(PHP 4, PHP 5, PHP 7)

gettype() dùng để lấy kiểu dữ liệu của biến.

Các giá trị trả về:

  • "boolean"
  • "integer"
  • "double"
  • "string"
  • "array"
  • "object"
  • "resource"
  • "resource (closed)" - cho PHP 7.2.0
  • "NULL"
  • "unknown type"

Ví dụ

<?php

$data 
= array(11.NULL, new stdClass'foo');

foreach (
$data as $value) {
    echo 
gettype($value), "\n";
}


?>

Kết quả của ví dụ:

integer
double
NULL
object
string

is_object() trong PHP

(PHP 4, PHP 5, PHP 7)

is_object() dùng để kiểm tra xem một biến nào đó có phải là một đối tượng hay không.

Phương thức trả về TRUE nếu biến là đối tượng, FALSE nếu ngược lại.

Ví dụ

<?php
// Khai báo một hàm để trả về một mảng
// từ đối tượng

function get_students($obj)
{
    if (!
is_object($obj)) {
        return 
false;
    }

    return 
$obj->students;
}


// Khai báo một thể hiện của lớp mới
// và đưa vào một số giá trị

$obj = new stdClass();
$obj->students = array('Kalle''Ross''Felipe');

var_dump(get_students(null));
var_dump(get_students($obj));
?>

array_key_exists() trong PHP

Hàm array_key_exists() dùng để kiểm tra xem một key nào đó có nằm trong mảng hay không.

Hàm trả về TRUE nếu key có trong mảng, trả về FALSE nếu ngược lại.

Lưu ý: array_key_exists() chỉ tìm key trong mảng một chiều, các key lồng trong mảng nhiều chiều sẽ không được tìm.

Ví dụ 1:

<?php
$search_array 
= array('first' => 1'second' => 4);
if (
array_key_exists('first'$search_array)) {
    echo 
"The 'first' element is in the array";
}

?>

Ví dụ 2: array_key_exists() với isset()

isset() không trả về TRUE nếu giá trị ứng với key cần tìm là NULL, trong khi array_key_exists() vẫn trả về TRUE.

<?php
$search_array 
= array('first' => null'second' => 4);

// trả về false
isset($search_array['first']);

// trả về true
array_key_exists('first'$search_array);
?>

Lưu ý:

array_key_exists() vẫn sẽ trả về TRUE ngay cả một thuộc tính được định nghĩa trong một đối tượng đã cho dưới dạng mảng.

Để kiểm tra xem một thuộc tính nào đó có tồn tại trong đối tượng hay không ta sử dụng hàm property_exists().

Chuẩn PSR trong PHP là gì

Như các bạn biết là khi lập trình PHP thì mỗi người có một cách viết code khác nhau cũng như cách đặt tên biến khác nhau, do đó khi làm việc nhóm thì cần phải thống nhất style code với nhau, nếu không thì dự án của bạn sau một thời gian sẽ rất lộn xộn.

Chính vì lẻ đó mà PHP đã ra một tiêu chuẩn về PSR, vậy PSR là gì. Trong bài viết này chúng ta sẽ cùng tìm hiểu chi tiết về PSR để các bạn hiểu rõ hơn về PSR, để hiểu PSR là gì ? Tại sao các lập trình viên cần tuân thủ theo các quy tắc của nó.

PSR là gì?

PSR là viết tắt của PHP Special Request, là những tiêu chuẩn khi code PHP, nó được cộng đồng PHP xây dựng và áp dụng theo.

Trong quá trình làm việc, các hệ thống sử dụng các framework khác nhau ví dụ như Phalcon hay Laravel có thể phải kết hợp với nhau để thực hiện những bài toán cụ thể.

Tuy nhiên đối với mỗi framework của mỗi team lại code theo những chuẩn khác nhau, do đó nảy sinh ra vấn đề là cần có một bộ quy tắc chuẩn để giải quyết việc các code không chuẩn này, và PSR ra đời nhắm chuẩn hóa coding convention cho tất cả các framework, các framework chỉ việc tuân theo các chuẩn này thì các hệ thống framework khác nhau vẫn sẽ dùng chung một quy tắc, do đó sẽ thuận lợi cho việc phát triển sau này.

Thông tin chính thức và chuẩn mực về PSR các bạn có thể tìm thấy tại trang chủ của PSR http://www.php-fig.org/

Hiện tại PSR đã có đủ 7 tiêu chuẩn và vẫn tiếp tục được cập nhật. Trong đó :

Chuẩn PSR-0 nói về autoloading

PSR-0 cung cấp các quy tắc về việc viết các hàm autoload trong PHP, cách sử dụng namespace và kiến trúc thư mục, file để có thể đảm bảo tính nhất quán giữa các project của các developer.

Chuẩn PSR-1 về basic coding, chuẩn PSR-2 về style coding

PSR-1 và PSR-2 cung cấp các quy tắc về cú pháp trong code ví dụ như cách đặt tên hàm, tên biến, class, cấu trúc điều khiển, sử dụng 4 space thay cho 1 tab…

Chuẩn PSR-3 nói về logging

Bất cứ FW nào cần tích hợp chuẩn này thì cần phải có các phương thức như emergency, debug, info, error, etc, hãy xem cụ thể trong Phalcon nào

<!--?php use Phalcon\Logger; use Phalcon\Logger\Adapter\File as FileAdapter; $logger = new FileAdapter("app/logs/test.log"); // These are the different log levels available: $logger->critical(<br ?--> "This is a critical message"
);

$logger->emergency(
"This is an emergency message"
);

$logger->debug(
"This is a debug message"
);

$logger->error(
"This is an error message"
);

$logger->info(
"This is an info message"
);

$logger->notice(
"This is a notice message"
);

$logger->warning(
"This is a warning message"
);

$logger->alert(
"This is an alert message"
);

// You can also use the log() method with a Logger constant:
$logger->log(
"This is another error message",
Logger::ERROR
);

// If no constant is given, DEBUG is assumed.
$logger->log(
"This is a message"
);

// You can also pass context parameters like this
$logger->log(
"This is a {message}",
[
'message' => 'parameter'
]
);

Sau khi bạn test đoạn code trên thì kết quả trong file test.log sẽ như thế này

[Tue, 28 Jul 15 22:09:02 -0500][CRITICAL] This is a critical message
[Tue, 28 Jul 15 22:09:02 -0500][EMERGENCY] This is an emergency message
[Tue, 28 Jul 15 22:09:02 -0500][DEBUG] This is a debug message
[Tue, 28 Jul 15 22:09:02 -0500][ERROR] This is an error message
[Tue, 28 Jul 15 22:09:02 -0500][INFO] This is an info message
[Tue, 28 Jul 15 22:09:02 -0500][NOTICE] This is a notice message
[Tue, 28 Jul 15 22:09:02 -0500][WARNING] This is a warning message
[Tue, 28 Jul 15 22:09:02 -0500][ALERT] This is an alert message
[Tue, 28 Jul 15 22:09:02 -0500][ERROR] This is another error message
[Tue, 28 Jul 15 22:09:02 -0500][DEBUG] This is a message
[Tue, 28 Jul 15 22:09:02 -0500][DEBUG] This is a parameter

Chuẩn PSR-4 nói về autoloading : đây là phần cải tiến của PSR-0

Table dưới đây sẽ demo cho bạn cách dùng nó như thế nào

Fully Qualified Class Name Namespace Prefix Base Directory Resulting File Path
\Acme\Log\Writer\File_Writer Acme\Log\Writer ./acme-log-writer/lib/ ./acme-log-writer/lib/File_Writer.php
\Aura\Web\Response\Status Aura\Web /path/to/aura-web/src/ /path/to/aura-web/src/Response/Status.php
\Symfony\Core\Request Symfony\Core ./vendor/Symfony/Core/ ./vendor/Symfony/Core/Request.php
\Zend\Acl Zend /usr/includes/Zend/ /usr/includes/Zend/Acl.php

Chuẩn PSR-7 nói về HTTP message

Chuẩn này thường dùng cho request và response, ngay lúc này bạn không cần quan tâm nó, dành cho phần nâng cao

Trong số các chuẩn này, theo mình các bạn nên nắm chắc PSR-1 và PSR-2.
Nếu bạn có ý định tự viết FrameWork một framework cho riêng mình thì tìm hiểu PSR-0, PSR-4, PSR-3, ngoài ra có thể đọc thêm PSR-7.

Kết luận

Trên đây tôi đã tóm tắt các chuẩn căn bản của PHP cho bạn có khái niệm cũng như cái nhìn căn bản, để hiểu rõ nó hơn bạn cần có thời gian thực hành nó, ngoài ra bạn cũng có thể đọc bản tiếng anh tại đây để hiểu rõ hơn http://www.php-fig.org

Nguồn: https://gsviec.com/blog/chuan-psr-trong-php-la-gi

Redis là gì?

1. Giới thiệu

Redis là 1 hệ thống lưu trữ key-value rất mạnh mẽ và phổ biến hiện nay.

Redis nổi bật bởi việc hỗ trợ nhiều cấu trúc dữ liệu cơ bản(hash, list, set, sorted set, string), giúp việc thao tác với dữ liệu tốt hơn các hệ thống cũ như memcached rất nhiều.

Bên cạnh lưu trữ key-value trên RAM giúp tối ưu performance, redis còn có cơ chế sao lưu dữ liệu trên đĩa cứng cho phép phục hồi dữ liệu khi gặp sự cố.

2. Khái quát

Bạn có thể clone mã nguồn redis về máy tính mình bằng câu lệnh dưới đây:

git clone https://github.com/antirez/redis.git

Bộ nhớ sử dụng:

Mặc định là mất ~ 1MB

1M small keys -> String value sử dụng ~ 100MB

1M Keys -> Hash value, lưu trữ 5 trường dữ liệu, sử dụng ~ 200MB

\"\\"\\"\"

Số lượng file mã nguồn: 55

Số lượng file header: 30

Tổng số dòng code: 43829

\"\\"\\"\"

3. Các modules

Redis bao gồm các module sau:

Framework hỗ trợ xử lý bất đồng bộ, networking: ae, anet

Mô tả dữ liệu: sds.c, t_hash.c, t_list.c, t_string.c, t_zset.c, object.c, notify.c (pub-sub)

Lưu trữ dữ liệu, cơ sở dữ liệu: db.c, dict.c, ziplist.c, zipmap.c, adlist.c

Module hỗ trợ IO/persistent redis: rdb.c, aof.c, bio.c, rio.c

Utilities: crc16.c, crc64.c, pqsort.c, lzf_c.c, lzf_d.c

4. Persistent redis

Bên cạnh việc lưu key-value trên bộ nhớ RAM, Redis có 2 background threads chuyên làm nhiệm vụ định kỳ ghi dữ liệu lên đĩa cứng.

Có 2 loại file được ghi xuống đĩa cứng:

RDB (Redis DataBase file) Cách thức làm việc RDB thực hiện tạo và sao lưu snapshot của DB vào ổ cứng sau mỗi khoảng thời gian nhất định.

Ưu điểm

RDB cho phép người dùng lưu các version khác nhau của DB, rất thuận tiện khi có sự cố xảy ra. Bằng việc lưu trữ data vào 1 file cố định, người dùng có thể dễ dàng chuyển data đến các data centers, máy chủ khác nhau. RDB giúp tối ưu hóa hiệu năng của Redis. Tiến trình Redis chính sẽ chỉ làm các công việc trên RAM, bao gồm các thao tác cơ bản được yêu cầu từ phía client như thêm/đọc/xóa, trong khi đó 1 tiến trình con sẽ đảm nhiệm các thao tác disk I/O. Cách tổ chức này giúp tối đa hiệu năng của Redis. Khi restart server, dùng RDB làm việc với lượng data lớn sẽ có tốc độ cao hơn là dùng AOF.

Nhược điểm

RDB không phải là lựa chọn tốt nếu bạn muốn giảm thiểu tối đa nguy cơ mất mát dữ liệu. Thông thường người dùng sẽ set up để tạo RDB snapshot 5 phút 1 lần (hoặc nhiều hơn). Do vậy, trong trường hợp có sự cố, Redis không thể hoạt động, dữ liệu trong những phút cuối sẽ bị mất. RDB cần dùng fork() để tạo tiến trình con phục vụ cho thao tác disk I/O. Trong trường hợp dữ liệu quá lớn, quá trình fork() có thể tốn thời gian và server sẽ không thể đáp ứng được request từ client trong vài milisecond hoặc thậm chí là 1 second tùy thuộc vào lượng data và hiệu năng CPU.

AOF (Append Only File) Cách thức làm việc AOF lưu lại tất cả các thao tác write mà server nhận được, các thao tác này sẽ được chạy lại khi restart server hoặc tái thiết lập dataset ban đầu.

Ưu điểm

Sử dụng AOF sẽ giúp đảm bảo dataset được bền vững hơn so với dùng RDB. Người dùng có thể config để Redis ghi log theo từng câu query hoặc mỗi giây 1 lần. Redis ghi log AOF theo kiểu thêm vào cuối file sẵn có, do đó tiến trình seek trên file có sẵn là không cần thiết. Ngoài ra, kể cả khi chỉ 1 nửa câu lệnh được ghi trong file log (có thể do ổ đĩa bị full), Redis vẫn có cơ chế quản lý và sửa chữa lối đó (redis-check-aof). Redis cung cấp tiến trình chạy nền, cho phép ghi lại file AOF khi dung lượng file quá lớn. Trong khi server vẫn thực hiện thao tác trên file cũ, 1 file hoàn toàn mới được tạo ra với số lượng tối thiểu operation phục vụ cho việc tạo dataset hiện tại. Và 1 khi file mới được ghi xong, Redis sẽ chuyển sang thực hiện thao tác ghi log trên file mới.

Nhược điểm

File AOF thường lớn hơn file RDB với cùng 1 dataset. AOF có thể chậm hơn RDB tùy theo cách thức thiết lập khoảng thời gian cho việc sao lưu vào ổ cứng. Tuy nhiên, nếu thiết lập log 1 giây 1 lần có thể đạt hiệu năng tương đương với RDB. Developer của Redis đã từng gặp phải bug với AOF (mặc dù là rất hiếm), đó là lỗi AOF không thể tái tạo lại chính xác dataset khi restart Redis. Lỗi này chưa gặp phải khi làm việc với RDB bao giờ.

5. Data model

Khác với RDMS như MySQL, hay PostgreSQL, Redis không có table (bảng). Redis lưu trữ data dưới dạng key-value. Thực tế thì memcache cũng làm vậy, nhưng kiểu dữ liệu của memcache bị hạn chế, không đa dạng được như Redis, do đó không hỗ trợ được nhiều thao tác từ phía người dùng. Dưới đây là sơ lược về các kiểu dữ liệu Redis dùng để lưu value.

STRING: Có thể là string, integer hoặc float. Redis có thể làm việc với cả string, từng phần của string, cũng như tăng/giảm giá trị của integer, float.

LIST: Danh sách liên kết của các strings. Redis hỗ trợ các thao tác push, pop từ cả 2 phía của list, trim dựa theo offset, đọc 1 hoặc nhiều items của list, tìm kiếm và xóa giá trị.

SET: Tập hợp các string (không được sắp xếp). Redis hỗ trợ các thao tác thêm, đọc, xóa từng phần tử, kiểm tra sự xuất hiện của phần tử trong tập hợp. Ngoài ra Redis còn hỗ trợ các phép toán tập hợp, gồm intersect/union/difference.

HASH: Lưu trữ hash table của các cặp key-value, trong đó key được sắp xếp ngẫu nhiên, không theo thứ tự nào cả. Redis hỗ trợ các thao tác thêm, đọc, xóa từng phần tử, cũng như đọc tất cả giá trị.

ZSET (sorted set): Là 1 danh sách, trong đó mỗi phần tử là map của 1 string (member) và 1 floating-point number (score), danh sách được sắp xếp theo score này. Redis hỗ trợ thao tác thêm, đọc, xóa từng phần tử, lấy ra các phần tử dựa theo range của score hoặc của string.

6. Kết luận

Redis là một sự lựa chọn tuyệt vời khi ta cần đến một server lưu trữ dữ liệu đòi hỏi tính mở rộng cao (scaleable) và chia sẻ bởi nhiều tiến trình, nhiều ứng dụng và nhiều server khác nhau. Chỉ riêng cơ chế tương tác giữa các tiến trình đã cực kỳ khó nhằn rồi. Do đó việc ta có thể tương tác cross-platform, cross-server, và cross-application đã làm Redis trở thành một lựa chọn đúng đắn cho rất rất nhiều công việc khác nhau. Tốc độ cực cao của Redis cũng có thể được lợi dụng để làm caching layer.

Nguồn: https://viblo.asia/p/redis-la-gi-157G5okARAje

Cách lấy URL với PHP

$url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";

diff và date_diff

(PHP 5 >= 5.3.0, PHP 7)

DateTime::diff -- DateTimeImmutable::diff -- DateTimeInterface::diff -- date_diff — Trả về sự khác nhau giữa 2 đối tượng DateTime.

Dạng hướng đối tượng

public DateInterval DateTime::diff ( DateTimeInterface $datetime2 [, bool $absolute = FALSE ] )

public DateInterval DateTimeImmutable::diff ( DateTimeInterface $datetime2 [, bool $absolute = FALSE ] )

public DateInterval DateTimeInterface::diff ( DateTimeInterface $datetime2 [, bool $absolute = FALSE ] )

Dạng hướng thủ tục

DateInterval date_diff ( DateTimeInterface $datetime1 , DateTimeInterface $datetime2 [, bool$absolute = FALSE ] )

Trả về sự khác nhau giữa hai đối tượng DateTimeInterface.

Các tham số

datetime

Ngày so sánh

absolute

Dùng khi bắt buộc thời gian phải là một số dương.

Giá trị trả về

Đối tượng DateInterval sẽ trả về sự khác nhau giữa hai ngày hoặc FALSE nếu có lỗi.

Ví dụ

Ví dụ #1: DateTime::diff()

Dạng hướng đối tượng

<?php
$datetime1 = new DateTime('2009-10-11');
$datetime2 = new DateTime('2009-10-13');
$interval = $datetime1->diff($datetime2);
echo $interval->format('%R%a days');
?>

Dạng hướng thủ tục

<?php
$datetime1 = date_create('2009-10-11');
$datetime2 = date_create('2009-10-13');
$interval = date_diff($datetime1, $datetime2);
echo $interval->format('%R%a days');
?>

Các ví dụ trên sẽ in ra:

+2 days

Ví dụ #2: so sánh đối tượng DateTime

Lưu ý:

Từ phiên bản PHP 5.2.2, các đối tượng DateTime có thể được so sánh với nhau bằng cách sử dụng các phép toán so sánh.

<?php
$date1 = new DateTime("now");
$date2 = new DateTime("tomorrow");

var_dump($date1 == $date2);
var_dump($date1 < $date2);
var_dump($date1 > $date2);
?>

Ví dụ trên sẽ in ra:

bool(false)
bool(true)
bool(false)

Documentation mẫu cho thiết kế website

Powered by: v1study.com

 
 
V1Study.com
 
Shop Mobile Online
Documentation
 
 
 

 

 
 
 
Tên lớp – Tên nhóm
Group Member
1-    Họ và tên các thành viên trong nhóm
2-     
3-     
4-     
 
Instructor
 
Họ tên Giảng viên hướng dẫn
 
 
- Hanoi, Tháng/Năm -
 
 

INDEX
1.     Problem Definition. 3
1.1.     Problem Abstraction. 3
1.2.     The Current System.. 3
1.3.     The Proposed System.. 4
1.4.     Boundaries of the System.. 4
1.5.     Hardware and Software Requirements. 5
1.5.1.     Minimum Requirements. 5
1.5.2.     Recommended Requirements. 5
2.     Customer Requirements Specification. 6
2.1.     Users of the System.. 6
2.1.1.     Với  Guest : 6
2.1.2.     Với  Member : 6
2.1.3.     Với Admin : 6
2.2.     System functions. 6
2.2.1.     Với Guest : 6
2.2.2.     Với Member : 7
2.2.3.     Với Admin : 9
3.     System Designs. 13
3.1.     Entity Relationship Diagram.. 13
3.2.     Database Design. 19
3.3.     Sitemap. 25
3.4.     Algorithms. 27
4.     Task Sheet 35
5.     Check List 36
5.1.     Check List of Validation. 36
5.2.     Submission Checklist 36

1. Problem Definition

1.1. Problem Abstraction

    Trong thời đại công nghệ thông tin như hiện nay, khi mà Internet đã trở nên thân quen và dần trở thành một công cụ không thể thiếu trong cuộc sống thì lợi ích của một Website đối với việc quảng bá sản phẩm và thương hiệu của một công ty là vô cùng lớn. Xã hội ngày một năng động hơn cùng với việc phát triển và thay đổi của những cách thức mua bán cũ đã hình thành một hình thức mới: thương mại điện tử.

     Tùy từng lĩnh vực kinh doanh của từng doanh nghiệp mà Website mang lại những ích lợi khác nhau. Qua đó trang Web trở thành một cửa ngõ để nhà sản xuất tiếp thị sản phẩm của mình đến khách hàng khắp trên cả nước. Khách hàng không cần đến tận nơi để xem và mua những chiếc điện thoại mà họ cần nữa, thay vào đó, một cách nhanh chóng và thuận tiện, họ chỉ cần vào Web và đặt mua những “chú dế” phù hợp với mình…

     MOBILE SHOP ONLINE  là một cách giới thiệu sản phẩm công nghệ (cụ thể là điện thoại di động), đồng thời là phương thức quảng bá hình ảnh sản phẩm một cách đầy đủ nhất trên cộng đồng online, sự quảng bá này là không biên giới. Mặt khác trang Web còn giúp tăng số lượng người biết đến thương hiệu, tiếp cận được nhiều đối tượng, qua đó tăng doanh số bán hàng cả khi bạn offline và online. Ngoài ra với MOBILE SHOP ONLINE bạn còn có thể giảm được đáng kể thời gian cũng như chi phí giao dịch và chi phí hỗ trợ cho shop của mình.

     Như đã nêu trên, MOBILE SHOP ONLINE là một shop bán điện thoại di dộng phong phú về mẫu mã, nhà cung cấp và kiểu dáng rất thuận lợi cho người dùng lựa chọn. Thông qua trang Web khách hàng có thể xem và đặt mua những “chú dế” phong cách, thời trang, cá tính hay đẳng cấp đang được bày bán tại đây. Với cách bố trí các mẫu mã điện thoại một cách khoa học, thân thiện, đồng thời luôn cập nhật những dòng máy mới, hy vọng trang web sẽ đưa đến cho người dùng những tiện ích khi sử dụng.

1.2.  The Current System

     Thương mại điện tử nói chung mà cụ thể là Website thực sự là một kênh kinh doanh mới, hiệu quả và rất kinh tế cho các doanh nghiệp ở Việt Nam. Nếu không có Website, doanh nghiệp sẽ bỏ lỡ rất nhiều cơ hội tốt bởi những khách hàng có tiềm năng trên thị trường.

      Với hệ thống hiện tại, khách hàng không được cung cấp đầy đủ thông tin một cách nhanh chóng và tiện lợi, cũng như sẽ không thể giải đáp thắc mắc của khách hàng nhanh chóng hiệu quả. Bên cạnh đó, để quảng bá cho shop cũng như cho những mẫu điện thoại mới, bạn sẽ phải mất chi phí cho marketing theo cách thức truyền thống như: chi phí in ấn, gửi tài liệu, chi phí liên lạc, nhân sự. Đối với những đơn đặt hàng qua điện thoại đôi khi vẫn xảy ra sự nhầm lẫn …

      MOBILE SHOP ONLINE sẽ giúp bạn tạo ra được tính chuyên nghiệp trong thời đại Toàn cầu hóa, kỹ thuật số, thông tin, kinh tế tri thức – bằng một Website ấn tượng, chuyên nghiệp với đầy đủ chức năng, thông tin, tiện ích để tạo được ấn tượng tốt đến cho khách hàng.

1.3. The Proposed System

 1.3.1. Mục đích của trang Web

- Cung cấp cho khách hàng những thông tin chi tiết về sản phẩm được bày bán trên shop, cũng như sẽ cập nhật những mẫu mã sản phẩm mới nhất đang có mặt trên thị trường.

- Quảng bá và bán các mẫu mã điện thoại mới và được ưa chuộng nhất. Khách hàng có thể đặt mua ngay trên trang Web.

- Khách hàng cũng có thể tham khảo thêm những phụ kiện kèm theo tương thích với những mẫu điện thoại, phù hợp với những nhu cầu cũng như lứa tuổi khác nhau.

- Ngoài ra khách hàng có thể tìm kiếm thêm những thông tin mới liên quan đến thế giới di động cũng như từng mẫu mã điện thoại có mặt trên thị trường, những thông tin về các chương trình khuyến mại khi mua hàng.

1.3.2. Chức năng của trang Web

- Đối với Guest : Khách hàng có thể xem, tìm kiếm những mẫu mã điện thoại cùng với  phụ kiện kèm theo luôn được cập nhật và nhận được những chương trình khuyến mại trên MOBILE SHOP ONLINE. Ngoài ra khách hàng có thể mua hàng, gửi những ý kiến đóng góp cho shop. Có thể đăng ký làm thành viên ( nếu muốn ).

- Đối với Admin : Quyền Admin quản lý các mặt hàng, nhóm hàng, hóa đơn, thành viên, thông tin phản hồi và thống kê các đơn đặt hàng theo địa bàn và theo thời gian. Không có quyền mua sản phẩm.

- Ngoài ra trang Web sẽ hỗ trợ khả năng tìm kiếm sản phẩm theo tên, hãng sản xuất  phụ kiện liên quan. Nâng cao chất lượng phục vụ khách hàng và giảm đáng kế các chi phí theo phương thức truyền thống.

1.4. Boundaries of the System

- Mặc dù có rất nhiều lý do hấp dẫn để kinh doanh trên Web như vậy, song bên cạnh đó     thương mại trực tuyến vẫn còn một số mặt hạn chế như :

- Sự bảo mật trên Internet không được bảo đảm, các thông tin tài chính có thể bị tiết lộ.

- Khách hàng có thể lo lắng về nguy cơ nhận được hàng kém chất lượng và lo lắng về các chính sách trả lại hàng của doanh nghiệp.

- Các hệ thống thanh toán tiền trực tuyến vẫn chưa phổ biến là gây ra sự khó khăn khi thanh toán, khách hàng sẽ phải đến tận nơi hoặc chuyển khoản cho doanh nghiệp.

- Không có sự nhất quán trong các luật thuế, cũng như các vấn đề về pháp lý.

- Thương mại điện tử đối với khách hàng vẫn còn là một hình thức mới mẻ và vẫn chưa phải là một phần không thể thiếu trong cuộc sống.

- Hầu hết những mặt hạn chế trong việc mua bán trên Web bắt nguồn từ nguyên nhân lĩnh vực thương mại điện tử còn khá mới mẻ. Cũng như đối với các công nghệ mới khác, nó cần thời gian để không chỉ phát triển công nghệ mà còn phát triển kinh nghiệm, chuyên môn, và văn hóa để sử dụng nó.

1.5. Hardware and Software Requirements

1.5.1. Minimum Requirements

 
 
Server
 
 
Client
 
 
Hardware
 
- Ram 1 GB or more
- CPU 2.0GHZ Xeon or more
- HDD 40GB or more
- Connect Internet and LAN
 
 
- Ram 128 MB or more
- CPU 1.5 GHZ or more
- Connnect Internet
- HDD 20 GB or more
 
 
Software
 
- Windows Server 2000/Linux
- MySQL, PHP
- IIS/Apache
 
 
Windows  7 or later.
- Chrome
- IE 9.0 or Later
- Firefox
- Opera
- Safari
 

1.5.2. Recommended Requirements:

 
 
Server
 
 
Client
 
 
Hardware
 
-  Ram 2 GB or more
-  CPU 2.4 GHZ Xeon or more
-  HDD 80 GB or more
-  Connect Internet and LAN
 
 
-  Ram 1 GB or more
-  CPU 2.0 MHZ or more
-  Connnect Internet and LAN
-  HDD 40 GB or more
 
 
Software
 
-  Windows Server 2003/ Linux
-  MySQL, PHP
-  IIS/Apache
-  Open Port: 8888, 3306
 
 
- Windows 7 or later
- Chrome
- IE 9.0 or Later
- Firefox
- Opera
- Safari

2. Customer Requirements Specification

2.1. Users of the System

2.1.1. Với  Guest:

_  Có quyền xem, tìm kiếm sản phẩm.

_  Có thể phản hồi thông tin.

_  Có thể lựa chọn và đưa sản phẩm vào giỏ hàng.

_  Đăng ký làm thành viên (nếu muốn).

2.1.2. Với  Member:

_  Có quyền xem, tìm kiếm sản phẩm.

_  Có quyền phản hồi thông tin.

_  Có quyền bình luận sản phẩm

_  Được hưởng những chương trình khuyến mại của shop nếu có

_  Mua hàng

_  Đăng nhập

_ Thay đổi mật khẩu

_ Thay đổi thông tin cá nhân.

2.1.3. Với Admin:

_   Cập nhật thông tin thường xuyên.

_   Quản lý, hỗ trợ khách hàng.

_   Quản lý hóa đơn, sản phẩm.

_   Tổng hợp thông tin phản hồi của khách hàng.

2.2. System functions

2.2.1. Với Guest:

_ Xem sản phẩm :
Description
Khách hàng có thể xem chi tiết về sản phẩm.
Input
Lựa chọn sản phẩm cần xem.
Process
Tìm kiếm trong CSDL.
Output
Hiển thị thông tin về sản phẩm mà khách hàng muốn xem.

Tìm kiếm :

Description
Khách hàng có thể tìm kiếm sản phẩm bằng những form tìm kiếm được xây dựng sẵn trên Website.
Input
Khách hàng nhập từ khóa tìm kiếm.
Process
Hệ thống sẽ ghi nhận và thực hiện tìm kiếm trong CSDL tất cả sản phẩm có chứa từ khóa khách hàng muốn tìm.
Output
Hiển thị thông tin sản phẩm khách hàng tìm kiếm.

Lựa chọn sản phẩm cần mua :

Description
Khách hàng có thể lựa chọn sản phẩm bất kỳ vào giỏ hàng.
Input
Lựa chọn sản phẩm cần mua.
Process
-          Kiểm tra sản phẩm có trong giỏ hàng.
-          Nếu giỏ hàng đã có sản phẩm thì tăng lên “ +1 ”, nếu chưa có thì          Hiển thị tiếp sản phẩm đang chọn vào giỏ hàng.
Output
Hiển thị thông tin về giỏ hàng mà khách hàng đã lựa chọn.

Đăng ký thành viên :

Description
Khách vãng lai có thể đăng ký làm thành viên thông qua một form được xây dựng sẵn.
Input
Đưa vào các thông tin cá nhân như User, Passwors, Số điện thoại, Câu hỏi bí mật, Địa chỉ Email …
Process
-          Kiểm tra User không được trùng lặp.
-          Mật khẩu phải có ít nhất 6 ký tự trở lên.
-          Kiểm tra định dạng Email và không được trùng lặp.
 
-          Thêm mới các thông tin khách hàng, mã hóa Password MD5 vào CSDL nếu đúng, nếu không yêu cầu nhập lại.
Output
Thông báo tới khách hàng việc đăng ký thành công hoặc trở về trang đăng ký nếu báo lỗi.

2.2.2. Với Member:

_ Member có đầy đủ các quyền của Guest. Ngoài ra Member còn có các quyền sau:

Đăng nhập:
Description
Đăng nhập vào Website với User và Password đã đăng ký.
Input
Nhập :
-          User.
-          Password.
Process
Truy xuất kiểm tra tính chính xác của dữ liệu được cung cấp trong CSDL.
Output
Hiển thị thông báo đăng nhập thành công hoặc lỗi – phải đăng nhập lại.

Đăng xuất :

Description
Đăng xuất khỏi Website.
Input
Click vào button “ Đăng xuất ” trên Website.
Process
-          Hủy toàn bộ session của người dùng hiện tại.
-          Đưa trở về chức năng dành cho Guest.
Output
Đưa về trạng thái là Guest.

_  Thay đổi mật khẩu:

Description
Khách hàng có thể thay đổi mật khẩu của mình.
Input
-          Nhập mật khẩu cũ.
-          Nhập mật khẩu mới.
-          Xác nhận mật khẩu mới muốn đổi.
Process
-          Kiểm tra tính chính xác của mật khẩu cũ.
-          Nếu đúng thì mã hóa và cập nhật mật khẩu mới vào CSDL.
-          Nếu sai yêu cầu nhập lại.
Output
-          Hiển thị thông  báo thay đổi mật khẩu thành công nếu đúng.
-          Hiển thị thông  báo yêu cầu nhập lại nếu có lỗi.

_  Thay đổi thông tin cá nhân:

Description
Khách hàng sau khi đăng nhập có thể thay đổi thông tin cá nhân thông qua form “ Cập nhật thông tin khách hàng ” bằng cách Click vào link cập nhật thông tin.
Input
Đăng nhập Website để thay đổi các thông tin cá nhân như họ, tên, địa chỉ, số điện thoại, …
Process
-          Kiểm tra thông tin thay đổi có hợp lệ không.
-          Nếu đúng sẽ cập nhập lại các thông tin mới của khách hàng vào CSDL.
-          Nếu sai quay trở lại form cập nhật.
Output
-          Hiển thị thông báo cập nhật hoàn tất nếu thành công.
-          Quay trở lại trang cập nhật thông tin nếu có lỗi.

_ Quên mật khẩu :

Description
Khách hàng có thể nhận mật khẩu mới thông qua mail kích hoạt từ admin trong trường hợp quên mật khẩu cũ.
Input
Yêu cầu người sử dụng nhập vào Email đã đăng ký.
Process
-          Hệ thống sẽ kiểm xem Email đó có tồn tại trong CSDL.
-          Hệ thống random tự động tạo mật khẩu, rồi gửi mật khẩu mới vào mail đã đăng ký.
Output
-          Thông báo thành công và có thể đăng nhập vào Website bằng mật khẩu mới .
-          Thông báo lỗi và quay lại form quên mật khẩu nếu cập nhật thất bại.

_  Mua hàng :

Description
Khách hàng có thể đặt mua hàng sau khi đã lựa chọn được sản phẩm ưng ý. Click nút “Thanh toán” để bắt đầu làm thủ tục mua hàng.
Input
Nhập các thông tin: Tên người mua, địa chỉ, điện thoại, email, ngày giao, ghichu, phương thức thanh toán, phương thức vận chuyển…
Process
+ Kiểm tra thông tin đăng ký đặt hàng của khách hàng:
-          Nếu chưa đăng nhập thì yêu cầu Đăng Nhập hoặc Đăng Ký.
-          Nếu bạn đã Đăng nhập thì chuyển sang form đặt hàng.
+ Thêm mới và cập nhật đơn hàng vào CSDL.
Output
Thông báo các sản phẩm đã được đặt mua thành công hoặc chưa thành công.

Gửi Feedback :

Description
Thành viên có thể gửi ý kiến phản hổi tới Admin.
Input
Nhập vào tiêu đề và nội dung ý kiến của mình bằng form được thiết kế sẵn.
Process
-          Kiểm tra thông tin nhập vào form hợp lệ chưa.
-          Thêm mới thông tin góp ý, phản hồi của khách hàng vào CSDL.
Output
-          Thông báo tới khách hàng việc gửi ý kiến phản hồi đã hoàn tất hoặc thất bại..

2.2.3. Với Admin:

Quyền Admin có thể:

_  Đăng nhập quản trị :

Description
Admin đăng nhập vào hệ thống bằng User và Password vào form được xây dựng sẵn.
Input
Nhập :
-          User.
-          Password.
Process
Truy xuất kiểm tra tính chính xác của dữ liệu được cung cấp trong CSDL.
Output
-          Chuyển đến trang quản trị nếu đăng nhập thành công.
-          Quay lại trang đăng nhập nếu thất bại.

_  Thay đổi mật khẩu :

Description
Admin sau khi đăng nhập có thể thay đổi mật khẩu
Input
Nhập Mật khẩu mới qua form yêu cầu
Process
-          Kiểm tra thông tin nhập vào có hơp lệ hay không.
-          Kết nối đến CSDL, cập nhật lại mật khẩu Admin.
Output
Chuyển đến trang đăng nhập nếu cập nhật thành công.

_  Quản lý tài khoản khách hàng :

Description
Admin có quyền xem thông tin hoặc khóa/ kích hoạt, xóa tài khoản của thành viên.
Input
Chọn lệnh tương ứng của tài khoản cần tương tác.
Process
+ Xem thông tin tài khoản :
-          Hiển thị thông tin khách hàng và không được phép sửa thông tin.
+ Sửa, Xóa tài khoản:Kiểm tra xem khách hàng đã mua chưa thì.Nếu chưa thì có thể xóa cùng các feedback liên quan.
+ Khóa/ kích hoạt tài khoản :
-          Admin có quyền khóa/ kích hoạt tài khoản của thành viên.
Output
Hiện thông báo thành công hoặc lỗi.

_  Quản lý sản phẩm :

Description
Admin có quyền thêm-sửa-xóa-ẩn-hiện các sản phẩm.
Input
Chọn và sử dụng công cụ được xây dựng sẵn để quản lý sản phẩm
Process
+ Thêm :
-          Kiểm tra tính hợp lệ của dữ liệu nhập vào.
-          Thêm mới vào CSDL.
+ Sửa : Cho phép sửa thông tin về sản phẩm và cập nhật vào CSDL.
+ Xóa :
-          Nếu sản phẩm có trong hóa đơn thì không được xóa.
-          Nếu sản phẩm chưa có trong bất kỳ hóa đơn nào thì có thể xóa (kèm các bình luận nếu có), và cập nhật vào CSDL.
+ Ẩn/ hiện : Cho phép ẩn hoặc hiện sản phẩm để trình bày trên giao diện người dung và cập nhật vào CSDL.
Output
Hiện thông báo thành công hoặc lỗi.

_  Quản lý hóa đơn :

Description
Admin có thể xem hoặc xóa hoặc cập nhật trạng thái hóa đơn.
Input
Chọn công cụ được xây dựng sẵn để xem hoặc xóa hoặc cập nhật trạng thái hóa đơn.
Process
+ Xem : Hiển thị tất cả hóa đơn.
+ Xóa :
-          Chỉ được phép xóa các hóa đơn chưa xử lý.
-          Các hóa đơn đang xử lý hoặc đã xử lý thì không được phép xóa.
+ Cập nhật trạng thái :
-          Hóa đơn chưa xử lý chỉ được cập nhật thành hóa đơn đang xử lý.
-          Hóa đơn đang xử lý có thể được cập nhật thành chưa xử lý hoặc đã xử lý xong.
-          Hóa đơn đã xử lý không được thay đổi trạng thái.
Output
Thông báo cập nhật thành công hoặc lỗi.

_  Quản lý tin tức :

Description
Admin có quyền thêm/ sửa/ xóa hoặc ẩn/ hiện tin tức.
Input
Chọn chức năng thêm/sửa /xóa hoặc ẩn/ hiện tin tức.
Process
+ Thêm tin tức : Thêm tiêu đề, nội dung, hình ảnh … tin tức và lưu vào CSDL.
+ Sửa tin tức : Sửa tiêu đề, nội dung, hình ảnh … tin tức và cập nhật vào CSDL.
+ Xóa tin tức : Xóa tiêu đề, nội dung, hình ảnh … tin tức và cập nhật vào CSDL.
+ Ẩn/ hiện tin tức : Ẩn hoặc hiện tin tức trên giao diện người dùng.
Output
Hiển thị thông báo thành công hoặc lỗi.

_  Quản lý Feedback :

Description
Admin có thể xem – xóa - ẩn/ hiện ý kiến, phản hồi của Guest.
Input
Chọn chức năng xem – xóa - ẩn/ hiện bình luận của Guest.
Process
+ Xem : Hiển thị tiêu đề và nội dung bình luận của Guest.
+ Xóa :
-          Yêu cầu xác nhận xóa.
-          Xóa toàn bộ nội dung và tiêu đề bình luận.
+ Ẩn/ hiện : Admin có quyền ẩn/ hiện bình luận của Guest.
Output
Hiển thị thông báo thành công hoặc lỗi.

_  Xem thống kê :

Description
Admin có thể xem thống kê về hóa đơn hoặc khách hàng.
Input
Chọn mục thống kê muốn xem bằng các công cụ được xây dựng sẵn.
Process
+ Xem hóa đơn : Liệt kê hóa đơn hoặc đang xử lý, hoặc chưa xử lý, hoặc đã xử lý.
+ Xem danh sách khách hàng : Liệt kê danh sách khách hàng bị khóa hoặc không bị khóa.
Output
-          Hiển thị các hóa đơn hoặc chưa thanh toán hoặc đã thanh toán.
-          Hiển thị danh sách thành viên bị khóa hoặc thành viên không bị khóa.

3. System Designs

3.1. Entity Relationship Diagram

Thuộc tính của các thực thể:

+ Thực thể Quản trị:

+ Thực thể Phản hồi:

+ Thực thể Hóa đơn:

+ Thực thể Khách hàng:

+ Thực thể Sản phẩm:

+ Thực thể Nhóm sản phẩm:

+ Thực thể Quảng cáo:

+ Thực thể Thanh toán:

+ Thực thể Vận chuyển:

+ Thực thể Hãng sản xuất:

3.2. Database Design

3.2.1. Table QuanTri:

 
Tính chất
 
 
Tên trường
 
Kiểu dữ liệu
 
Kích cỡ
 
Chú thích
Primary key
TaiKhoan
varchar
20
Tài khoản
Quản Trị
 
 
MatKhau
varchar
32
Mật khẩu

3.2.2. Table KhachHang:

 
Tính chất
 
Tên trường
Kiểu dữ liệu
Kích cỡ
Chú thích
Primary key
Auto-Increment
MaKhachHang
int
 
 
Mã khách hàng
 
 
TaiKhoan
varchar
25
Tài khoản
khách hàng
(unique)
 
 
MatKhau
varchar
32
Mật khẩu
 
 
Email
varchar
30
Email
 
 
TenKhachHang
varchar
30
Tên khách hàng
 
 
DienThoai
varchar
15
Điện thoại
 
 
DiaChi
varchar
150
Địa chỉ
 
 
TrangThai
tinyint
 
Trạng thái

3.2.3. Table HoaDon:

Tính chất
Tên trường
Kiểu dữ liệu
Kích cỡ
Chú thích
Primary key
Auto-Increment
MaHoaDon
int
 
 
Mã hóa đơn
Foreign key
MaThanhToan
int
 
 
Tham chiếu đến ThanhToan
Foreign key
MaKhachHang
int
 
 
Tham chiếu đến KhachHang
Foreign key
MaVanChuyen
int
 
 
Tham chiếu đến VanChuyen
 
 
NgayMuaHang
date
 
 
Ngày mua hàng
 
 
NgayGiaoHang
date
 
 
Ngày giao hàng
 
 
TrangThai
tinyint
 
 
Trạng thái hóa đơn: 1-Chưa xử lý;
2-Đang xử lý;
3-Đã xử lý
 
 
Tennguoinhan
varchar
30
Tên người nhận
 
 
DiaChi
varchar
100
Địa chỉ
người nhận
 
DienThoai
varchar
15
Điện thoại
người nhận
 
Email
varchar
30
Email người nhận
 
GhiChu
varchar
255
Ghi chú

3.2.4. Table PhanHoi:

 
Tính chất
 
 
Tên trường
 
Kiểu dữ liệu
 
Kích cỡ
 
Chú thích
Primary key
Auto-Increment
MaPhanHoi
int
 
 
Mã phản hồi
Foreign key
MaKhachHang
int
 
 
Tham chiếu đến KhachHang
 
 
NgayPhanHoi
int
 
 
Ngày gửi phản hồi
 
 
TieuDe
varchar
50
Tiêu đề
 
 
NoiDung
text
 
 
Nội dung
 
 
TraLoiPhanHoi
text
 
 
Trả lời phản hồi
 
TrangThai
tinyint
 
Trạng thái trả lời phản hồi
(1: rồi; 0: chưa)

3.2.5. Table NhomSanPham:

 
Tính chất
 
Tên trường
Kiểu dữ liệu
Kích cỡ
Chú thích
Primary key
Auto-Increment
MaNhomSanPham
int
 
 
Mã nhóm sản phẩm
 
 
TenNhom
varchar
50
Tên nhóm sản phẩm
 
 
TrangThai
tinyint
 
Trạng thái nhóm sản phẩm

3.2.6. Table HangSanXuat:

 
Tính chất
 
Tên trường
Kiểu dữ liệu
Kích cỡ
Chú thích
Primary key
Auto-Increment
MaHang
int
 
Mã hãng sản xuất
 
TenHang
varchar
50
Tên hãng sản xuất
 
TrangThai
tinyint
 
0-Ẩn;
1-Hiện

3.2.7. Table SanPham:

 
Tính chất
 
Tên trường
Kiểu dữ liệu
Kích cỡ
Chú thích
Primary key
Auto-Increment
MaSanPham
int
 
 
Mã sản phẩm
Foreign key
MaNhomSanPham
int
 
 
Tham chiếu đến NhomSanPham
Foreign key
MaHang
int
 
 
Tham chiếu đến HangSanXuat
 
 
NgayNhap
date
 
 
Ngày nhập sản phẩm
 
 
TenSanPham
varchar
50
Tên sản phẩm
 
 
MoTa
varchar
255
Mô tả sản phẩm
 
 
SoLuong
int
 
 
Số lượng sản phẩm
 
 
GiaSanPham
int
 
 
Giá sản phẩm
 
 
HinhAnh
varchar
200
Tên hình ảnh
 
 
TrangThai
int
 
 
Trạng thái sản phẩm

3.2.8.Table QuangCao:

 
Tính chất
 
Tên trường
Kiểu dữ liệu
Kích cỡ
Chú thích
Primary key
Auto-Increment
MaQuangCao
int
 
 
Mã quảng cáo
 
 
HinhAnh
varchar
50
Tên hình ảnh
 
 
DuongDan
varchar
50
Đường dẫn hình ảnh
 
 
ViTri
int
 
 
Vị trí banner
 
 
TrangThai
tinyint
 
 
Trạng thái quảng cáo

3.2.9. Table ThanhToan:

 
Tính chất
 
Tên trường
Kiểu dữ liệu
Kích cỡ
Chú thích
Primary key
Auto-Increment
MaThanhToan
int
 
Mã thanh toán
 
 
HinhThucThanhToan
varchar
50
Tên hình thức thanh toán
 
TrangThai
tinyint
 
0: Ẩn
1: Hiện

3.2.10. Table VanChuyen:

 
Tính chất
 
Tên trường
Kiểu dữ liệu
Kích cỡ
Chú thích
Primary key
Auto-Increment
MaVanChuyen
int
 
Mã chuyên mục
 
 
HinhThucVanChuyen
varchar
50
Tên chuyên mục
 
TrangThai
tinyint
 
0: Ẩn
1: Hiện

3.2.11. Table ChiTietHoaDon:

 
Tính chất
 
 
Tên trường
 
Kiểu dữ liệu
 
Kích cỡ
 
Chú thích
Primary key
Foreign key
MaSanPham
int
 
Tham chiếu đến MaSanPham
Foreign key
MaHoaDon
int
 
Tham chiếu đến MaHoaDon
 
 
SoLuong
int
 
Số lượng sản phẩm đặt mua
 
 
GiaSanPham
int
 
Giá sản phẩm tại thời điểm mua

3.2.12. Table Binhluan:

 
Tính chất
 
 
Tên trường
 
Kiểu dữ liệu
 
Kích cỡ
 
Chú thích
Primary key
Auto-Increment
MaBinhLuan
int
 
Mã bình luận
Foreign key
MaKhach
int
 
Tham chiếu đến bảng Khach
Foreign key
MaSanPham
int
 
Tham chiếu đến bảng SanPham
 
 
Ngaygui
date
 
Ngày gửi bình luận
 
 
Noidung
varchar
500
Nội dung bình luận
 
Trangthai
tinyint
1
Trạng thái bình luận

Mối quan hệ giứa các bảng:


3.3. Sitemap:

3.3.1. Guest:

3.3.2. Thành viên:

3.3.3. Admin :

 

3.4. Algorithms

3.4.1. Đăng ký:

3.4.2. Đăng nhập:

3.4.3. Tìm kiếm:

3.4.4. Thêm sản phẩm:

3.4.5. Thêm tin tức:

  

3.4.6. Phản hồi:

3.4.7. Thoát tài khoản người dùng:

4. Task Sheet

 
 
Tên lớp _ Tên nhóm
 
 
Tên Project
 
STT
 
Công việc
 
Tên thành viên tham gia
1
Viết DOC
 
…………………
2
-          Thiết kế cơ sở dữ liệu
-          Thiết kế giao diện website
-          Thiết kế giao diện phía máy chủ
-          Code thay mật khẩu Admin.
-          Code quản lý thành viên.
-          Code quản lý nhóm sản phẩm.
-          Code quản lý nhà sản xuất.
-          Code thêm, sửa, xoá sản phẩm
-          Code tìm kiếm phía User
-          Code quản lý thông tin phản hồi
-          Code quản lý hóa đơn.
-          Code quản lý tin tức
 
…………………
3
-          Thiết kế Slide trình bày
-          Code đăng ký, đăng nhập đăng xuất, quên mật khẩu, thay đổi mật khẩu của User
-          Code phần hiển thị sản phẩm phía User.
-          Nhập dữ liệu.
-          Cập nhập sẩn phẩm
 
…………………

5. Check List

5.1. Check List of Validation:

 
Option
 
Validate
Các trường form không được để chống?
yes
Dữ liệu nhập phù hợp?
yes
Tên đăng nhập khách hang là duy nhất
yes
Có sự dàng buộc giữa khách hàng,sản phẩm,Chi tiết thông số ,hóa đơn,phản hồi…. ?
 
 
yes

5.2. Submission Checklist:

STT
Particulars
Yes
No
NA
Comments
1
Tất cả các form đều hoạt động?
yes
 
 
 
2
Font  đều đúng chính tả?
yes
 
 
 
3
Các mầu đựơc sử dụng là mầu cơ bản, phổ biến?
yes
 
 
 
4
Các thành phần tạo nên form đều hoạt động?
yes
 
 
 
5
Dữ liệu vào sai có bị nhắc nhở?
yes
 
 
 

Hướng dẫn chuyển hướng từ HTTP sang HTTPS

Sau khi cài đặt xong SSL cho website chạy hosting Linux. Bạn muốn chuyển hướng mọi truy vấn vào website từ http thành https thì ta thêm đoạn sau vào file .htaccess:

RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R,L]

Với đoạn mã trên khi bạn truy cập vào link http://domain.com, mọi truy vấn sẽ được chuyển sang https://domain.com

Hướng dẫn upload ảnh và đưa vào bài viết với CKEditor

Một số câu hỏi khi phỏng vấn

1. See the following commands:

$a = "V1";
$a[10] = "Study";

What is result if you run this command:

echo $a;

2. How to get the different between 2 dateparts?

3. What is the output of those statements:

$a='a';
$b=$$a;
echo $b; //a

4. What is the output of those statements:

$a='V1';
$b=&$a;
echo $b; //V1

5. What is the output of those statements:

$a='V1';
$b=$$a;
echo $b; //Error

6. How to implement a package in Laravel?

7. What caching does Laravel use?

8. How to enable a long query in Laravel?

9. Do you know Git and Github?

10. Do you know Source Version Control?

11. Do you know about RESTful API?

12. Is the following query True or False:
Select * from Product where 1=?

13. What is the difference between the slice() function and the splice() function?

Hàm xử lý mảng

1. count()

Hàm count() dùng để đếm số phần tử trong mảng.

Ví dụ:

<?php
$a=[1,3,2,5,4];
echo count($a); //print: 5
?>

2. is_array()

Hàm is_array() dùng để kiểm tra một biến nào đó có phải là một mảng hay không, trả về 1 nếu là một mảng.

Ví dụ:

<?php
$a=[1,3,2,5,4];
echo is_array($a); //print: 1
?>

Bài 6. Vòng lặp while

Bài 7. Vòng lặp do-while

Cách dùng FTP/SFTP Package trong Sublime Text

Sublime Text là IDE phổ biến dùng để phát triển web. Có nhiều nhà phát triển đã sử dụng editor này.

Cách cài đặt SFTP Package

Nhấn tổ hợp phím ctrl+shift+P đối với Windows và Linux, và cmd+shift+P đối với macOS, sau đó soạn Package Control, rồi chọn Package Control: Install Package.

install-package

Soạn SFTP sẽ hiện ra gói SFTP, ta chọn gói này:

sftp

Sau khi chọn thì Sublime Text sẽ tự động cài cho ta.

Cách sử dụng SFTP Package

Bạn hãy chọn File->SFTP/FTP->Setup Server như hình dưới đây:

setup-server

Một file sẽ mở ra như hình dưới:

add-details

File này sẽ được lưu lại với tên sftp-config.json tại thư mục gốc của site.

Để upload file ta phím phải chuột vào file đó rồi chọn SFTP/FTP->Upload File.

upload-file

Để download file ta chọn SFTP/FTP->Download File.

Nguồn: https://artisansweb.net/use-ftpsftp-sublime-text/

Cách indent 2 dấu cách (space) trong Sublime Text

Bạn hãy mở: Preferences -> Settings - Syntax Specific

Sau đó điền đoạn sau vào phần {} :

"tab_size": 2,
"translate_tabs_to_spaces": true,
"detect_indentation": false

Bạn lưu lại rồi đóng cửa sổ sẽ được kết quả.