Cộng đồng chia sẻ tri thức Lib24.vn

Php nâng cao

c4dbd44cd4cfeded7545a3e5305533dd
Gửi bởi: Trường Cao Đẳng Cơ Điện Hà Nội 12 tháng 1 2022 lúc 15:59:50 | Được cập nhật: 13 giờ trước (18:03:50) | IP: 100.117.8.155 Kiểu file: DOCX | Lượt xem: 104 | Lượt Download: 1 | File size: 0.326844 Mb

Nội dung tài liệu

Tải xuống
Link tài liệu:
Tải xuống

Các tài liệu liên quan


Có thể bạn quan tâm


Thông tin tài liệu

Bài 1: Lập trình website theo mô hình MVC

Giới thiệu mô hình MVC

MVC là từ viết tắt bởi 3 từ Model – View – Controller. Đây là mô hình thiết kế sử dụng trong kỹ thuật phần mềm. Mô hình source code thành 3 phần, tương ứng mỗi từ. Mỗi từ tương ứng với một hoạt động tách biệt trong một mô hình.

Để hiểu rõ hơn, sau đây chúng ta sẽ cùng đi phân tích từng thành phần:

Thành phẩn của MVC.

Mô hình MVC và các thành phần bên trong của MVC.

Model (M):

Là bộ phận có chức năng lưu trữ toàn bộ dữ liệu của ứng dụng. Bộ phận này là một cầu nối giữa 2 thành phần bên dưới là View và Controller. Model thể hiện dưới hình thức là một cơ sở dữ liệu hoặc có khi chỉ đơn giản là một file XML bình thường. Model thể hiện rõ các thao tác với cơ sở dữ liệu như cho phép xem, truy xuất, xử lý dữ liệu,…

View (V):

Đây là phần giao diện (theme) dành cho người sử dụng. Nơi mà người dùng có thể lấy được thông tin dữ liệu của MVC thông qua các thao tác truy vấn như tìm kiếm hoặc sử dụng thông qua các website.

Thông thường, các ứng dụng web sử dụng MVC View như một phần của  hệ thống, nơi các thành phần HTML được tạo ra. Bên cạnh đó, View cũng có chức năng ghi nhận hoạt động của  người dùng để tương tác với Controller. Tuy nhiên, View không có mối quan hệ trực tiếp với Controller, cũng không được lấy dữ liệu từ Controller mà chỉ hiển thị yêu cầu chuyển cho Controller mà thôi.

Ví dụ: Nút “delete” được tạo bởi View khi người dùng nhấn vào nút đó sẽ có một hành động trong Controller.

Controller (C):

Bộ phận có nhiệm vụ xử lý các yêu cầu người dùng đưa đến thông qua view. Từ đó, C đưa ra dữ liệu phù hợp với người dùng. Bên cạnh đó, Controller còn có chức năng kết nối với model.

Luồng tương tác giữa các thành phần trong MVC.

Luồng tương tác giữa các thành phần trong MVC.

Ví dụ: Chức năng thêm bài viết mới trong trang quản trị website. Nơi đây có 2 trường nhập về tiêu đề và nội dung bài viết, thì trong đó:

  • View sẽ hiển thị ra phần nhập form tiêu đề và nội dung.

  • Controller lấy dữ liệu từ 2 trường và gửi tới Model.

  • Model lúc này sẽ nhận dữ liệu từ Controller để lưu trữ trong cơ sở dữ liệu.

Mỗi bộ phận thực hiện chức năng nhất định, nhưng chúng có sự thống nhất, liên kết với nhau tạo nên mô hình MVC. Mô hình này tương đối nhẹ. Nó có thể tích hợp được nhiều tính năng có trong ASP.NET hiện giờ. Ví dụ như authentication (quá trình xác thực).

Luồng đi trong mô hình MVC như thế nào?

Chúng ta có thể hình dung, khi  một yêu cầu từ máy client gửi tới server, Controller sẽ thực hiện nhiệm vụ của mình đó là tiếp nhận và xử lý yêu cầu. Trong trường hợp cần thiết, nó có thể liên hệ Model – bộ phận làm việc với database để hỗ trợ.

Khi xử lý xong yêu cầu, kết quả sẽ được trả về View. Tại View sẽ tạo mã HTML thành giao diện và trả về hiển thị trên trình duyệt.

Ưu điểm của mô hình MVC

Nhẹ, tiết kiệm băng thông: MVC không sử dụng viewstate nên khá tiết kiệm diện tích băng thông. Khi sử dụng, người dùng có thể sử dụng ứng dụng trên web cần tương tác gửi và nhận dữ liệu một cách liên tục. Do đó, việc giảm băng thông giúp cho website hoạt động tốt và ổn định hơn.

Ưu - nhược điểm của mô hình MVC.

  • Kiểm tra dễ dàng: Với MVC, bạn có thể dễ dàng kiểm tra, rà soát lỗi phần mềm trước khi tới tay người tiêu dùng, đảm bảo chất lượng và độ uy tín cao hơn.

  • Chức năng control: Trên các nền website thì ngôn ngữ lập trình như CSS, HTML, Javascript có một vai trò vô cùng quan trọng. Việc sử dụng mô hình MVC sẽ giúp bạn có một bộ control ưu việt trên nền tảng các ngôn ngữ hiện đại với nhiều hình thức khác nhau.

  • View và size: View sẽ là nơi lưu trữ các dữ liệu. Càng nhiều yêu cầu được thực hiện thì kích thước càng tệp càng lớn. Khi  đó, đường truyền mạng cũng giảm tốc độ load. Việc sử dụng mô hình MVC sẽ giúp bạn tiết kiệm được diện tích băng thông một cách tối ưu.

  • Chức năng Soc (Separation of Concern): Chức năng này cho phép bạn phân tách rõ ràng các phần như Model, giao diện, data, nghiệp vụ.

  • Tính kết hợp: Việc tích hợp ở mô hình MVC cho phép bạn thoải mái viết code trên nền tảng website. Khi đó, server của bạn sẽ được giảm tải khá nhiều.

  • Đơn giản: Đây là một mô hình với kết cấu tương đối đơn giản. Dù bạn không có quá nhiều chuyên môn cũng có thể sử dụng được.

Nhược điểm của mô hình MVC

MVC thường được sử dụng vào những  dự án lớn. Do đó, với các dự án nhỏ, mô hình MVC có thể gây cồng kềnh, tốn thời gian trong quá trình phát triển cũng như thời gian trung chuyển dữ liệu.

Ứng dụng mô hình MVC vào lập trình

Mô hình MVC được ứng dụng trong nhiều ngôn ngữ lập trình khác nhau, nhưng phổ biến nhất là ứng dụng ASP.NET MVC hay PHP MVC.

Ứng dụng mô hình MVC

MVC đang là mô hình được ứng dụng rất nhiều trong lập trình.

Hệ thống MVC phát triển tốt sẽ cho phép phát triển front – end, back – end cùng trên hệ thống mà không có sự can thiệp, chia sẻ, chỉnh sửa các tập tin trong khi một hoặc hai bên vẫn đang làm việc.

Việc sử dụng mô hình tương đối đơn giản. Chỉ cần hiểu rõ quy trình vận hành, nắm được các chức năng của từng bộ phận thì việc triển khai mô hình MVC tương đối dễ dàng.

Xây dựng chức năng đăng nhập bằng MVC

Phần này hướng dẫn tạo chức năng đăng nhập theo mô hình MVC.

Bước 1: Tạo một thư mục mới. Trong thư mục mới này, tạo 3 thư mục mới khác với tên controller, model, view tương ứng và cũng tạo một trang PHP với tên index.php.

  • new folder

                  –  controller
                  –  model

                  –  view
                  –  index.php

Bước 2: Trong thư mục controller, tạo một trang PHP với tên Controller và viết đoạn mã sau:

<?php

include_once(“model/Model.php”);

class Controller {

public $model;

public function __construct()

    {

        $this->model = new Model();

    }

public function invoke()

{

$reslt = $this->model->getlogin();     // gọi hàm getlogin() của lớp model và lưu giá trị trả về của hàm này vào biến reslt.

if($reslt == ‘login’)

{

include ‘view/Afterlogin.php’;

}

else

{

include ‘view/login.php’;

}

}

}

?>

Bước 3: Trong thư mục model, tạo một trang PHP với tên Model và viết đoạn mã sau:

<?php

include_once(“model/Book.php”);

class Model {

public function getlogin()

{

if(isset($_REQUEST[‘username’]) && isset($_REQUEST[‘password’])){

if($_REQUEST[‘username’]==’admin’ && $_REQUEST[‘password’]==’admin’){

return ‘login’;

}

                    else{

return ‘invalid user’;

}

}

}

}

?>

Bước 4: Trong thư mục view, tạo hai trang PHP với tên lần lượt là login.php, Afterlogin.php và viết đoạn mã sau:

login.php

<>

<head></head>

<div>

<?php

echo $reslt;

?>

<form action=”” method=”POST”>

<p>

<label>Username</label>

<input id=”username” value=”” name=”username” type=”text” required=”required” /><br>

</p>

<p>

<label>Password</label>

<input id=”password” name=”password” type=”password” required=”required” />

</p>

   <br />

<p>

   <button type=”submit” name=”submit”><span>Login </span> </button>

<button type=”reset”><span>Cancle</span></button>

</p>

</form>

</div>

</>

 

Afterlogin.php

<>

<head></head>

<div>

<?php

echo $reslt;

?>

</div>

</>

Bước 5: Mở tệp index.php và viết mã sau:

<?php

include_once(“controller/Controller.php”);

$controller = new Controller();

$controller->invoke();

?>

Bài 2: Các kỹ thuật lập trình MySQL với PHP nâng cao

1. Kết nối và truy vấn cơ sở dữ liệu sử dụng PDO

Giới thiệu PDO - PHP Data Objects

PHP Data Objects (PDO) là một lớp truy xuất cơ sở dữ liệu cung cấp một phương pháp thống nhất để làm việc với nhiều loại cơ sở dữ liệu khác nhau. Khi làm việc với PDO bạn sẽ không cần phải viết các câu lệnh SQL cụ thể mà chỉ sử dụng các phương thức mà PDO cung cấp, giúp tiết kiệm thời gian và làm cho việc chuyển đổi Hệ quản trị cơ sở dữ liệu trở nên dễ dàng hơn, chỉ đơn giản là thay đổi Connection String (chuỗi kết nối CSDL).

Chúng ta chỉ cần nắm rõ API mà PDO cung cấp là có thể làm việc được với nhiều Hệ quản trị cơ sở dữ liệu khác nhau như MySQL, SQLite, PostgreSQL, Microsoft SQL Server,... và có thể dễ dàng chuyển đổi chúng.

