7. YII LÀ GÌ?
Yii là component có tính thể hiện cao -
framework PHP căn bản cho lập trình các
ứng dụng web có kích cỡ lớn. Nó có khả
năng tái sử dụng lớn trong các chương trình
web và có thể đẩy nhanh đáng kể quá trình
lập trình.
9. THE MVC PATTERN
MVC là mẫu thiết kế mở
rộng theo hướng lập trình
web nhằm chia các công
việc một cách logic từ giao
diện người dùng, để các lập
trình viên có thể dễ dàng
thay đỗi từng phần mà
không ảnh hưởng đến phần
khác.
10. THE MVC PATTERN
Giả sử một ứng dụng Web gồm có nhiều ứng dụng
con:
• Front end:webstie công khai cho người dùng bình thường;
• Back end: website có tiện ích quản trị dành cho
việc quản lý ứng dụng.
• Console: Ứng dụng gồm có các câu lệnh điều khiển chạy
ở cửa sổ terminal hoặc các công việc được đặt lịch để hỗ
trợ cho toàn ứng dụng;
• Web API: Cung cấp giao diện tới bên thứ ba để tích
hợp vào ứng dụng.
11. M for MODEL
Models được sử dụng để lưu trữ dữ liệu và các quy tắc công việc
liên quan. Model tiêu biểu cho một đối tượng dữ liệu đơn lẻ, có thể
là một hàng trong một bảng cơ sở dữ liệu hoặc là các phần nhập
vào form của người dùng.
• nên chứa các thuộc tính đại diện cho dữ liệu đặc thù;
• nên chứa công việc một cách logic (ví dụ: các quy tắc chuẩn
hóa) để chắc chắn dữ liệu tiêu biểu thi hành các yêu cầu thiết
kế;
• có thể chứa mã để thao tác dữ liệu. Ví dụ, một model SearchForm
tiêu biểu cho việc tìm kiếm dữ liệu dữ liệu nhập vào, có thể chứa
phương thức search để thực hiện việc tìm kiếm thực sự.
12. C for CONTROLLER
Controller là chất keo gắn models, views và các thành phần
khác lại với nhau trong một ứng dụng chạy được. Chúng đáp
ứng việc giao dịch trực tiếp với các yêu cầu của người dùng
cuối.
• Có thể truy cập $_GET, $_POST và các biến PHP khác,
tiêu biểu cho các yêu cầu của người dùng;
• có thể tạo các đối tượng model và quản lý vòng đời của chúng.
• nên tránh việc chứa các câu lệnh SQL nhúng vào, chúng tốt
hơn nên được để trong model.
• nên tránh việc chứa bất kỳ mã HTML hoặc bất kỳ ngôn ngữ
đánh dấu thể hiện nào khác. Nó tốt hơn nên để trong views.
13. V for VIEW
View là chương trình PHP gồm có phần lớn các phần tử của giao diện người dùng
dựa trên sự phân tách giữa logic và trình bày, phần lớn đoạn logic nên được đặt
trong controller hoặc model thay vì để trong view.
• nên chứa phần lớn mã trình bày, như HTML và mã PHP đơn
giản để duyệt, định dạng và render dữ liệu;
• nên tránh chứa mã thể hiện các câu truy vấn db rõ ràng.
Mã như vậy nên để ở models.
• nên tránh truy cập trực tiếp tới $_GET, $_POST, hoặc các
biến tương tự khác tiêu biểu cho các yêu cầu của người dùng
cuối. Đây là công việc của controller.
15. TOÀN BỘ CHƯƠNG TRÌNH
Đây là file "bootstrap", nghĩa là tất cả các tương tác người dùng đều qua
nó. Ví dụ như để hiển thị bản nghi nhân viên thì phải thông qua URL. Nó
chỉ là mã PHP mà người dùng cuối có thể yêu cầu trực tiếp thực thi.
// Bỏ dòng này đi nếu ở chế độ sản phẩm
defined('YII_DEBUG') or define('YII_DEBUG',true);
// include file bootstrap Yii
require_once('path/to/yii/framework/yii.php');
// Tạo một thể hiện của ứng dụng và chạy nó
$configFile='path/to/config/file.php';
Yii::createWebApplication($configFile)->run();
16. YII WORKFLOW
1 – Yêu cầu bằng URL
http://example.com/index.php?r=post/
show&id=1 và Web server kiểm soát yêu
cầu này bằng cách thực thi chương trình
khởi động index.php.
2 - Mã khởi động tạo ra một thể hiện của ứng
dụng và chạy nó.
3 - Ứng dụng thu được thông tin yêu cầu chi
tiết của người dùng từ một thành phần ứng
dụng đặt tên là request.
4 - Ứng dụng xác định cotroller nào được yêu cầu
và thực thi với sự giúp đỡ của thành phần ứng
dụng tên là urlManager.
17. YII WORKFLOW
5 - Ứng dụng tạo ra một thể hiện của controller
được yêu cầu để kiểm soát xa hơn yêu cầu của
người dùng. Controller xác định rằng chương
trình hành động này chuyển đến phương thức đặt
tên là actionShow trong lớp controller.
6 - Hành động này đọc model Post có ID là 1 từ cơ
sở dữ liệu.
7 - Hành động này render view đặt tên là show
với model Post.
8 - View đọc và hiển thị các thuộc tính của model
Post.
9,10,11 - View thực thi một số widget, nhúng
kết quả đã render trong layout và hiển thị nó tới
người dùng.
18. OK, OK, I GOT IT, TOO MUCH TALK..
CHÚNG TA CÙNG CÓ Ý TƯỞNG ĐỂ XÂY DỰNG..
21. BLOG!
OK, NÓ KHÔNG TUYỆT VỜI NHƯNG VỚI ĐIỀU
NÀY TÔI CHẮC CHẮN LÀ TẤT CẢ CÁC BẠN
BIẾT ĐƯỢC CHÚNG TA SẼ XÂY DỰNG CÁI GÌ
22. KHỞI ĐỘNG
• TẠO MỘT THƯ MỤC “BLOGDEMO”
TRONG THƯ MỤC GỐC APACHE
CỦA BẠN
• TẢI FILE YiiBlogDemo.zip TỪ
http://goo.gl/nOqef VÀ GIẢI NÉN
NÓ
• MỞ FRAMEWORK.ZIP VÀ ĐẶT
NỘI DUNG CỦA NÓ TRONG
THƯ MỤC “BLOGDEMO”
23. CHUẨN BỊ Yii
Chạy câu lệnh console đơn giản
“blogdemo/framework/yiic webapp ../“
để tạo ra bộ khung ứng dụng Web xây dựng với Yii.
Điều này sẽ tạo một khung ứng dụng Yii ở thư mục
WebRoot/testdrive.
24. ỨNG DỤNG WEB
Ứng dụng này có đầy đủ chức năng, với các đặc trưng như người
dùng đăng nhập và form liên hệ. Đó là điểm bắt đầu tốt cho việc
thực hiện các đặc trưng phức tạp hơn.
25. BLOG THƯỜNG CÓ GÌ?
• BÀI VIẾT
• NGƯỜI DÙNG
• BÌNH LUẬN
• TAG
28. SINH MODELS
Chúng ta cần tạo lớp model cho các bảng cơ sở dữ liệu. Yii có một thành phần
tuyệt vời là Gii nó hoàn toàn tự động tiến trình này (gọi là scaffolding) cho
chúng ta.
'modules'=>array(
'gii'=>array(
'class'=>'system.gii.GiiModule',
'password'=>'pick up a password here',
),
),
30. CÁC MODEL TA CÓ
• User.php chứa lớp User và có thể được sử dụng để truy xuất
bảng tbl_user;
• Post.php chứa lớp Post và có thể được sử dụng để truy xuất
bảng tbl_post;
• Tag.php chứa lớp Tag và có thể được sử dụng để truy xuất bảng
tbl_tag;
• Comment.php chứa lớp Comment và có thể được sử dụng để
truy xuất bảng tbl_comment;
• Lookup.php chứa lớp Lookup và có thể được sử dụng để
truy xuất bảng tbl_lookup.
31. CRUD OPERATIONS
Sau khi tạo các lớp model, ta có thể sử dụng Crud
Generator để sinh ra mã thực thi CRUD operation cho
những model này. Chúng ta sẽ làm điều này cho các model
Post và Comment.
32. AUTHENTICATING USER
Ứng dụng blog của ta cần phân biệt giữa chủ hệ thống
và người dùng vãng lai. Vì vậy, ta cần thực hiện tính
năng xác thực người dùng
Xác thực người dùng được thực thi trong class thực hiện
giao diện IUserIdentity. Khung ứng dụng sử dụng lớp
UserIdentity cho mục đích này.
Lớp này được lưu trong file /wwwroot/blogdemo/
protected/components/UserIdentity.php.
33. AUTHENTICATING USER
Ứng dụng đã cung cấp xác thực người dùng bằng
cách kiểm tra username và password đều là demo
hoặc admin.
Bây giờ ta sẽ chỉnh sửa mã tương ứng để việc xác
thực được hoàn thiện dựa trên bảng User.
34. EDITING USERIDENTITY.PHP
public function authenticate()
{
$username=strtolower($this->username);
$user=User::model()->find('LOWER(username)=?',array($username));
if($user===null)
$this->errorCode=self::ERROR_USERNAME_INVALID;
else if(!$user->validatePassword($this->password))
$this->errorCode=self::ERROR_PASSWORD_INVALID;
else
{
$this->_id=$user->id;
$this->username=$user->username;
$this->errorCode=self::ERROR_NONE;
}
return $this->errorCode==self::ERROR_NONE;
}
public function getId()
{
return $this->_id;
}
35. RECAP
• Xác định các yêu cầu cần hoàn thiện;
• Chúng ta cài đặt Yii framework và tạo khung ứng
dụng;
• Chúng ta thiết kế và tạo cơ sở dữ liệu của blog;
• Chúng ta tạo ra CRUD operation cơ bản;
• Chúng ta chỉnh sửa phương thức xác thực để
kiểm tra dựa vào bảng tbl_user.
36. CUSTOMIZING POST MODEL
Việc sinh model Post là được rồi nhưng giờ chúng ta cần
chỉ rõ các quy tắc chuẩn hóa và các đối tượng liên quan
• Các quy tắc chuẩn hóa đảm bảo các giá trị của thuộc tính
đưa vào bởi người dùng là chuẩn xác trước khi chúng
được lưu vào cơ sở dữ liệu. Ví dụ, trạng thái thuộc tính
của Post sẽ là số 1,2, hoặc 3.
• Tùy biến quan hệ chúng ta có thể khai thác sức mạnh của
đặc tính bản ghi quan hệ hiện thời (Relational
ActiveRecord (RAR)) để truy xuất thông tin đối tượng
liên quan của bài viết,ví dụ như tác giả và bình luận của
bài viết, không cần đến việc viết các câu lệnh SQL phức
tạp.
37. VALIDATION RULES
Dựa trên yêu cầu vừa phân tích, chúng ta chỉnh
sửa phương thức rules() như sau:
public function rules()
{
return array(
array('title, content, status', 'required'),
array('title', 'length', 'max'=>128),
array('status', 'in', 'range'=>array(1,2,3)),
array('tags', 'match', 'pattern'=>'/^[ws,]+$/',
'message'=>'Tags can only contain word characters.'),
array('tags', 'normalizeTags'),
array('title, status', 'safe', 'on'=>'search'),
);
}
38. MODEL RELATIONS
Chúng ta tùy biến phương thức relations() như sau:
public function relations()
{
return array(
'author' => array(self::BELONGS_TO, 'User', 'author_id'),
'comments' => array(self::HAS_MANY, 'Comment', 'post_id',
'condition'=>'comments.status='.Comment::STATUS_APPROVED,
'order'=>'comments.create_time DESC'),
'commentCount' => array(self::STAT, 'Comment', 'post_id',
'condition'=>'status='.Comment::STATUS_APPROVED),
);
}
Chúng ta cũng giới thiệu trong lớp class Comment extends CActiveRecord
{
model Comment hai hằng số sử const STATUS_PENDING=1;
dụng ở phương thức trên: const STATUS_APPROVED=2;
......
}
39. REPRESENTING STATUS IN TEXT
Vì trạng thái của bài viết được lưu vào cơ sở dữ liệu dưới dạng
số, nên chúng ta cần cung cấp văn bản đại diện để nó trực
quan hơn khi được hiển thị tới nhiều người dùng cuối. Ở hệ
thống lớn, yêu cầu như vậy là rất phổ biến.
Như một giải pháp chúng, chúng ta sử dụng bảng tbl_lookup
để lưu bản đồ giữa các giá trị số và các văn bản đại diện, nó
cần thiết cho những đối tượng dữ liệu khác nữa.
Chúng ta chỉnh sửa lớp model Lookup như sau để truy cập dễ
dàng hơn vào dữ liệu văn bản trong bảng.
40. LOOKUP.PHP
class Lookup extends CActiveRecord
{
private static $_items=array();
public static function items($type)
{
if(!isset(self::$_items[$type]))
self::loadItems($type);
return self::$_items[$type];
}
public static function item($type,$code)
{
if(!isset(self::$_items[$type]))
self::loadItems($type);
return isset(self::$_items[$type][$code]) ? self::$_items[$type][$code] : false;
}
private static function loadItems($type)
{
self::$_items[$type]=array();
$models=self::model()->findAll(array(
'condition'=>'type=:type',
'params'=>array(':type'=>$type),
'order'=>'position',
));
foreach($models as $model)
self::$_items[$type][$model->code]=$model->name;
}
}
41. POST POSSIBLE STATUSES
class Post extends CActiveRecord
{
const STATUS_DRAFT=1;
const STATUS_PUBLISHED=2;
const STATUS_ARCHIVED=3;
......
}
Bây giờ chúng ta có thể gọi Lookup::items('PostStatus') để
lấy danh sách của các trạng thái bài viết có thể (chuỗi văn
bản được đánh chỉ mục bằng các giá trị dạng số trả về), và
gọi Lookup::item('PostStatus',
Post::STATUS_PUBLISHED) để lấy chuỗi đại diện của
trạng thái được xuất bản.
42. CONFIGURING ACCESS RULES
public function accessRules()
{
return array(
array('allow', // cho phép tất cả người dùng thực thi các hành
động 'list' và 'show'
'actions'=>array('index', 'view'),
'users'=>array('*'),
),
array('allow', // cho phép người sử dụng đã được xác thực thực
thi bất kỳ hành động nào
'users'=>array('@'),
),
array('deny', // từ chối mọi người dùng
'users'=>array('*'),
),
);
}
Các trạng thái quy tắc: mọi người dùng có thể truy cập vào hành
động index và view, còn người dùng đã được xác thực thì có thể
truy cập vào bất kỳ hành động nào, kể cả hành động quản trị.
43. CREATE AND UPDATE
Các hoạt động tạo và cập nhật là tương tự. Cả hai cần hiển thị form
HTML để thu thập những cái người dùng nhập vào, chuẩn hóa
chúng, và lưu chúng vào cơ sở dữ liệu.
Gii sinh ra một phần của view /wwwroot/blog/protected/views/
post/_form.php nó được nhúng vào cả view tạo và cập nhật để
render ra form HTML cần thiết.
Chúng ta muốn thêm danh sách thả xuống để thu thập thông tin
nhập vào của người dùng cho thuộc tính STATUS
echo $form->dropDownList($model,'status',Lookup::items('PostStatus'));
44. CREATE AND UPDATE
Sau đó ta chỉnh sửa lớp Post để nó có thể tự động thiết lập một
vài thuộc tính (create_time, author_id) trước khi bài viết được
lưu vào cơ sở dữ liệu. Ta ghi đè lên phương thức beforeSave()
như sau
protected function beforeSave() {
if(parent::beforeSave())
{
if($this->isNewRecord)
{
$this->create_time=$this->update_time=time();
$this->author_id=Yii::app()->user->id;
}
else
$this->update_time=time();
return true;
}
else
return false;
}
53. BOOTSTRAP RESPONSIVENESS
Nó hỗ trợ một số media queries nằm trong một file đơn
giúp cho dự án của bạn thích hợp trên nhiều thiết bị và độ
phân giải màn hình khác nhau.
@media (min-width:400px) { }
54. Cảm ơn
Giuliano Iacobelli
giuliano.iacobelli
me@giulianoiacobelli.com
http://giulianoiacobelli.com
Connect with me:
Ps: slide 47 and 48 were borrowed from this amazing presentation of Brad Frost