Mình rất ít khi viết bài trên các diễn đàn, tiện bữa nay đang chán nên muốn góp một chút ý kiến về PHP nói chung, nhưng bài này cũng có thể áp dụng với các ngôn ngữ khác, không biết những bạn đọc bài này có coi trọng về việc khả dụng của nó không, nhưng đối với mình, mình cảm thấy nó hợp lý nên chia sẻ. sau đây là bài hướng dẫn.
Những điều cần thiết sau đây.
1/ Có một IDE tốt, bạn có thể chọn một trong những IDE sau.
a> PHPED (đã có *****)
b> Zend studio (cũng ***** luôn)
c> Netbean (cái này free).
2/ Đã biết lập trình hướng đối tượng(nói chung) PHP(nói riêng), có một số kỹ thuật đơn giản nhưng có lẽ có bạn không để ý nên không biết.
3/ Kiên trì nhẫn nại
I/ Tạo Project
Điều này là rất quan trọng trong cách mà mình hướng dẫn sau đây, vì nó sẽ rất tiện lợi trong quá trình bạn làm việc sau này, vì khi đó tất cả các hàm, các lớp có trong project của bạn sẽ được hiển thị trên một menu tooltip
cách tạo project thì mỗi ide có một cách khác nhau, cái này bạn tự tìm hiểu nhé.
II/ Tạo thư viện.
Cái mình nói thư viện ở đây nó là một file để include vào mỗi trang, và chỉ cần 1 file duy nhất, vì cách mình làm đây phải tạo rất nhiều file thư viện tương đương với từng table của CSDL(Cơ sở dữ liệu) nên bạn có thể viết ra một file để include tất cả các file trong cùng thư mục vào, và sau này nếu cần dùng đến thư viện ta chỉ cần include file đó vào.
tạo một file Lib.php như sau trong folder /Lib:
PHP Code:
<?php
$path = dirname(__FILE__);
function __IncludePath($p)
{
$handle = opendir($p);
if ($handle) {
while ($file = readdir($handle)) {
if($file != "Lib.php" && $file != "." && $file != ".."){
if(is_file("$p\\$file")) require_once($p.'\\'.$file);
else __IncludePath("$p\\$file");
}
}
closedir($handle);
}
}
__IncludePath($path);
?>
File này có tác dụng include tất cả các file trong thư mục Lib và trong Folder con của nó.
III/ tạo một lớp kết nối MySQL
cái này cũng không cần thiết lắm, nhưng tốt nhất bạn cứ làm riêng ra cho dễ sử dụng và code một cách trong sáng hơn.
Bây giờ đã có file Lib.php, bạn có thể tạo các file với bất cứ tên gì và đặt trong Folder Lib.(cùng với file Lib.php)
đây là file của mình, bạn có thể tham khảo.
PHP Code:
<?php
class Config
{
function Config(){
}
public static $host = "localhost";
public static $user = "root";
public static $pass = "admin";
public static $data = "manager";
public static $tbfix = "manager_";
public static $count = 0;
}
class MySQL extends config
{
public static $conn = NULL;
function MySQL()
{
$this->connect();
}
public static function connect()
{
self::$conn = mysql_connect(
self::$host,
self::$user,
self::$pass,
TRUE
)or die (mysql_error());
mysql_select_db(
self::$data,
self::$conn
) or die (mysql_error());
mysql_query("SET NAMES 'utf8'");
}
public static function disconnect() {
if (is_resource(self::$conn)){
mysql_close(self::$conn);
}
}
public static function query($query){
if (!is_resource(self::$conn)) self::connect();
$result = mysql_query(
$query,
self::$conn
) or die (Log::Write(array(
"Key1" => "ErroMySql",
"Key2" => "Query",
"Msg" => "<div> Câu lệnh thực hiện:<b>$query</b></div>Nội dung<div>".mysql_error()."</div>"
),null,true));
if($result) return $result;
return false;
}
public static function select($table,$field=NULL,$where = NULL,$orderBy = NULL,$limit = NULL){
if(strlen($table) != 0){
if(strlen($field) == 0) $field = '*';
$sql = "select $field from ".self::$tbfix.$table;
if($where != NULL) $sql .= " where $where";
if($orderBy != NULL) $sql .= " order by ".$orderBy;
if($limit != NULL) $sql .= " limit $limit";
return self::query($sql);
}
}
public static function getCountRows($table,$where = NULL)
{
$sql = "select count(*) as rows from ".self::$tbfix.$table;
if(strlen($where)>0) $sql .= " where $where";
$resultRows = mysql_fetch_array(self::query($sql));
return $resultRows***91;'rows'***93;;
}
public static function insert($table,$all){
$sql = "insert into ".self::$tbfix.$table;
$i=0;
foreach($all as $field => $value)
{
if($i>0)
{
$fields .= ",";
$values .= ",";
}
$value = str_replace("'","''",$value);
$fields .= "$field";
$values .= "'$value'";
$i++;
}
$sql = "$sql ($fields) values ($values)";
if(self::query($sql)) return self::LastID($table);
return false;
}
public static function update($table = NULL,$all = NULL,$dk = NULL){
//if($table)
if($dk != NULL){
if(self::getCountRows($table,$dk)==0)
{
Log::Write(array(
"Key1" => "ErroMySql",
"Key2" => "NotFoundObjectUpdate",
"Msg" => "Bảng: $table<br> $dk<br>"
),$all,true);
return;
}
$sql = "update ".self::$tbfix.$table." set";
$i=0;
foreach($all as $field => $value)
{
if($i>0) $up.=',';
$value = str_replace("'","''",$value);
$up .=" $field = '$value'";
$i++;
}
$sql = "$sql $up where $dk";
return self::query($sql);
}
}
public static function LastID($table)
{
$result = MySQL::query("SELECT LAST_INSERT_ID() AS lastInsertID FROM ".self::$tbfix.$table);
$row = mysql_fetch_row($result); $rs = $row***91;0***93;;
return $rs;
}
public static function Del($table,$where){
$sql = "delete from ".self::$tbfix.$table." where $where";
self::query($sql);
}
}
?>
tuy nó hơi loằng ngoằng mì tôm chút nhưng sau này công việc của bạn sẽ đỡ mệt hơn.
IV/ Tạo một lớp đại diện cho table trong CSDL
Điều này là rất quan trọng đối với hướng lập trình này,
Nó mang tất cả những điều cần có liên quan tới CSDL, ví dụ hàm insert, update, delete, select sẽ xuất hiện tất cả trong đối tượng này. tới bước này mình chưa thể giải thích tường tận, qua bước sau bạn sẽ hiểu nó quan trọng như thế nào, và bước này là bước phiền phức nhất, nhưng không sao, đối với lập trình hướng đối tượng bạn có thể cải thiện nó một cách dễ dàng mà không một một chút công sức nào. đây là file của mình, từ sau trở đi mình sẽ dựa vào nó để giải thích, bạn có thể làm theo một hướng tốt hơn đối với bạn.
PHP Code:
<?php
class ObjectDB
{
/**
* Các bạn nhớ kỹ, đối tượng ở lớp này mình nói ở đây là đại diện cho một dòng dữ liệu trong table.
* Biến lưu trữ các cột trong đối tượng
*/
public $DB_Fields = null; //***91;0***93; Name, ***91;1***93; is auto, ***91;2***93; is PK(Lưu trữ các field trong CSDL sẽ khởi tạo sau)
public $DB_Table = null; // tên của Table cho đối tượng, sẽ khởi tạo sau
private $Limit = null; // khởi tạo sau khi gọi ham SetLimit(int $limit)
private $exist = null; // Xác định đối tượng có tồn tại hay không(biến lưu trữ, tránh trường hợp kiểm tra nhiều lần)
public $checkErrField; // Biến Bol xác định có kiểm tra lỗi hay không(không quan trọng)
private $LastWhere; // Lưu điều kiện cuối cùng khi sử dụng lệnh select, để đếm dòng thôi, không quan trọng
/**
* Phương thức khởi tạo
*
* @access public
* @param array()/Pk feild(int,string) $arr Khởi tạo các giá trị cho đối tượng(array()), lấy đối tượng nếu $arr = PK value
* @param Bol $checkErr Thiết lập phương thức kiểm tra lỗi Feild, có hoặc không
*/
function ObjectDB($arr = null,$checkErr = true)
{
$this->checkErrField = $checkErr;
$this->Install(); //sau khi khởi tạo, sẽ chạy hàm Install() để khởi tạo đối tượng, bạn sẽ hiểu sau.
$this->InstallField();// tạo field cho đối tượng sau khi nhận được field từ hàm Install()
if($arr) //nếu truyền vào mảng sẽ gọi hàm SetValue để khởi tạo giá trị cho đối tượng
{
$this->SetValue($arr,$checkErr);
if(!is_array($arr)) $this->GetInfo();
}
}
function Install(){} //Khai báo hàm phụ, không cần thiết, nhưng tránh cho khỏi lỗi nếu quên thôi
private function InstallField()
{//cái này đọc không hiểu thì mình cũng chịu, không biết giải thích thế nào
if(count($this->DB_Fields)==0) $this->ShowErro("not set DB_Fields on Object <b>".get_class($this)."</b>"); // cái ShowErro này là chỉ là phụ thôi, báo lỗi ra cho đỡ phải tìm phiền phức
if(!$this->DB_Table) $this->ShowErro("not set DB_Table on Object <b>".get_class($this)."</b>");
foreach($this->DB_Fields as $field => $opt)
{
$this->{$field} = null; // gán field cho đối tượng. VD: khai báo Field ID thì khi đó sẽ có thêm Biến là $this->ID cách khai báo sẽ hướng đẫn ở dưới
}
}
/**
* lấy đối tượng từ database
*
* @access public
* @param string $where truyền vào điều kiện lấy dữ liệu, tự tạo bằng phương thức $this->SetFieldWhere();
*/
function GetInfo($where = null) // cái này chính là hàm select lấy một dựa vào điều kiện, nếu đã có PK(Primari key) thì không cần truyền $where
{
if(!$where) $where = $this->SetFieldWhere(); //lấy điều kiện với PK field, sẽ hiểu ở lớp dưới
if(!$where) return false;
$rs = MySQL::select($this->DB_Table,"*",$where); // cái này phải cố hiểu thôi :(
$rs = mysql_fetch_array($rs);
if(!$rs){
$this->exits = false;
return false;
}
$this->SetValue($rs);// khi lấy được dữ liệu sẽ thiết đặt giá trị cho đối tượng
$this->exist = true;
return true;
}
/**
* Lấy danh sách đối tượng.
*
* @access public
* @param string $where truyền vào điều kiện lấy dữ liệu, lấy tất cả nếu null;
* @param int $page Trang thứ $page trong lần lấy dữ liệu, bắt buộc thiết lập $limit qua $this->SetLimit($limit)
* @param string/array() $order cách sắp xếp trong lần lấy dữ liệu, default theo Pk của đối tượng
* @param ASC|DESC $by cach sap xep
*/
function Gets($where = null,$page = null,$order = null,$by = null) //cái hàm này cũng tương tự như hàm trên, nhưng thay vào đó nó lấy ra một danh sách(array) đối tượng chứ không phải một đối tượng
{
$bgRow = $this->GetBgRow($page);//tính toán để lấy dòng bắt đầu select, nếu truyền vào $page, trước đó phải set $this->limit trước ($this->SetLimit(int $limit))
$limit = null;
if($page)
{
if($page<1) $page = 1;
$limit = "$bgRow,".$this->Limit;
}
if($order)
{
$field = '';
if(is_string($order)) $field = $this->CheckField($order); //kiểm tra xem truyền vào có đúng tên cột không, tránh trường hợp nó hack CSDL
elseif(is_array($order)) foreach($order as $f){ // có thể truyền vào một array
if($field) $field .= ',';
$field .= $this->CheckField($f);
}
if(!$field){//cái này là lớp riêng của mình để ghi lỗi, từ giờ bạn không cần quan tâm đến lớp này (Log)
Log::Write(array(
'Key1' => 'ErroObject',
'Key2' => 'NotFoundOrderField',
),$order);
return array(); // trả về array trống để tránh lỗi khi duyệt foreach()
}
}
if($by) //kiểm tra xem truyền vào cách sắp xếp có đúng không
{
$by = strtolower(str_replace(' ','',$by));
if($by == 'asc' || $by == 'desc');
else
{
Log::Write(array(
'Key1' => 'ErroObject',
'Key2' => 'OrderByIsIncorrect',
'Msg' => 'Thiết đặt từ khoá sắp xếp không đúng'
),$by);
return array();
}
}
if($field) $order = $field.' '.$by;
$rs = MySQL::select($this->DB_Table,"*",$where,$order,$limit);
$list = array();
while($row = mysql_fetch_array($rs))
{
$class = get_class($this); //Tạo mới đối tượng để truyền vào danh sách
$list***91;***93; = new $class($row);
}
$this->LastWhere = $where;
return $list;// trả về danh sách
}
function FullText($key,$page = null) // không cần quan tâm
{
if(!$this->FieldsFullText) return false;
return $this->Gets("MATCH(".$this->FieldsFullText.") against('$key')",$page);
}
private function GetBgRow($page)
{
$bgRow = $this->Limit * ($page-1);
return $bgRow;
}
/**
* lấy tổng số bản ghi trong lần lấy dữ liệu trước.
*
* return int
*/
function GetTotalRow()
{
return MySQL::getCountRows($this->DB_Table,$this->LastWhere);
}
/**
* Ghi đối tượng vào cơ sở dữ liệu
*
* Return
* true/false Thành công/thất bại
*/
function Insert()// ghi đối tượng vào CSDL
{
$rs = MySQL::insert($this->DB_Table,$this->SetFieldValue());
return MySQL::LastID($this->DB_Table); //trả về PK mới tạo khi Ghi dữ liệu
}
/**
* Cập nhật đối tượng
* @access public
* @param string $where điều kiện cập nhật, tự tạo nếu null $this->SetFieldWhere();
* @param array $arr dữ liệu cập nhật, tự tạo nếu null $this->SetFieldValue()
*/
function Update($where = null, $arr = null) // cập nhật dữ liệu vào CSDL
{
if(!$where) $where = $this->SetFieldWhere();//nếu không truyền điều kiện, sẽ lấy điều kiện mặc định bằng PK
if($arr == null) $arr = $this->SetFieldValue(); //chuyển các giá trị tồn tại cho việc cập nhật, những hàm này phía trên có sử dụng
return MySQL::update($this->DB_Table,$arr,$where);
}
/**
* Xoá đối tượng trên database
*
* @access public
* @param string $where điều kiện xoá đối tượng, xoá đối tượng này nếu null
*/
function Delete($where = null) // xóa đối tượng trong CSDL
{
if(!$where) $where = $this->SetFieldWhere();
return MySQL::Del($this->DB_Table,$where);
}
private function SetFieldValue() // lấy những đối giá trị có tồn tại trong đối tượng
{
$InputVal = array();
foreach($this->DB_Fields as $field => $opt)
{
if(!$opt***91;0***93; && $this->{$field}!= null) $InputVal***91;$field***93; = $this->{$field};
}
return $InputVal; // trả về array
}
private function SetFieldWhere() // lấy điều kiện thông qua PK
{
$where = "";
$i = false;
foreach($this->DB_Fields as $field => $opt)
{
if($opt***91;1***93;){
if($i) $where .= " and ";
$where .= "$field = '".$this->{$field}."'";
$i = true;
}
}
if(!$i) $this->ShowErro("not set PK on Object <b>".get_class($this)."</b>"); // thông báo lỗi khi không tồn tại PK, cái PK này phải thiết lập trước
return $where; // trả về điều kiện
}
/**
* Thiết đặt giá trị giới hạn cho mỗi trang
*
* @access public
* @param int $limit số đối tượng được lấy ra trong mỗi lần sử dụng phương thức Gets()
*/
function SetLimit($limit)
{
if($limit) $this->Limit = $limit;
}
/**
* Thiết đặt giá trị cho đối tượng
*
* @access public
* @param array()/Pk feild(int,string) $arr Những giá trị cho đối tượng, đặt PK nếu không phải array()
* @param Bol $checkErr Thiết lập phương thức kiểm tra lỗi Feild, có hoặc không
*/
function SetValue($arrVal,$checkErr = true) //thiết đặt giá trị cho đối tượng, hàm này có một chút biến hóa, bạn nên đọc kỹ
{
$this->checkErrField = $checkErr;
if(!is_array($arrVal)){ // giá trị truyền vào không phải array sẽ set giá trị cho PK
foreach($this->DB_Fields as $field => $opt)
{
if($opt***91;1***93;){ // $opt***91;1***93; ở đây là kiểm tra xem field có phải PK không, cái này được thiết đặt ở lớp dưới.
$this->{$field} = $arrVal;
return;
}
}
}else{ // trường hợp truyền vào array
foreach($arrVal as $field => $val)
{
$field = $this->CheckField($field); //kiểm tra xem field có tồn tại không, và trả về tên field nếu index là số int
if($field)$this->{$field} = $val;
}
}
}
/**
* Đặt khoá cho cột
*
* @access public
* @param string/aray $fields tên cột hoặc Danh sách tên cột array(array('feild1' => bol,'feild1' => bol, ...))
* @param bol $bol true/false thiết đặt, huỷ bỏ
*
*/
function SetPK($fields,$bol = true)// thiết đặt khóa cho đối tượng, khi là khóa, field sẽ được lấy làm điều kiện khi update hoặc xóa đối tượng trong CSDL
{
if(!is_array($fields)) $this->DB_Fields***91;$field***93;***91;1***93; = $bol;
else foreach($fields as $field){
$this->SetPK($field***91;0***93;,$field***91;1***93;);
}
}
/**
* Đặt giá trị auto update cho cột / không sử dụng trong mỗi lần ghi đối tượng
*
* @access public
* @param string/aray $fields tên cột hoặc Danh sách tên cột array(array('feild1' => bol,'feild1' => bol, ...))
* @param bol $bol true/false thiết đặt, huỷ bỏ
*
*/
function SetAuto($field,$bol = true) //thiết đặt field tự động cập nhật, khi là là field tự động cập nhật sẽ không được insert hay update vào CSDL
{
if(!is_array($fields)){
$field = $this->CheckField($field);
$this->DB_Fields***91;$field***93;***91;0***93; = $bol;
}
else foreach($fields as $field){
$this->SetAuto($field***91;0***93;,$field***91;1***93;);
}
}
private function CheckField($fieldIn) // hàm kiểm tra vả trả về tên field
{
$i=0;
foreach($this->DB_Fields as $field => $opt){
if($fieldIn == $field || ($fieldIn == $i && is_int($fieldIn))) return $field;
$i++;
}
if($this->checkErrField){
$this->ShowErro("Field index '$fieldIn' not found of Object ".get_class($this)."</b>");
}
return false;
}
/**
* Trả về array giá trị đối tượng
*/
function ToArray()// trả về array giá trị của đối tượng
{
$arr = array();
foreach($this->DB_Fields as $field => $opt){
$arr***91;$field***93; = $this->{$field};
}
return $arr;
}
/**
* Kiểm tra một đối tượng có tồn tại không
*/
function Exist() // kiểm tra sự tồn tại của đối tượng trong CSDL
{
if($this->exits == null) $this->GetInfo();
return $this->exist;
}
private function ShowErro($msg)
{
echo $msg;
exit();
}
}
?>
Ôi mệt thật
Trên lớp trên mình có ghi chú thích tường tận cho mỗi bước, để hiểu rõ hơn về lớp trên dùng để làm gì, dưới đây sẽ là một vài vd minh họa.
Chú ý: bạn nên đổi tên file của lớp trên để nó được include đầu tiên, nếu không sẽ sảy ra lỗi,VD thêm dấu "." ở trước tên file để nó được đưa lên đầu.
VD1: trong CSDL bạn có một table Category như sau;
Field: ID: int(kiểu int) PK(Primary key) Auto increment(tự tăng mỗi khi insert)
Field: Name: varchar(kiểu string, chuỗi ngắn)
Field: Comment: text(kiểu string,văn bản)
viết đối tượng cho table này:
PHP Code:
<?php
class CategoryObj extends ObjectDB // lớp CategoryObj kế thừa lớp trên tên CategoryObj có thể tùy bạn, muốn đặt tên như thế nào cũng được.
{
function Install() //hàm khởi tạo đối tượng, thiết đặt các Option cho đối tượng này
{
$this->DB_Table = "Category"; //Thiết đặt tên của Table tham chiếu cho đối tượng
$this->DB_Fields = array( //thiết đặt các field cho đối tượng
"ID" => array(true,true),//Field ID: true 1 = PK, true 2 = Auto
"Name" => array(),//Field: Name, không phải PK cũng không auto nên không cần thiết đặt, bạn có thể thiết đặt false, false tùy ý.
"Comment"=>array()//như trên
);
}
}
?>
chỉ như vậy bạn đã có một đối tượng CSDL, trước đây nó không đơn giản nhưng giờ thì đơn giản rồi đó, vậy làm thế nào để sử dụng.
// những file thực thi bạn không được bỏ vào thư mục Lid đâu nhé.
1/ ghi mới vào CSDL
PHP Code:
<?php
include('Lib/Lib.php'); // include file thư viện
$cate = new CategoryObj(array(
"Name" => "Thư viện",
"Comment" => "lời comment thứ nhất"
));
$cate->Insert();
$cate = new CategoryObj(array( //truyền vào theo index field
null, // bắt buộc, vì field***91;0***93; là ID
"Tự học PHP",
"lời comment thứ 2"
));
$cate->Insert();
$cate = new CategoryObj();
$cate->SetValue(array( // truyền giá trị như hai vd trên
"Name" => "Học MySQL",
"Comment" => "lời comment thứ 3"
));
$cate->Insert();
$cate->SetValue(array( // không cần tạo mới đối tượng vì đã khởi tạo ở trên
"Name" => "lập trình"
));
$cate->Insert();
$cate->SetValue(array( // không cần tạo mới đối tượng vì đã khởi tạo ở trên
"Name" => "học xtemplate",
"Action"=> "Insert",
"Page" => "19"
),false);//đặt false ở biến thứ hai để bỏ qua quá trình kiểm tra lỗi field
//có thể truyền vào các field không có trong đối tượng, trường hợp cụ thể như là bạn có một form, đặt tên tương đương với các field trong đối tượng và có một số không có thì bạn có thể truyền trực tiếp $cate->SetValue($_POST);
$cate->Insert();
?>
vậy đó, đó là quá trình ghi dữ liệu, tuy hơi dài dòng nhưng có phải rất dễ hiểu không? sau này sửa lại cũng rất chi là đơn giản.
vậy insert xong rồi thì làm thế nào để lấy dữ liệu?
2/ lấy dữ liệu
PHP Code:
<?php
include('Lib/Lib.php'); // include file thư viện
$cate = new CategoryObj(1); //truyền vào PK
echo $cate->ID;
echo $cate->Comment;
$cate = new CategoryObj()// không truyền vào PK
$cate->GetInfo("ID = 2"); // thiết đặt điều kiện
echo $cate->ID;
echo $cate->Comment;
$cate = new CategoryObj()// không truyền vào PK
$cate->SetValue(3)//Thiết đặt PK
$cate->GetInfo();
echo $cate->ID;
echo $cate->Comment;
$cate = new CategoryObj()// không truyền vào PK
$cate->SetValue(3)//Thiết đặt PK
$cate->GetInfo();
$c = $cate->ToArray(); // chuyển dữ liệu về dạng array
echo $c***91;'ID'***93;;
// lấy danh sách
$cate = new CategoryObj()// không truyền vào PK
$danhsach = $cate->Gets(); // lấy tất cả dữ liệu
foreach($danhsach as $c)
{
echo $c->ID;
echo $c->Comment;
}
$cate = new CategoryObj()// không truyền vào PK
$danhsach = $cate->Gets("Name like '%học%'"); // lấy tất cả dữ liệu với điều kiện
foreach($danhsach as $c)
{
echo $c->ID;
echo $c->Comment;
}
$cate = new CategoryObj()// không truyền vào PK
$cate->SetLimit(3); // giới hạn lấy 3 dòng dữ liệu
$danhsach = $cate->Gets("Name like '%học%'",1); // lấy tất cả dữ liệu với điều kiện và phân trang
foreach($danhsach as $c)
{
echo $c->ID;
echo $c->Comment;
}
$cate = new CategoryObj()// không truyền vào PK
$danhsach = $cate->Gets(null,null,"Name","ASC"); // lấy tất cả dữ liệu và sắp xếp, ASC hoặc DESC theo field Name
foreach($danhsach as $c)
{
echo $c->ID;
echo $c->Comment;
}
$cate = new CategoryObj()// không truyền vào PK
$danhsach = $cate->Gets(null,null,array('Name','Comment'),"ASC"); // lấy tất cả dữ liệu và sắp xếp, ASC hoặc DESC theo field Name và field Comment, sắp xếp Name trước rồi tới Comment
foreach($danhsach as $c)
{
echo $c->ID;
echo $c->Comment;
}
?>
như vậy là xong quá trình lấy dữ liệu bây giờ thử cập nhật dữ liệu nhé
Bookmarks