Các Hệ quản trị cơ sở dữ liệu (Database Management System) mà PDO hỗ trợ gồm có:

Tên driver DBMS
PDO_CUBRID Cubrid
PDO_DBLIB FreeTDS Microsoft SQL Server / Sybase
PDO_FIREBIRD Firebird
PDO_IBM IBM DB2
PDO_INFORMIX IBM Informix Dynamic Server
PDO_MYSQL MySQL 3.x/4.x/5.x
PDO_OCI Oracle Call Interface
PDO_ODBC ODBC v3 (IBM DB2, unixODBC and win32 ODBC)
PDO_PGSQL PostgreSQL
PDO_SQLITE SQLite 3 and SQLite 2
PDO_SQLSRV Microsoft SQL Server / SQL Azure
PDO_4D 4D

Kết nối cơ sở dữ liệu

Mỗi DBMS sẽ có các phương thức kết nối khác nhau (có loại cần Username, Password, đường dẫn đới Database, Port, có loại không). Connection String của các DBMS phổ biến hầu hết đều có dạng như sau:

$conn = new PDO('mysql:host=localhost;dbname=izlearn', $username, $password);

Với mysql là tên của DBMS, localhost có ý nghĩa database được đặt trên cùng server, izlearn là tên của database. $username và $password là 2 biến chứa thông tin xác thực.

Đối với SQLite, DBMS này không có cơ chế xác thực bằng Username và Password mà chỉ đơn giản là đường dẫn tới file dữ liệu:

$conn = new PDO("sqlite:your/database/path/izlearn.db");

Đế ngắt kết nối khi không cần thao tác với database nữa, chúng ta chỉ cần sét biến $conn về null;

$conn = null;

Insert và Update

Thêm mới (insert) và cập nhật (update) dữ liệu là những hoạt động cơ bản khi thao tác với database. Với PDO, mỗi hoạt động insert hay update được thực hiện qua 3 quá trình sử dụng cơ chế Prepared Statement

  • Prepare statement: Chuẩn bị một câu lệnh SQL làm khung/mẫu được gọi là Prepared Statement với các Placeholder (có thể hiểu placeholder đóng vai trò như tham số của các phương thức khi bạn khai báo hàm)

  • Bind params: Gắn giá trị thực vào các placeholder (tương tự như khi bạn truyền giá trị vào các tham số của phương thức)

  • Execute: Thực thi câu lệnh.

Prepared Statement

Có 2 loại Placeholder trong Prepared Statement là Placeholder không định danh (Unnamed Placeholder) và Placeholder định danh (Named Placeholder) như ví dụ sau:

$stmt = $conn->prepare('INSERT INTO users (name, email, age) values (?, ?, ?)');

$stmt = $conn->prepare('INSERT INTO users (name, email, age) values (:name, :mail, :age)');

Dòng lệnh thứ nhất sử dụng Placeholder không định danh là các dấu hỏi - ?. Dòng lệnh thứ 2 sử dụng Placeholder định danh: :name, :mail, :age (lưu ý dấu hai chấm và placeholder không nhất thiết phải giống tên column). Sau đây là toàn bộ quá trình Insert và Update sử dụng 2 loại Placeholder nêu trên.

Unnamed Placeholder

//Khởi tạo Prepared Statement từ biến $conn ở phần trước

$stmt = $conn->prepare('INSERT INTO users (name, email, age) values (?, ?, ?)');

//Gán các biến (lúc này chưa mang giá trị) vào các placeholder theo thứ tự tương ứng

$stmt->bindParam(1, $name);

$stmt->bindParam(2, $mail);

$stmt->bindParam(3, $age);

//Gán giá trị và thực thi

$name = "Vu Hoang Lam"<

$mail = "[email protected]";

$age = 22;

$stmt->execute();

//Gán những giá trị khác và tiếp tục thực thi

$name = "Nguyen Van A";

$mail = "[email protected]";

$age = 23;

$stmt->execute();

Như chúng ta thấy ta chỉ cần khởi tạo Prepared Statement một lần và có thể sử dụng lại nhiều lần. Với mỗi column - placeholder ta phải thực hiện gán tham số một lần, điều này sẽ không sao với những table có ít column như ví dụ trên, nhưng sẽ rất bất tiện nếu bảng có nhiều table, rất may mắn ta có cách khác để làm việc này, đó là lưu toàn bộ giá trị vào trong một mảng và truyền mảng này vào phương thức execute(), cụ thể như sau:

$stmt = $conn->prepare('INSERT INTO users (name, email, age) values (?, ?, ?)');

$data = array('Vu Hoang Lam', '[email protected]', 22);

//Phương thức execute() dưới đây sẽ gán lần lượt giá trị trong mảng vào các Placeholder theo thứ tự

$stmt->execute($data);

Named Placeholder

Đối với Named Placeholder, cách thực hiện cũng khá tương đồng với Unnamed Placeholder, chỉ khác là chúng ta không dùng thứ tự placeholder để gán giá trị (bind) mà dùng chính tên của placeholder:

//Khởi tạo Prepared Statement từ biến $conn ở phần trước

$stmt = $conn->prepare('INSERT INTO users (name, email, age) values (:name, :mail, :age)');

//Gán các biến (lúc này chưa mang giá trị) vào các placeholder theo tên của chúng

$stmt->bindParam(':name', $name);

$stmt->bindParam(':mail', $mail);

$stmt->bindParam(':age', $age);

//Gán giá trị và thực thi

$name = "Vu Hoang Lam";

$mail = "[email protected]";

$age = 22;

$stmt->execute();

Chúng ta cũng có thể sử dụng mảng để rút gọn:

//Lưu ý: Không cần thiết phải sử dụng dấu hai chấm cho các key

$data = array('name' => 'Vu Hoang Lam', 'mail' => '[email protected]', 'age' => 22);

Một mẹo hữu ích khác khi sử dụng Named Placeholder đó là insert Object

class $user

{

public $name;

public $mail;

public $age;

}

$person = new $user();

$person->name = 'Vu Hoang Lam';

$person->mail = '[email protected]';

$person->age = 22;

$stmt = $conn->prepare('INSERT INTO users (name, email, age) values (:name, :mail, :age)');

$stmt->execute((array)$person);

Ở dòng cuối cùng, chúng ta đã thực hiện "ép kiểu" (cast) Object $person thành array để truyền vào phương thức execute();

Việc sử dụng Prepared Statement sẽ giúp chúng ta tránh được SQL Injection.

Select Data - "Đọc" dữ liệu từ database

Khi đọc dữ liệu từ database, PDO sẽ trả về dữ liệu theo cấu trúc mảng (array) hoặc đối tượng (object) thông qua phương thức fetch(). Bạn nên thiết lập trước cấu trúc dữ liệu trước khi gọi phương thức này, PDO hỗ trợ các tuỳ chọn sau:

  • PDO::FETCH_ASSOC: Trả về dữ liệu dạng mảng với key là tên của column (column của các table trong database)

  • PDO::FETCH_BOTH (default): Trả về dữ liệu dạng mảng với key là tên của column và cả số thứ tự của column

  • PDO::FETCH_BOUND: Gán giá trị của từng column cho từng biến đã khởi tạo trước đó qua phương thức bindColumn()

  • PDO::FETCH_CLASS: Gán giá trị của từng column cho từng thuộc tính (property/attribute) của một lớp Class theo tên column và tên thuộc tính.

  • PDO::FETCH_INTO: Gán giá trị của từng column cho từng thuộc tính của một Class Instance (thể hiện của một lớp)

  • PDO::FETCH_LAZY: Gộp chung PDO::FETCH_BOTH/PDO::FETCH_OBJ

  • PDO::FETCH_NUM: Trả về dữ liệu dạng mảng với key là số thứ tự của column

  • PDO::FETCH_OBJ: Trả về một Object của stdClass (link is external) với tên thuộc tính của Object là tên của column.

Trong thực tế, chúng ta chỉ thường dùng 3 kiểu fetch đó là: FETCH_ASSOC, FETCH_CLASS và FETCH_OBJ. Để thiết lập cấu trúc dữ liệu (Fetch Style hay Fetch Mode) trước khi fetch ta dùng câu lệnh sau:

$stmt->setFetchMode(PDO::FETCH_ASSOC);

Hoặc nếu muốn bạn cũng có thể thiết lập kiểu fetch khi gọi hàm fetch():

$stmt->fetch(PDO::FETCH_ASSOC);

FETCH_ASSOC

Kiểu fetch này sẽ tạo ra một mảng kết hợp lập chỉ mục theo tên column (nghĩa là các key của mảng chính là tên của column), tương tự như khi ta dùng MySQL/MySQLi Extension.

//Tạo Prepared Statement

$stmt = $conn->prepare('SELECT email, age from users WHERE name = :name');

//Thiết lập kiểu dữ liệu trả về

$stmt->setFetchMode(PDO::FETCH_ASSOC);

//Gán giá trị và thực thi

$stmt->execute(array('name' => 'a'));

//Hiển thị kết quả, vòng lặp sau đây sẽ dừng lại khi đã duyệt qua toàn bộ kết quả

while($row = $stmt->fetch()) {

echo $row['name'] , '\n';

echo $row['email'] , '\n';

echo $row['age'] , '\n';

}

FETCH_OBJ

Kiểu fetch này trả về một Object của stdClass cho mỗi row của kết quả.

//Tạo Prepared Statement

$stmt = $conn->prepare('SELECT email, age from users WHERE name = :name');

//Thiết lập kiểu dữ liệu trả về

$stmt->setFetchMode(PDO::FETCH_OBJ);

//Gán giá trị và thực thi

$stmt->execute(array('name' => 'a'));

//Hiển thị kết quả, vòng lặp sau đây sẽ dừng lại khi đã duyệt qua toàn bộ kết quả trả về

while($row = $stmt->fetch()) {

echo $row->name , '\n';

echo $row->email , '\n';

echo $row->age , '\n';

}

FETCH_CLASS

Kiểu fetch này cho phép chúng ta đưa kết quả vào Object của một Class mà chúng ta chỉ định. Khi sử dụng FETCH_CLASS, thuộc tính của class sẽ được gán giá trị trước khi constructor của class đó được gọi (phải chú ý vì điều này rất quan trọng). Nếu không có thuộc tính khớp với tên của một column bất kỳ thì thuộc tính đó sẽ được tự động tạo ra (public).

Giả sử table users có một ta đã có Class User được định nghĩa như sau:

class User {

public $name;

public $email;

public $isAdmin = 'No';

function __construct() {

if ($this->name == 'Vu Hoang Lam')

$this->isAdmin = 'Yes';

}

}

Khi query data từ database sử dụng đoạn code sau:

//Tạo Prepared Statement

$stmt = $conn->prepare('SELECT email, age from users WHERE name = :name');

//Thiết lập kiểu dữ liệu trả về, chỉ định dữ liệu được đưa vào object của class User

$stmt->setFetchMode(PDO::FETCH_CLASS, 'User');

//Gán giá trị và thực thi

$stmt->execute(array('name' => 'a'));

//Hiển thị kết quả, vòng lặp sau đây sẽ dừng lại khi đã duyệt qua toàn bộ kết quả trả về

while($obj = $stmt->fetch()) {

echo $obj->email;

echo $obj->isAdmin;

}

Vì constructor được gọi sau khi thuộc tính $name được gán bằng Vu Hoang Lam nên isAdmin sẽ mang giá trị Yes. Nếu muốn constructor của class được gọi trước khi các thuộc tính được gán giá trị, chúng ta phải sử dụng thêm PDO::FETCH_PROPS_LATE. Cách sử dụng như sau:

//Hãy thử sử dụng kiểu fetch trên và so sánh kết quả hiển thị

$stmt->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'User');

Nếu cần truyền các tham số cho constructor của class thông qua phương thức fetch(), chúng ta có thể đặt chúng trong một array theo thứ tự tương ứng cụ thể như sau:

$stmt->setFetchMode(PDO::FETCH_CLASS, 'User', array('param1', 'param2', 'param3'));

Exceptions - Xử lý ngoại lệ

PDO dùng các Exceptions để xử lý các lỗi phát sinh khi làm việc với database, vì thế tất cả những gì chúng ta làm với PDO nên được đặt trong một try/catch block. PDO cung cấp 3 chế độ xử lý lỗi (Error Mode) được thiết lập thông qua phương thức setAttribute():

$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT );

$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );

$conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

PDO::ERRMODE_SILENT

Đây là chế độ xử lý lỗi mặc định của PDO, khi gặp mỗt lỗi bất kỳ, PDO sẽ im lặng (silent) và chương trình vẫn tiếp tục chạy. Chúng ta có thể lấy mã lỗi và thông tin về các lỗi đã xảy ra qua PDO::errorCode() và PDO::errorInfo()

PDO::ERRMODE_WARNING

Ở chế độ này khi gặp phải lỗi PDO sẽ ném ra một PHP Warning, chương trình sẽ tiếp tục chạy.

PDO::ERRMODE_EXCEPTION

Đây là mode mà chúng ta nên sử dụng nhất, khi đặt trong một try/catch block sẽ giúp bạn kiểm soát các lỗi phát sinh một cách uyển chuyển và giấu các thông báo lỗi có thể khiến Attacker khai thác hệ thống của bạn.

try {

$stmt = new PDO('mysql:host=localhost;dbname=izlearn', 'lamvh', 'talapassday');

$stmt->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

//Sai cú pháp, FORM thay vì FROM

$stmt->prepare('SELECT name FORM people');

}

catch(PDOException $e) {

echo "ERROR! Co loi xay ra voi PDO";

file_put_contents('PDOErrors.txt', $e->getMessage(), FILE_APPEND);

}

Đoạn code trên sẽ ghi thông báo lỗi vào một file text với tên PDOErrors.txt

Một số phương thức hữu ích khác

$conn->lastInsertId();

Phương thức trên trả về Auto Incremented ID của rows được thêm gần nhất.

$conn->exec('DELETE FROM users WHERE uid = 1');

Đối với các lệnh SQL không có dữ liệu trả về, và không cần thiết phải truyền tham số thì có thể sử dụng phương thức exec(). Phương thức này sẽ trả về số lượng row bị tác động sau khi thực hiện câu lệnh. Như ví dụ trên sẽ trả về số lượng row bị xoá.

$conn = $DBH->quote($foo);

Phương thức quote() sẽ giúp chúng ta thêm dấu nháy cho một string để string đó an toàn khi sử dụng để truy vấn, nếu chúng ta không muốn sử dụng Prepared Statement.

$stmt->rowCount();

Phương thức rowCount() trả về số lượng row bị tác động sau khi thực hiện các thao tác DELETE, INSERT và UPDATE. Dùng rowCount() cho thao tác SELECT có thể sẽ trả về kết quả không đúng với một số loại database.

Kết nối và truy vấn cơ sở dữ liệu sử dụng MySQLi

Mở kết nối tới MySQL

Ví dụ (MySQLi Hướng đối tượng)

<?php
$servername = "localhost";
$username = "username";
$password = "password";

// Tạo kết nối
$conn = new mysqli($servername, $username, $password);

// Kiểm tra kết nối
if ($conn->connect_error) {
  die("Lỗi kết nối: " . $conn->connect_error);
}
echo "Kết nối thành công";
?>

Ví dụ (MySQLi Thủ tục)

<?php
$servername = "localhost";
$username = "username";
$password = "password";

// Tạo kết nối
$conn = mysqli_connect($servername, $username, $password);

// Kiểm tra kết nối
if (!$conn) {
  die("Lỗi kết nối: " . mysqli_connect_error());
}
echo "Kết nối thành công";
?>

Đóng kết

Kết nối sẽ tự động đóng khi tập lệnh kết thúc. Để đóng kết nối trước đó, hãy sử dụng như sau:

MySQLi Hướng đối tượng:

$conn->close();

MySQLi Thủ tục:

mysqli_close($conn);

Insert dữ liệu

Sau khi cơ sở dữ liệu và bảng đã được tạo, chúng ta có thể bắt đầu thêm dữ liệu vào chúng.

Dưới đây là một số quy tắc cú pháp cần tuân theo:

  • Truy vấn SQL phải được đặt trong cặp dấu nháy (“”) bằng PHP

  • Giá trị chuỗi bên trong truy vấn SQL đặt trong cặp dấu nháy (“”)

  • Giá trị số không đặt trong cặp dấu nháy (“”)

  • Từ NULL đặt trong cặp dấu nháy (“”)

Câu lệnh INSERT INTO được sử dụng để thêm các bản ghi mới vào bảng MySQL:

INSERT INTO table_name (column1, column2, column3,...)
VALUES (value1, value2, value3,...)

Sau đây là ví dụ thêm một bản ghi mới vào bảng "MyGuests":

Ví dụ (MySQLi Hướng đối tượng)

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Tạo kết nối

$conn = new mysqli($servername, $username, $password, $dbname);
// Kiểm tra kết nối
if ($conn->connect_error) {
  die("Lỗi kết nối: " . $conn->connect_error);
}

$sql = "INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('John', 'Doe', '[email protected]')";

if ($conn->query($sql) === TRUE) {
  echo "Bản ghi mới đã được tạo thành công";
} else {
  echo "Lỗi: " . $sql . "<br>" . $conn->error;
}

$conn->close();
?>

Ví dụ (MySQLi Thủ tục)

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Tạo kết nối
$conn = mysqli_connect($servername, $username, $password, $dbname);
// Kiểm tra kết nối
if (!$conn) {
  die("Lỗi kết nối: " . mysqli_connect_error());
}

$sql = "INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('John', 'Doe', '[email protected]')";

if (mysqli_query($conn, $sql)) {
  echo "Thêm bản ghi mới thành công";
} else {
  echo "Lỗi: " . $sql . "<br>" . mysqli_error($conn);
}

mysqli_close($conn);
?>

Lấy ID của bản ghi được chèn sau

Nếu chúng ta thực hiện INSERT hoặc UPDATE trên bảng có trường AUTO_INCREMENT, chúng ta có thể nhận được ID của bản ghi được chèn/cập nhật lần cuối ngay lập tức.

Trong bảng "MyGuests", cột "id" là trường AUTO_INCREMENT:

CREATE TABLE MyGuests (
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
firstname VARCHAR(30) NOT NULL,
lastname VARCHAR(30) NOT NULL,
email VARCHAR(50),
reg_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)

The following examples are equal to the examples from the previous page (PHP Insert Data Into MySQL), except that we have added one single line of code to retrieve the ID of the last inserted record. We also echo the last inserted ID:

Các ví dụ sau tương đương với các ví dụ từ trước (Insert dữ liệu), ngoại trừ việc chúng ta thêm một dòng mã duy nhất để truy xuất ID của bản ghi được chèn cuối cùng. Chúng ta cũng lặp lại ID được chèn lần cuối:

Ví dụ (MySQLi Hướng đối tượng)

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Tạo kết nối
$conn = new mysqli($servername, $username, $password, $dbname);
// Kiểm tra kết nối
if ($conn->connect_error) {
  die("Lỗi kết nối: " . $conn->connect_error);
}

$sql = "INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('John', 'Doe', '[email protected]')";

if ($conn->query($sql) === TRUE) {
  $last_id = $conn->insert_id;
  echo "Bản ghi mới đã được tạo thành công. ID được chèn sau cùng là: " . $last_id;
} else {
  echo "Lỗi: " . $sql . "<br>" . $conn->error;
}

$conn->close();
?>

Example (MySQLi Procedural)

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Tạo kết nối

$conn = mysqli_connect($servername, $username, $password, $dbname);
// Kiểm tra kết nối
if (!$conn) {
  die("Lỗi kết nối: " . mysqli_connect_error());
}

$sql = "INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('John', 'Doe', '[email protected]')";

if (mysqli_query($conn, $sql)) {
  $last_id = mysqli_insert_id($conn);
  echo " Bản ghi mới đã được tạo thành công. ID được chèn sau cùng là: " . $last_id;
} else {
  echo "Lỗi: " . $sql . "<br>" . mysqli_error($conn);
}

mysqli_close($conn);
?>

Insert nhiều bản

Nhiều câu lệnh SQL phải được thực thi bằng hàm mysqli_multi_query().

Các ví dụ sau thêm ba bản ghi mới vào bảng "MyGuests":

Ví dụ (MySQLi Hướng đối tượng)

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Tạo kết nối
$conn = new mysqli($servername, $username, $password, $dbname);
// Kiểm tra kết nối
if ($conn->connect_error) {
  die("Lỗi kết nối: " . $conn->connect_error);
}

$sql = "INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('John', 'Doe', '[email protected]');";
$sql .= "INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('Mary', 'Moe', '[email protected]');";
$sql .= "INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('Julie', 'Dooley', '[email protected]')";

if ($conn->multi_query($sql) === TRUE) {
  echo "Thêm các bản ghi thành công";
} else {
  echo "Lỗi: " . $sql . "<br>" . $conn->error;
}

$conn->close();
?>

Ví dụ (MySQLi Thủ tục)

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Tạo kết nối
$conn = mysqli_connect($servername, $username, $password, $dbname);
// Kiểm tra kết nối
if (!$conn) {
  die("Lỗi kết nối: " . mysqli_connect_error());
}

$sql = "INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('John', 'Doe', '[email protected]');";
$sql .= "INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('Mary', 'Moe', '[email protected]');";
$sql .= "INSERT INTO MyGuests (firstname, lastname, email)
VALUES ('Julie', 'Dooley', '[email protected]')";

if (mysqli_multi_query($conn, $sql)) {
  echo "Thêm mới các bản ghi thành công";
} else {
  echo "Lỗi: " . $sql . "<br>" . mysqli_error($conn);
}

mysqli_close($conn);
?>

Câu lệnh Prepared và tham số Bound

Câu lệnh Prepared là một tính năng được sử dụng để thực thi các câu lệnh SQL giống nhau (hoặc tương tự) lặp đi lặp lại với hiệu quả cao.

Các câu lệnh Prepared về cơ bản hoạt động như sau:

  1. Prepared: Một mẫu câu lệnh SQL được tạo và gửi đến cơ sở dữ liệu. Các giá trị nhất định không được xác định, được gọi là tham số (có nhãn "?"). Ví dụ: INSERT INTO MyGuests VALUES (?,?,?)

  2. Cơ sở dữ liệu phân tích cú pháp, biên dịch và thực hiện tối ưu hóa truy vấn trên mẫu câu lệnh SQL và lưu trữ kết quả mà không cần thực thi nó

  3. Execute: Sau đó, ứng dụng liên kết các giá trị với các tham số và cơ sở dữ liệu thực thi câu lệnh. Ứng dụng có thể thực thi câu lệnh bao nhiêu lần tùy ý với các giá trị khác nhau

So với việc thực thi trực tiếp các câu lệnh SQL, các câu lệnh Prepared có ba ưu điểm chính:

  • Các câu lệnh Prepared giảm thời gian phân tích cú pháp vì việc chuẩn bị trên truy vấn chỉ được thực hiện một lần (mặc dù câu lệnh được thực hiện nhiều lần)

  • Tham số ràng buộc (Bound) giảm thiểu băng thông đến máy chủ vì chúng ta chỉ cần gửi các tham số mỗi lần, chứ không phải toàn bộ truy vấn

  • Các câu lệnh Prepared rất hữu ích để chống lại việc tấn công SQL, bởi vì các giá trị tham số, được truyền sau này bằng một giao thức khác, không cần phải được thoát một cách chính xác. Nếu mẫu câu lệnh ban đầu không có nguồn gốc từ đầu vào bên ngoài, thì không thể xảy ra chèn SQL.

Câu lệnh Prepared

Sau đây là ví dụ sử dụng câu lệnh prepared và tham số bound trong MySQLi:

Ví dụ

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Tạo kết nối

$conn = new mysqli($servername, $username, $password, $dbname);

// Kiểm tra kết nối
if ($conn->connect_error) {
  die("Lỗi kết nối: " . $conn->connect_error);
}

// prepare và bind
$stmt = $conn->prepare("INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)");
$stmt->bind_param("sss", $firstname, $lastname, $email);

// Thiết lập các tham số và thực thi
$firstname = "John";
$lastname = "Doe";
$email = "[email protected]";
$stmt->execute();

$firstname = "Mary";
$lastname = "Moe";
$email = "[email protected]";
$stmt->execute();

$firstname = "Julie";
$lastname = "Dooley";
$email = "[email protected]";
$stmt->execute();

echo "Các bản ghi đã được tạo";

$stmt->close();
$conn->close();
?>

Mô tả các dòng code từ ví dụ trên:

"INSERT INTO MyGuests (firstname, lastname, email) VALUES (?, ?, ?)"

Trong SQL của chúng ta, chúng ta chèn một dấu chấm hỏi (?) Mà chúng ta muốn thay thế bằng giá trị số nguyên, chuỗi, kép hoặc blob.

Sau đó, hãy xem hàm bind_param ():

$stmt->bind_param("sss", $firstname, $lastname, $email);

Hàm này liên kết các tham số với truy vấn SQL và cho cơ sở dữ liệu biết các tham số là gì. Đối số "sss" liệt kê các loại dữ liệu của các tham số. Ký tự s cho mysql biết rằng tham số là một chuỗi.

Đối số có thể là một trong bốn loại:

  • i - integer

  • d - double

  • s - string

  • b - BLOB

Chúng ta phải có một trong những thứ này cho mỗi tham số.

Bằng cách cho mysql biết loại dữ liệu mong đợi, chúng ta giảm thiểu nguy cơ bị tấn công SQL.

Select dữ liệu

Câu lệnh SELECT được sử dụng để lựa chọn dữ liệu từ một hoặc nhiều bảng:

SELECT column_name(s) FROM table_name

Hoặc chúng ta có thể sử dụng ký tự * để lựa chọn tất cả các cột của bảng:

SELECT * FROM table_name

Ví dụ sau đây chọn cột id, firstname và lastname từ bảng MyGuests và hiển thị nó trên trang:

Ví dụ (MySQLi Hướng đối tượng)

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Tạo kết nối
$conn = new mysqli($servername, $username, $password, $dbname);
// Kiểm tra kết nối
if ($conn->connect_error) {
  die("Lỗi kết nối: " . $conn->connect_error);
}

$sql = "SELECT id, firstname, lastname FROM MyGuests";
$result = $conn->query($sql);

if ($result->num_rows > 0) {
  // Hiển thị dữ liệu
  while($row = $result->fetch_assoc()) {
    echo "id: " . $row["id"]. " - Name: " . $row["firstname"]. " " . $row["lastname"]. "<br>";
  }
} else {
  echo "0 results";
}
$conn->close();
?>

Code lines to explain from the example above:

First, we set up an SQL query that selects the id, firstname and lastname columns from the MyGuests table. The next line of code runs the query and puts the resulting data into a variable called $result.

Then, the function num_rows() checks if there are more than zero rows returned.

If there are more than zero rows returned, the function fetch_assoc() puts all the results into an associative array that we can loop through. The while() loop loops through the result set and outputs the data from the id, firstname and lastname columns.

The following example shows the same as the example above, in the MySQLi procedural way:

Các dòng code của ví dụ trên được mô tả như sau:

Đầu tiên, chúng ta thiết lập một truy vấn SQL chọn các cột id, firstname và lastname từ bảng MyGuests. Dòng mã tiếp theo chạy truy vấn và đặt dữ liệu kết quả vào một biến được gọi là $result.

Sau đó, hàm num_rows () kiểm tra nếu có nhiều hơn 0 hàng được trả về.

Nếu có nhiều hơn 0 hàng được trả về, hàm fetch_assoc() đặt tất cả kết quả vào một mảng kết hợp mà chúng ta có thể lặp qua. Vòng lặp while() lặp qua tập kết quả và xuất dữ liệu từ các cột id, firstname và lastname.

Sau đây là ví dụ theo hướng thủ tục:

Ví dụ (MySQLi Thủ tục)

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Tạo kết nối
$conn = mysqli_connect($servername, $username, $password, $dbname);
// Kiểm tra kết nối
if (!$conn) {
  die("Lỗi kết nối: " . mysqli_connect_error());
}

$sql = "SELECT id, firstname, lastname FROM MyGuests";
$result = mysqli_query($conn, $sql);

if (mysqli_num_rows($result) > 0) {
  // Hiển thị dữ liệu
  while($row = mysqli_fetch_assoc($result)) {
    echo "id: " . $row["id"]. " - Name: " . $row["firstname"]. " " . $row["lastname"]. "<br>";
  }
} else {
  echo "0 results";
}

mysqli_close($conn);
?>

Chúng ta cũng có thể đưa kết quả ra bảng HTML:

Ví dụ (MySQLi Hướng đối tượng)

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Tạo kết nối
$conn = new mysqli($servername, $username, $password, $dbname);
// Kiểm tra kết nối
if ($conn->connect_error) {
  die("Connection failed: " . $conn->connect_error);
}

$sql = "SELECT id, firstname, lastname FROM MyGuests";
$result = $conn->query($sql);

if ($result->num_rows > 0) {
  echo "<table><tr><th>ID</th><th>Name</th></tr>";
  // Hiển thị dữ liệu

  while($row = $result->fetch_assoc()) {
    echo "<tr><td>".$row["id"]."</td><td>".$row["firstname"]." ".$row["lastname"]."</td></tr>";
  }
  echo "</table>";
} else {
  echo "0 results";
}
$conn->close();
?>

Lựa chọn và lọc dữ

  • Mệnh đề WHERE được sử dụng để lọc các bản ghi.

  • Mệnh đề WHERE chỉ được sử dụng để trích xuất những bản ghi đáp ứng một điều kiện cụ thể.

SELECT tên_cột(s) FROM tên_bảng WHERE tên_cột toán tử giá trị 

Ví dụ sau lựa chọn cột id, firstname và lastname từ bảng MyGuests với điều kiện lastname là "Doe” và hiển thị lên trang::

Ví dụ (MySQLi Hướng đối tượng)

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Tạo kết nối

$conn = new mysqli($servername, $username, $password, $dbname);
// Kiểm tra kết nối
if ($conn->connect_error) {
  die("Lỗi kết nối: " . $conn->connect_error);
}

$sql = "SELECT id, firstname, lastname FROM MyGuests WHERE lastname='Doe'";
$result = $conn->query($sql);

if ($result->num_rows > 0) {
  // Hiển thị dữ liệu
  while($row = $result->fetch_assoc()) {
    echo "id: " . $row["id"]. " - Name: " . $row["firstname"]. " " . $row["lastname"]. "<br>";
  }
} else {
  echo "0 results";
}
$conn->close();
?>

Các dòng code trên được mô tả như sau:

Đầu tiên, chúng ta thiết lập truy vấn SQL chọn các cột id, firstname và lastname từ bảng MyGuests trong đó firstname là "Doe". Dòng mã tiếp theo chạy truy vấn và đặt dữ liệu kết quả vào một biến được gọi là $result.

Sau đó, hàm num_rows() kiểm tra nếu có nhiều hơn 0 hàng được trả về.

Nếu có nhiều hơn 0 hàng được trả về, hàm fetch_assoc() đặt tất cả kết quả vào một mảng kết hợp mà chúng ta có thể lặp qua. Vòng lặp while() lặp qua tập kết quả và xuất dữ liệu từ các cột id, firstname và lastname.

Ví dụ sau được viết theo hướng thủ tục:

Ví dụ (MySQLi Thủ tục)

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Tạo kết nối
$conn = mysqli_connect($servername, $username, $password, $dbname);
// Kiểm tra kết nối
if (!$conn) {
  die("Connection failed: " . mysqli_connect_error());
}

$sql = "SELECT id, firstname, lastname FROM MyGuests WHERE lastname='Doe'";
$result = mysqli_query($conn, $sql);

if (mysqli_num_rows($result) > 0) {
  // Hiển thị dữ liệu
  while($row = mysqli_fetch_assoc($result)) {
    echo "id: " . $row["id"]. " - Name: " . $row["firstname"]. " " . $row["lastname"]. "<br>";
  }
} else {
  echo "0 results";
}

mysqli_close($conn);
?>

Chúng ta cũng có thể hiển thị chúng trên bảng HTML:

Ví dụ (MySQLi Hướng đối tượng)

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Tạo kết nối
$conn = new mysqli($servername, $username, $password, $dbname);
// Kiểm tra kết nối
if ($conn->connect_error) {
  die("Lỗi kết nối: " . $conn->connect_error);
}

$sql = "SELECT id, firstname, lastname FROM MyGuests WHERE lastname='Doe'";
$result = $conn->query($sql);

if ($result->num_rows > 0) {
  echo "<table><tr><th>ID</th><th>Name</th></tr>";
  // Hiển thị dữ liệu
  while($row = $result->fetch_assoc()) {
    echo "<tr><td>".$row["id"]."</td><td>".$row["firstname"]." ".$row["lastname"]."</td></tr>";
  }
  echo "</table>";
} else {
  echo "0 results";
}
$conn->close();
?>

Lựa chọn và sắp xếp dữ liệu

Mệnh đề ORDER BY được sử dụng để sắp xếp tập hợp kết quả theo thứ tự tăng dần hoặc giảm dần.

Mệnh đề ORDER BY sắp xếp các bản ghi theo thứ tự tăng dần theo mặc định. Để sắp xếp các bản ghi theo thứ tự giảm dần, hãy sử dụng từ khóa DESC.

SELECT column_name(s) FROM table_name ORDER BY column_name(s) ASC|DESC 

Ví dụ sau đây chọn các cột id, firstname và lastname từ bảng MyGuests. Các bản ghi sẽ được sắp xếp theo cột lastname:

Ví dụ (MySQLi Hướng đối tượng)

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Tạo kết nối

$conn = new mysqli($servername, $username, $password, $dbname);
// Kiểm tra kết nối
if ($conn->connect_error) {
  die("Lỗi kết nối: " . $conn->connect_error);
}

$sql = "SELECT id, firstname, lastname FROM MyGuests ORDER BY lastname";
$result = $conn->query($sql);

if ($result->num_rows > 0) {
  // Hiển thị dữ liệu
  while($row = $result->fetch_assoc()) {
    echo "id: " . $row["id"]. " - Name: " . $row["firstname"]. " " . $row["lastname"]. "<br>";
  }
} else {
  echo "0 results";
}
$conn->close();
?>

Ví dụ (MySQLi Thủ tục)

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Tạo kết nối
$conn = mysqli_connect($servername, $username, $password, $dbname);
// Kiểm tra kết nối
if (!$conn) {
  die("Lỗi kết nối: " . mysqli_connect_error());
}

$sql = "SELECT id, firstname, lastname FROM MyGuests ORDER BY lastname";
$result = mysqli_query($conn, $sql);

if (mysqli_num_rows($result) > 0) {
  // Hiển thị dữ liệu
  while($row = mysqli_fetch_assoc($result)) {
    echo "id: " . $row["id"]. " - Name: " . $row["firstname"]. " " . $row["lastname"]. "<br>";
  }
} else {
  echo "0 results";
}

mysqli_close($conn);
?>

Xoá dữ liệu

Câu lệnh DELETE statement được sử dụng để xoá dữ liệu từ bảng:

DELETE FROM table_name
WHERE some_column = some_value

Xem bảng "MyGuests" sau:

id firstname lastname email reg_date
1 John Doe [email protected] 2014-10-22 14:26:15
2 Mary Moe [email protected] 2014-10-23 10:22:30
3 Julie Dooley [email protected] 2014-10-26 10:48:23

Ví dụ sau đây xoá bản ghi có id=3 trong bảng "MyGuests":

Ví dụ (MySQLi Hướng đối tượng)

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Tạo kết nối
$conn = new mysqli($servername, $username, $password, $dbname);
// Kiểm tra kết nối
if ($conn->connect_error) {
  die("Lỗi kết nối: " . $conn->connect_error);
}

// sql để xoá bản ghi
$sql = "DELETE FROM MyGuests WHERE id=3";

if ($conn->query($sql) === TRUE) {
  echo "Xoá bản ghi thành công";
} else {
  echo "Lỗi xoá bản ghi: " . $conn->error;
}

$conn->close();
?>

Ví dụ (MySQLi Thủ tục)

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Tạo kết nối

$conn = mysqli_connect($servername, $username, $password, $dbname);
// Kiểm tra kết nối
if (!$conn) {
  die("Lỗi kết nối: " . mysqli_connect_error());
}

// sql để xoá bản ghi
$sql = "DELETE FROM MyGuests WHERE id=3";

if (mysqli_query($conn, $sql)) {
  echo "Xoá bản ghi thành công";
} else {
  echo "Lỗi xoá bản ghi: " . mysqli_error($conn);
}

mysqli_close($conn);
?>

Cập nhật dữ liệu

Câu lệnh UPDATE được sử dụng để cập nhật bản ghi trong bảng:

UPDATE table_name
SET column1=value, column2=value2,...
WHERE some_column=some_value 

Xem xét bảng "MyGuests" sau:

id firstname lastname email reg_date
1 John Doe [email protected] 2014-10-22 14:26:15
2 Mary Moe [email protected] 2014-10-23 10:22:30

Sau đây là ví dụ cập nhật bản ghi với id=2 trong bảng "MyGuests":

Ví dụ (MySQLi Hướng đối tượng)

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Tạo kết nối
$conn = new mysqli($servername, $username, $password, $dbname);
// Kiểm tra kết nối
if ($conn->connect_error) {
  die("Connection failed: " . $conn->connect_error);
}

$sql = "UPDATE MyGuests SET lastname='Doe' WHERE id=2";

if ($conn->query($sql) === TRUE) {
  echo "Cập nhật thành công";
} else {
  echo "Lỗi cập nhật: " . $conn->error;
}

$conn->close();
?>

Ví dụ (MySQLi Thủ tục)

<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "myDB";

// Tạo kết nối
$conn = mysqli_connect($servername, $username, $password, $dbname);
// Kiểm tra kết nối
if (!$conn) {
  die("Lỗi kết nối: " . mysqli_connect_error());
}

$sql = "UPDATE MyGuests SET lastname='Doe' WHERE id=2";

if (mysqli_query($conn, $sql)) {
  echo "Cập nhật thành công";
} else {
  echo "Lỗi cập nhật " . mysqli_error($conn);
}

mysqli_close($conn);
?>

Giới hạn dữ

MySQL cung cấp một mệnh đề LIMIT được sử dụng để chỉ định số lượng bản ghi trả về.

Mệnh đề LIMIT giúp dễ dàng viết mã các kết quả nhiều trang hoặc phân trang bằng SQL và rất hữu ích trên các bảng lớn. Trả lại một số lượng lớn bản ghi có thể ảnh hưởng đến hiệu suất.

Giả sử chúng ta muốn chọn tất cả các bản ghi từ 1 đến 30 từ một bảng có tên "Orders ". Truy vấn SQL sau đó sẽ giống như sau:

$sql = "SELECT * FROM Orders LIMIT 30";

Khi truy vấn SQL ở trên được chạy, nó sẽ trả về 30 bản ghi đầu tiên.

Điều gì xảy ra nếu chúng ta muốn chọn các bản ghi 16 - 25?

Mysql cũng cung cấp một cách để xử lý điều này: bằng cách sử dụng OFFSET.

Truy vấn SQL bên dưới cho biết "chỉ trả lại 10 bản ghi, bắt đầu từ bản ghi 16 (OFFSET 15)":

$sql = "SELECT * FROM Orders LIMIT 10 OFFSET 15";

Chúng ta cũng có thể sử dụng một cú pháp ngắn hơn để đạt được kết quả tương tự:

$sql = "SELECT * FROM Orders LIMIT 15, 10";

Lưu ý rằng các số được đảo ngược khi chúng ta sử dụng dấu phẩy.

Bài 3: Bảo mật cho website

Giao thức bảo mật SSL

Http và https là 2 protocol chúng ta thường gặp khi truy cập vào một trang web. Hầu hết chúng ta đều hiểu https bảo mật hơn http. Hôm nay mình sẽ giải thích bản chất, cơ chế và cách config một trang web https.

Http và https

  • http là tên viết tắt của HyperText Transfer Protocol (giao thức truyền tải siêu văn bản), là một giao thức cơ bản dùng cho World Wide Web (www) để truyền tải dữ liệu dưới dạng văn bản, hình ảnh, video, âm thanh và các tập tin khác từ Web server đến các trình duyệt web và ngược lại.

  • https là viết tắt của từ HyperText Transfer Protocol Secure và chính là giao thức HTTP có sử dụng thêm các chứng chỉ SSL (Secure Sockets Layer) giúp mã hóa dữ liệu truyền tải nhằm gia bảo mật giữa Web sever đến các trình duyệt web. Nói cách khác https là phiên bản httpnhưng an toàn hơn, bảo mật hơn. Việc bảo mật thông tin riêng tư, cá nhân là rất quan trọng. Do đó có rất nhiều website đã sử dụng https thay http. Các trình duyệt web như Firefox, Chrome và IE như hiện nay đều hiển thị biểu tượng ổ khóa ở thanh địa chỉ để cho biết giao thức https có hoạt động trên trang web bạn truy cập vào hay không.

Cơ chế của SSL ứng dụng trong HTTPS.

SSL là gì?

Việc kết nối giữa một Web browser tới bất kỳ điểm nào trên mạng Internet đi qua rất nhiều các hệ thống độc lập mà không có bất kỳ sự bảo vệ nào với các thông tin trên đường truyền. Không một ai kể cả người sử dụng lẫn Web server có bất kỳ sự kiểm soát nào đối với đường đi của dữ liệu hay có thể kiểm soát được liệu có ai đó thâm nhập vào thông tin trên đường truyền.

Để bảo vệ những thông tin mật trên mạng Internet hay bất kỳ mạng TCP/IP nào, SSL đã kết hợp những yếu tố sau để thiết lập được một giao dịch an toàn:

  • Xác thực: đảm bảo tính xác thực của trang mà khách hàng sẽ làm việc ở đầu kia của kết nối. Cũng như vậy, các trang Web cũng cần phải kiểm tra tính xác thực của người sử dụng.

  • Mã hoá: đảm bảo thông tin không thể bị truy cập bởi đối tượng thứ ba. Để loại trừ việc nghe trộm những thông tin “nhạy cảm” khi nó được truyền qua Internet, dữ liệu phải được mã hoá để không thể bị đọc được bởi những người khác ngoài người gửi và người nhận.

  • Toàn vẹn dữ liệu: đảm bảo thông tin không bị sai lệch và nó phải thể hiện chính xác thông tin gốc gửi đến.Với việc sử dụng SSL, các Web site có thể cung cấp khả năng bảo mật thông tin, xác thực và toàn vẹn dữ liệu đến người dùng. SSL được tích hợp sẵn vào các browser và Web server, cho phép người sử dụng làm việc với các trang Web ở chế độ an toàn.

Giao thức SSL là gì?

SSL được phát triển bởi Netscape, ngày nay giao thức SSL đã được sử dụng rộng rãi trên World Wide Web trong việc xác thực và mã hoá thông tin giữa client và server. Tổ chức IETF (Internet Engineering Task Force ) đã chuẩn hoá SSL và đặt lại tên là TLS (Transport Layer Security). Mặc dù là có sự thay đổi về tên nhưng TSL chỉ là một phiên bản mới của SSL. Phiên bản TSL 1.0 tương đương với phiên bản SSL 3.1. Tuy nhiên SSL là thuật ngữ được sử dụng rộng rãi hơn

SSL được thiết kế như là một giao thức riêng cho vấn đề bảo mật có thể hỗ trợ cho rất nhiều ứng dụng. Giao thức SSL hoạt động bên trên TCP/IP và bên dưới các giao thức ứng dụng tầng cao hơn như là HTTP, IMAP và FTP.

SSL không phải là một giao thức đơn lẻ, mà là một tập các thủ tục đã được chuẩn hoá để thực hiện các nhiệm vụ bảo mật sau:

  • Xác thực server: Cho phép người sử dụng xác thực được server muốn kết nối. Lúc này, phía browser sử dụng các kỹ thuật mã hoá công khai để chắc chắn rằng certificate và public ID của server là có giá trị và được cấp phát bởi một CA (certificate authority) trong danh sách các CA đáng tin cậy của client. Điều này rất quan trọng đối với người dùng. Ví dụ như khi gửi mã số credit card qua mạng thì người dùng thực sự muốn kiểm tra liệu server sẽ nhận thông tin này có đúng là server mà họ định gửi đến không.

  • Xác thực Client: Cho phép phía server xác thực được người sử dụng muốn kết nối. Phía server cũng sử dụng các kỹ thuật mã hoá công khai để kiểm tra xem certificate và public ID của server có giá trị hay không và được cấp phát bởi một CA (certificate authority) trong danh sách các CA đáng tin cậy của server không. Điều này rất quan trọng đối với các nhà cung cấp. Ví dụ như khi một ngân hàng định gửi các thông tin tài chính mang tính bảo mật tới khách hàng thì họ rất muốn kiểm tra định danh của người nhận.

  • Mã hoá kết nối: Tất cả các thông tin trao đổi giữa client và server được mã hoá trên đường truyền nhằm nâng cao khả năng bảo mật. Điều này rất quan trọng đối với cả hai bên khi có các giao dịch mang tính riêng tư. Ngoài ra, tất cả các dữ liệu được gửi đi trên một kết nối SSL đã được mã hoá còn được bảo vệ nhờ cơ chế tự động phát hiện các xáo trộn, thay đổi trong dữ liệu. (đó là các thuật toán băm – hash algorithm).

Giao thức SSL bao gồm 2 giao thức con:

  • Giao thức SSL record: xác định các định dạng dùng để truyền dữ liệu.

  • Giao thức SSL handshake: sử dụng SSL record protocol để trao đổi một số thông tin giữa server và client vào lấn đầu tiên thiết lập kết nối SSL

Một số thuật toán dùng trong SSL

Các thuật toán mã hoá và xác thực của SSL được sử dụng bao gồm:

  • DES (Data Encryption Standard): là một thuật toán mã hoá có chiều dài khoá là 56 bit.

  • 3-DES (Triple-DES): là thuật toán mã hoá có độ dài khoá gấp 3 lần độ dài khoá trong mã hoá DES.

  • DSA (Digital Signature Algorithm): là một phần trong chuẩn về xác thực số đang được được chính phủ Mỹ sử dụng.

  • KEA (Key Exchange Algorithm): là một thuật toán trao đổi khoá đang được chính phủ Mỹ sử dụng.

  • MD5 (Message Digest algorithm): được phát thiển bởi Rivest.

  • RSA: là thuật toán mã hoá công khai dùng cho cả quá trình xác thực và mã hoá dữ liệu được Rivest, Shamir, and Adleman phát triển.

  • RSA key exchange: là thuật toán trao đổi khoá dùng trong SSL dựa trên thuật toán RSA.

  • RC2 and RC4: là các thuật toán mã hoá được phát triển bởi Rivest dùng cho RSA Data Security.

  • SHA-1 (Secure Hash Algorithm): là một thuật toán băm đang được chính phủ Mỹ sử dụng.

Khi một client và server trao đổi thông tin trong giai đoạn bắt tay (handshake), họ sẽ xác định bộ mã hoá mạnh nhất có thể và sử dụng chúng trong phiên giao dịch SSL.

Cách hoạt động giữa client và server sử dụng SSL.

Đơn giản chúng ta có ví dụ: A cần bán hàng cho anh B sẽ có các thủ tục sau:

  1. B yêu cầu A gửi cho mình chứng minh thư

  2. A đưa chứng minh thư cho B

  3. B mang lên cơ quan công an nhờ xác nhận xem có phải là đúng là A không?

  4. Nếu xác nhận ok, thì B báo cho A biết là ok

  5. A gửi cho B một key

  6. B và A sẽ dùng key này để mã hóa thông tin trao đổi với nhau

Qua ví dụ trên thì:

  • A là server, B là client

  • Chứng minh thư là chính chỉ SSL

  • Cơ quan công an là tổ chức CA (Certification Authority); là một tổ chứng mà 2 A, B đều tin cậy, là người cấp SSL

  • Nếu C mà nghe lén được thông tin của A, B thì cũng không giải mã được vì không có key

Có 2 cách tạo SSL:

  • Nhờ một tổ chức CA cấp, là tổ chức có độ tin cậy cao, được quyền cấp và chứng nhận SSL. Tất nhiên là chúng ta phải mất tiền để mua chứng chỉ SSL.

  • Self-signed SSL: là tự server cấp, tự kí, tự xác thực (ko an toàn và tin tưởng bằng nhờ bên thứ 3)

Phần demo chúng ta sẽ tạo self-signed SSL trên môi trường Nginx và Ubuntu 16.04.

Cấu hình HTTPS

Step 1: Tạo một chứng chỉ SSL

TLS/SSL hoạt động dựa vào sự kết hợp giữa một public certificate và một private key. SSL key được giữ bí mật ở trên server. Nó được sử dụng để mã hóa nội dung gửi tới clients.

Còn SSL certificate được chia sẻ rộng rãi với bất cứ ai yêu cầu nội dung. Nó được sử dụng để giải mã nội dung được ký bởi SSL key.

Chúng ta sẽ tạo một self-signed key và một cặp chứng chỉ với câu lệnh OpenSSL:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt

Chúng ta sẽ tìm hiểu ý nghĩa lệnh trên như:

  • openssl là một command để tạo vào quản lý chứng chỉ OpenSSL , keys và các file khác.

  • req là một subcommand chỉ định rõ chúng ta mún sử dụng X.509 CSR (certificate signing request) : chứng chỉ yêu cầu ký. X.509 là một chuẩn public key của SSL và TLS.

  • nodes chỉ rõ OpenSSL bỏ qua việc bảo mặt chứng chỉ của chúng ta bằng một chuỗi mật khẩu (passphrase). Nếu để mật khẩu này thì nginx của chúng ta luôn phải nhập mật khẩu này mỗi khi khởi động nên rất là bất tiện.

  • days 365 là tham số xác định thời hạn sử dụng chứng chỉ là 365 ngày (1 năm).

  • newkey rsa:2048 là tham số chỉ định chúng ta muốn sinh ra một chứng chỉ mới và một key mới tại cùng câu lệnh với key RSA có độ dài 2048 bít.

  • keyout chỉ định nơi chứng ta lưu trữ private key được sinh ra lúc tạo

  • out chỉ định nơi chứng chỉ được lưu trữ sau khi tạo

Khi chúng ta sử dụng câu lệnh ở trên, nó sẽ tạo ra 2 file : 1 file key và một file chứng chỉ. Sẽ có một số câu hỏi về server để thêm đúng thông tin vào chứng chỉ.

Chúng ta cần điền đầy đủ các thông tin như sau: Chú ý là dòng Common Name (e.g. server FQDN or YOUR name) chúng ta cần nhập đúng tên domain hoặc IP của server.

Country Name (2 letter code) [AU]: VN

State or Province Name (full name) [Some-State]: Ha Noi

Locality Name (eg, city) []: Ha Noi

Organization Name (eg, company) [Internet Widgits Pty Ltd]:Test company

Organizational Unit Name (eg, section) []: Test company

Common Name (e.g. server FQDN or YOUR name) []: IP hoặc test.com

Email Address []:[email protected]

Cả 2 file được tạo trong thư mục /etc/ssl Để tăng tính bảo mật, chúng ta cũng nên tạo một Diffie-Hellman group:

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

Kết thúc chúng ta sẽ có một group DH đủ mạnh trong tại file /etc/ssl/certs/dhparam.pem.

Step 2: Cấu hình Nginx để sử dụng SSL

Bước tiếp theo là chúng ta sẽ config lại nginx. Đầu tiên chúng ta sẽ tạo một Nginx configuration snippet tên là self-signed.conf trong thư mục /etc/nginx/snippets. Cấu hình ssl_certificate và ssl_certificate_key có đường dẫn tới certificate và key chúng ta đã tạo.

  • sudo nano /etc/nginx/snippets/self-signed.conf

# /etc/nginx/snippets/self-signed.conf

ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;

ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;

Chúng ta tạo thêm một file snippet khác, định nghĩa vài cài đặt SSL. Nó sẽ tăng tính bảo mật của SSL.

  • sudo nano /etc/nginx/snippets/ssl-params.conf

Chúng ta sẽ sử dụng mã hóa được recommend trên trang https://cipherli.st/. Ở đây chúng ta chọn cấu hình cho Nginx. Setting được gợi ý ở trang này tạo ra sự bảo mật tốt nhất cho từng web server. Chúng ta sẽ sửa lại vài chỗ trong cấu hình này cho phù hợp:

  • Thêm preferred DNS resolver cho upstream request là DNS của Google. Thêm ssl_dhparam tới file Diffie-Hellman đã được tạo ra từ bước trước.

  • Chúng ta sẽ tắt chức năng preload HSTS vì hơi phức tạp để hiểu và cấu hình.

# /etc/nginx/snippets/ssl-params.conf

# from https://cipherli.st/

# and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

ssl_prefer_server_ciphers on;

ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";

ssl_ecdh_curve secp384r1;

ssl_session_cache shared:SSL:10m;

ssl_session_tickets off;

ssl_stapling on;

ssl_stapling_verify on;

resolver 8.8.8.8 8.8.4.4 valid=300s;

resolver_timeout 5s;

# Disable preloading HSTS for now. You can use the commented out header line that includes

# the "preload" directive if you understand the implications.

#add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";

add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";

add_header X-Frame-Options DENY;

add_header X-Content-Type-Options nosniff;

ssl_dhparam /etc/ssl/certs/dhparam.pem;

Cấu hình Nginx sử dụng SSL

  • Trước khi cấu hình, chúng ta cần backup lại config default của nginx - sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak

  • Mở file cấu hình nginx lên và chỉnh sửa: - sudo nano /etc/nginx/sites-available/default

Ban đầu nội dung file sẽ như thế này:

# /etc/nginx/sites-available/default

server {

listen 80 default_server;

listen [::]:80 default_server;

# SSL configuration

# listen 443 ssl default_server;

# listen [::]:443 ssl default_server;

  • Trước hết, chúng ta sẽ bắt các request http sẽ redirect về https. Nghĩa là khi người dùng truy cập bằng http thì server tự động chuyển sang https.

# /etc/nginx/sites-available/default

server {

listen 80 default_server;

listen [::]:80 default_server;

server_name server_domain_or_IP;

return 302 https://$server_name$request_uri;

}

# SSL configuration

# listen 443 ssl default_server;

# listen [::]:443 ssl default_server;

  • Tiếp theo chúng ta cấu hình SSL listen ở cổng 443 vào block thứ 2. Thêm cấu hình 2 file snippets vào như sau:

# /etc/nginx/sites-available/default

server {

listen 80 default_server;

listen [::]:80 default_server;

server_name server_domain_or_IP;

return 302 https://$server_name$request_uri;

}

server {

# SSL configuration

listen 443 ssl http2 default_server;

listen [::]:443 ssl http2 default_server;

include snippets/self-signed.conf;

include snippets/ssl-params.conf;

}

Chúng ta đã cấu hình xong Nginx SSL. Tiếp đến cần bật firewall cho HTTPS.

Step 3: Chỉnh sửa Firewall

Nếu ufw firewall được bật, thì chúng tá sẽ cần chỉnh sửa cài đặt cho phép SSL (HTTPS). Xem danh sách các pro/files firewall:

  • sudo ufw app list

Output

Available applications:

Nginx Full

Nginx HTTP

Nginx HTTPS

OpenSSH

Xem trạng thái settings hiện tại thì dùng command:

  • sudo ufw status Chúng ta có thể thấy chỉ có HTTP được cho phép.

Output

Status: active

To Action From

-- ------ ----

OpenSSH ALLOW Anywhere

Nginx HTTP ALLOW Anywhere

OpenSSH (v6) ALLOW Anywhere (v6)

Nginx HTTP (v6) ALLOW Anywhere (v6)

Để thêm HTTPS traffic, chúng ta cần cho phép Nginx Full profile và xóa Nginx HTTP profile:

sudo ufw allow 'Nginx Full'

sudo ufw delete allow 'Nginx HTTP'

Xem lại trạng thái firewall:

  • sudo ufw status

Status: active

To Action From

-- ------ ----

OpenSSH ALLOW Anywhere

Nginx Full ALLOW Anywhere

OpenSSH (v6) ALLOW Anywhere (v6)

Nginx Full (v6) ALLOW Anywhere (v6)

Step 4: Cấu hình Nginx

Để kiểm tra lõi cũ pháp trong cấu hình nginx thì dùng command sau:

  • sudo nginx -t

Nếu config ok thì sẽ get được kết quả như sau:

nginx: [warn] "ssl_stapling" ignored, issuer certificate not found

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok

nginx: configuration file /etc/nginx/nginx.conf test is successful

Nếu không bị lỗi gì, thì restart lại nginx:

  • sudo systemctl restart nginx

Step 5: Kiểm tra Encryption

Chúng ta đã cấu hình xong SSL cho domain. Mở trình duyệt và đánh https để kiểm tra. Kết quả chúng ta sẽ thấy có cái biểu tượng khóa ở trên trình duyệt:

  • https://server_domain_or_IP

  • Kết quả sẽ có warning như hình dưới: 

Mã hóa trong PHP

Có lẽ bạn đã biết nhiều về MD5 và SHA1 dùng để mã hóa chuỗi thông tin đầu vào s1 và cho ra chuỗi thông tin được mã hóa s2. Về lý thuyết, chúng ta không thể dịch ngược được chuỗi s2 để ra dữ liệu ban đầu, mặc dù hiện nay có rất nhiều phương pháp và thuật toán đã làm rất tốt việc này.

Hàm md5() và sha1()

Để mã hóa thông tin đầu vào bằng MD5 hay SHA1, đơn giản bạn chỉ cần dùng hàm md5() và sha1(). Hãy xem ví dụ sau:

<?php

// Mật khẩu là dammio

$password = 'dammio';

 

echo 'Mật khẩu <b>' . $password . '</b> được mã hóa thành: <br/><br/>';

echo 'MD5: <b>' . md5($password) . '</b><br/>'; // mật khẩu đã được mã hóa bằng md5

echo 'SHA1: <b>' . sha1($password) . '</b>'; // mật khẩu đã được mã hóa bằng sha1

?>

Để bảo mật hơn chúng ta có thể kết hợp 2 hàm này với nhau để tạo ra chuỗi mã hóa khó dịch ngược hoặc tự viết thêm một số thuật toán cắt ghét chuỗi của riêng bạn.

Hàm md5_file() và sha1_file()

Như tên gọi, bạn có thể mã hóa md5 và sha1 cho một tập tin. Chúng ta có thể thực hiện đoạn code mã hóa đơn giản như sau:

$file = 'dammio.txt';

echo 'Mã hóa MD5 tập tin ' . $file . ': ' . md5_file($file);

Hàm crc32()

CRC là viết tắt của từ Cyclic Redundancy Check, tạm dịch là “Kiểm dư chu trình”, là một phương pháp kiểm tra và phát hiện lỗi, được sử dụng trong các mạng số và thiết bị lưu trữ để phát hiện sự thay đổi tình cờ đối với dữ liệu được truyền đi hay lưu trữ.

Hàm có thể dùng hàm crc32() để checksum hay kiểm tra dữ liệu nhận được có bị lỗi hay hư hỏng hay không. Hãy cùng xét đến ví dụ sau:

<?php

$checksum = crc32("Thông tin dữ liệu cần kiểm tra CRC --- dammio.com!");

printf("%u\n", $checksum);

// Kết quả: 1139409907

?>

Hàm hash()

Hàm hash cho phép chúng ta mã hóa tất cả các dạng md5, sha1,… chỉ cần dùng hàm này. Cú pháp:

string hash (string $algo, string $data, bool $output)

Trong đó $algo là thuật toán mã hóa (MD5, SHA1,…), $data là dữ liệu cần mã hóa, $output là dạng đầu ra, nếu = TRUE là dạng dữ liệu đầu ra nhị phân, = FALSE (hay mặc định) là dữ liệu đầu ra văn bản.

Ví dụ mã hóa chuỗi ‘dammio’ bằng thuật toán RIPEMD (RIPE Message Digest), chủ yếu dùng trong mã hóa tiền ảo Bitcoin.

<?php

echo 'Văn bản: ' . hash('ripemd160', 'dammio') . "<br />";

echo 'Nhị phân: ' . hash('ripemd160', 'dammio', TRUE);

?>

Ngoài ra bạn còn có hàm crypt() và password_hash() cũng với chức năng mã hóa thông tin tương tự.

Bài 4: Chức năng gửi thư điện tử cho website

Giới thiệu

PHP hỗ trợ 3 cách thức gửi mail: Sử dụng gói PEAR Mail; Sử dụng hàm helper để gửi email; Sử dụng thư viện cURL.

Quy trình gửi và nhận email:

Phía client sẽ gửi yêu cầu đến máy chủ email thông qua giao thức SMTP. Máy chủ xử lý và gửi mail cho máy khách thông qua giao thức POP3 hoặc IMAP.

Gửi mail sử dụng PEAR Mail

Để cấu hình gửi mail sử dụng PEAR Mail từ localhost, trước tiên chúng ta cần cấu hình tài khoản gmail của chúng ta.

  • Đăng nhập vào tài khoản

  • Nhấn nút Settings

  • Vào tab Forwarding and POP/IMAP

  • Trong mục POP download đánh dấu chọn vào ô Enable POP for all mail

  • Nhấn nút Save changes

Thông số kết nối của máy chủ Gmail:

Image 4.png

Bước 1: Nạp gói PEAR Mail

  • Sử dụng lệnh

  • Không cần copy file Mail.php vào mã nguồn ứng dụng

  • Tránh tạo file Mail.php khác để không trùng

Bước 2: Thiết lập thông số cho đối tượng mailer mail

//Ví dụ 1: Máy chủ SMTP đơn giản

$option = array();

$option['host'] = 'mail.example.com';

//Ví dụ 2: Máy chủ SMTP có xác thực

$option = array();

$option['host'] = 'mail.example.com';

$option['auth'] = true;

$option['username'] = '[email protected]';

$option['password'] = 'ghg44463';

//Ví dụ 3: Máy chủ SMTP có xác thực và bảo mật SSL

$option = array();

$option['host'] = 'ssl://mail.example.com';

$option['port'] = 465;

$option['auth'] = true;

$option['username'] = '[email protected]';

$option['password'] = 'ghg44463';

Bước 3: Tạo đối tượng mailer

Sử dụng phương thức tĩnh factory trả về đối tượng mailer dùng để gửi mail

$mailer = Mail::factory('smtp', $option);

Bước 4: Viết mail

//1. Thiết lập SMTP header

$headers = array();

$headers['From'] = '[email protected]';

$headers['To'] = '[email protected], [email protected]';

$headers['Cc'] = '[email protected]';

$headers['Bcc'] = '[email protected]';

$headers['Subject'] = 'Hello';

$headers['Content-type'] = 'text/';

//2. Thiết lập danh sách gửi

$recipients = '[email protected], [email protected]';

$recipients .= '[email protected], [email protected]';

//3. Thiết lập phần div

$div = "<p>Hello</p>

<p>How are you</p>";

Bước 5: Gửi mail và kiểm tra kết quả

//1. Gửi mail

$result = $mailer->send($recipients, $header, $div);

//2. Kiểm tra kết quả và hiển thị lỗi nếu có

if (PEAR::isError($result)) {

$error = $result->getMessage();

echo specialchars($error);

Gửi mail sử dụng hàm Hàm helper

<?php

require_once 'Mail.php';

require_once 'Mail/RFC822.php';

function send_mail($to, $from, $subject, $div, $is_div_ = false) {

if (!valid_email($to)) {

throw new Exception('Địa chỉ email To không đúng: ' . specialchars($to));

}

if (!valid_email($from)) {

throw new Exception('Địa chỉ email From không đúng: ' . specialchars($from));

}

$smtp = array();

$smtp['host'] = 'ssl://smtp.gmail.com';

$smtp['port'] = 465;

$smtp['auth'] = true;

$smtp['username'] = '[email protected]'; //Điền địa chỉ email thực vào đây

$smtp['password'] = '123456'; //Điền password vào đây

$mailer = Mail::factory('smtp', $smtp);

if (PEAR::isError($mailer)) {

throw new Exception('Could not create mailer');

}

//Thêm địa chỉ email vào danh sách email

$recipients = array();

$recipients[] = $to;

//Thiết lập header

$headers = array();

$headers['From'] = $from;

$headers['To'] = $to;

$header['Subject'] = $subject;

if ($is_div_) {

$header['Content-type'] = 'text/';

}

//Gửi email

$result = $mailer->send($recipients, $headers, $div);

//Kiểm tra kết quả và hiển thị lỗi nếu có

if (PEAR::isError($result)) {

throw new Exception('Error sending email: ' . specialchars($result->getMessage()));

}

}

function valid_email($email) {

$emailObjects = Mail_RFC822::parseAddressList($email);

if (PEAR::isError($emailObjects)) return false;

//Lấy mailbox và host của email đầu tiên

$mailbox = $emailObjects[0]->mailbox;

$host = $emailObjects[0]->host;

//Đảm bảo mailbox và host không quá dài

if (strlen($mailbox) > 64) return false;

if (strlen($host) > 255) return false;

//Xác thực mailbox

$atom = '[[:alnum:]_!#$%&\'*+\/=?^`{|}~-]+';

$doatom = '(\.' . $atom . ')*';

$address = '(^' . $atom . $doatom . '$)';

$char = '([^\\\\"])';

$esc = '(\\\\[\\\\"])';

$text = '(' . char . '|' . $esc . ')+';

$quoted = '(^"' . $text . '"$)';

$localPart = '/' . $address . '|' . $quoted . '/';

$localMatch = preg_match($localPart, $mailbox);

if ($localMatch === false || $localMatch != 1) {

return false;

}

//Xác thực host

$hostname = '([[:alnum:]]([-[:alnum:]]{0,62}[[:alnum:]])?)';

$hostnames = '(' . $hostname . '(\.' . hostname . ')*)';

$top = '\.[[:alnum:]]{2,6}';

$domainPart = '/^' . $hostnames . $top . '$/';

$domainMatch = preg_match($domainPart, $host);

if ($domainMatch === false || $domainMatch != 1) {

return false;

}

return true;

}

?>

Gửi mail sử dụng hàm send_email

require_once 'message.php';

$from = 'John Doe <[email protected]>';

$to = 'Jane Doe <[email protected]>';

$subject = 'How to use PEAR Mail';

$div = '<p>Murach PHP and MySQL book has a chapter on how to use the <a href="http://pear.php.net/Mail/">PEAR Mail package<a>to send email.</p>';

$is_div_ = true;

try {

send_email($to, $from, $subject, $div, $is_div_);

} catch (Exception $e) {

$error = $e->getMessage();

echo $error;

}

Bài 5: Tải file và hình ảnh lên website

Gửi file và hình ảnh đơn lên website

Một PHP script có thể sử dụng với một HTML form cho phép người dùng upload file lên Server. Đầu tiên các file này được upload lên một thư mục tạm thời, sau đó được di chuyển tới một đích bởi một PHP script.

Thông tin trong trang phpinfo.php mô tả thư mục tạm thời mà được sử dụng cho các file được upload ở dạng upload_tmp_dir và kích thước giới hạn của các file có thể được upload được bắt đầu ở dạng upload_max_/filesize. Các tham số này được thiết lập trong file cấu hình php.ini.

Tiến trình upload một file theo các bước sau:

  • Người dùng mở trang chứa một HTML form là một text file, một nút browse và một nút submit.

  • Người dùng nhấn nút browse và chọn một file để upload từ máy local.

  • Đường dẫn đầy đủ đến file được chọn sẽ xuất hiện trong trường văn bản, sau đó người dùng nhấn nút Submit.

  • File được chọn được gửi đến thư mục tạm thời trên Server.

  • PHP script, mà được xác định như một Form Handler trong thuộc tính action của form, sẽ kiểm tra xem file đã đến chưa và sau đó sao chép file này sang thư mục mong muốn.

  • PHP script xác nhận thành công tới người dùng.

Thông thường khi ghi các file, nó là cần thiết cho cả thư mục tạm thời và thư mục đích để có quyền truy cập được thiết lập là cho phép ghi. Nếu một trong 2 được thiết lập là read-only, thì tiến trình sẽ thất bại.

Một file được upload lên có thể là text file hoặc image file hoặc bất cứ tài liệu nào.

Tạo upload form trong PHP

Dưới đây là HTML code tạo một upload form. Form này có thuộc tính method được thiết lập là post và thuộc tính enctype thiết lập là multipart/form-data

<?php

if(isset($_FILES['image'])){

$errors= array();

$file_name = $_FILES['image']['name'];

$file_size =$_FILES['image']['size'];

$file_tmp =$_FILES['image']['tmp_name'];

$file_type=$_FILES['image']['type'];

$file_ext=strtolower(end(explode('.',$_FILES['image']['name'])));

$expensions= array("jpeg","jpg","png");

if(in_array($file_ext,$expensions)=== false){

$errors[]="Không chấp nhận định dạng ảnh có đuôi này, mời bạn chọn JPEG hoặc PNG.";

}

if($file_size > 2097152){

$errors[]='Kích cỡ file nên là 2 MB';

}

if(empty($errors)==true){

move_uploaded_file($file_tmp,"images/".$file_name);

echo "Thành công!!!";

}

else{

print_r($errors);

}

}

?>

<>

<div>

<form action="" method="POST" enctype="multipart/form-data">

<input type="file" name="image" />

<input type="submit"/>

</form>

</div>

</>

Lưu chương trình trên trong một file có tên là test.php trong htdocs, sau đó mở trình duyệt và gõ địa chỉ http://localhost:8080/test.php sẽ cho kết quả:

Upload file trong PHP

Tạo upload script trong PHP

Có một biến PHP toàn cục là $_FILES. Biến này là một mảng mảng liên hợp và giữ tất cả thông tin liên quan đến file được tải lên. Vì vậy, nếu giá trị gán cho thuộc tính name của input trong form upload là file, khi đó PHP có thể tạo 5 biến sau:

  • $_FILES['file']['tmp_name'] − File đã upload trong thư mục tạm thời trên Web Server.

  • $_FILES['file']['name'] − Tên thực sự của file đã upload.

  • $_FILES['file']['size'] − Kích thước tính theo byte của file đã upload.

  • $_FILES['file']['type'] − Kiểu MIME của file đã upload.

  • $_FILES['file']['error'] − Mã hóa lỗi liên quan đến file tải lên này.

Ví dụ

Dưới đây là ví dụ cho phép tải các hình ảnh và trả về kết quả ở dạng thông tin file đã được tải lên.

<?php

if(isset($_FILES['image'])){

$errors= array();

$file_name = $_FILES['image']['name'];

$file_size =$_FILES['image']['size'];

$file_tmp =$_FILES['image']['tmp_name'];

$file_type=$_FILES['image']['type'];

$file_ext=strtolower(end(explode('.',$_FILES['image']['name'])));

$expensions= array("jpeg","jpg","png");

if(in_array($file_ext,$expensions)=== false){

$errors[]="Không chấp nhận định dạng ảnh có đuôi này, mời bạn chọn JPEG hoặc PNG.";

}

if($file_size > 2097152){

$errors[]='Kích cỡ file nên là 2 MB';

}

if(empty($errors)==true){

move_uploaded_file($file_tmp,"images/".$file_name);

echo "Thành công!!!";

}

else{

print_r($errors);

}

}

?>

<>

<div>

<form action="" method="POST" enctype="multipart/form-data">

<input type="file" name="image" />

<input type="submit"/>

<ul>

<li>Gửi file có tên: <?php echo $_FILES['image']['name']; ?>

<li>Kích cỡ file : <?php echo $_FILES['image']['size']; ?>

<li>Kiểu file : <?php echo $_FILES['image']['type'] ?>

</ul>

</form>

</div>

</>

Kết quả sẽ có dạng giống như hình sau:

Gửi nhiều file và hình ảnh lên website

<form method="post" enctype="multipart/form-data">

File name: <input type="file" name="userfile[]"><br>

File name: <input type="file" name="userfile[]"><br>

File name: <input type="file" name="userfile[]"><br>

File name: <input type="file" name="userfile[]"><br>

File name: <input type="file" name="userfile[]"><br>

<input type="submit" value="Upload">

</form>

<?php

if (isset($_FILES['userfile'])){

foreach ($_FILES['userfile']['name'] as $k=>$v){

if (is_uploaded_file($_FILES['userfile']['tmp_name'][$k])) {

move_uploaded_file($_FILES['userfile']['tmp_name'][$k], "hieulv68/" . $_FILES['userfile']['name'][$k]);

echo "File '<b>" . $_FILES['userfile']['name'][$k] . “

</b>' is valid,and was successfully uploaded<br>";

}}

}?>