09/10/2018, 23:32
MVC trong lập trình PHP.
Tìm hiểu cũng được một xíu kiến thức về MVC, nay viết bài này giới thiệu một số hiểu biết về lập trình 3 lớp với php.
MVC là gì, là viết tắt của Model, View, Controller.
Đây là cách người ta phân một ứng dụng ra làm 3 phần có chức năng khác nhau để dễ quản lí và phát triển các ứng dụng.
Tầng View là tầng ở vị trí cuối trong 3 tầng, nó đóng vai trò tạo giao diện cho người dùng. Tương tác với ứng dụng web của người dùng là tương tác trên giao diện đó là những thứ đc tạo ra, trình bày bởi tầng này.
Nhưng nếu chỉ có out put ra mà bạn không thể biết được người dùng làm gì, click, submit, gởi các HTTP request... thì ứng dụng web của bạn cũng chẳng có gì ngoài cái xác vô hồn. Khi đó để bắt đc, xử lí các sự kiện này chúng ta sẽ cần đến tầng Controller.
Tầng Controller dùng để quản lí, quyết định phương thức mà ứng dụng web của bạn sẽ đáp ứng cho các sự kiện, yêu cầu đến từ phía giao diện web của người dùng.
Đông thời tần này cũng đóng một vai trò là cầu nối đến một tầng khác đó là tầng Model, tần Controller sẽ gọi các phương thức để đáp ứng cho các yêu cầu, sự kiện đến từ phía người dùng ( tầng View) và các phương thức này gọi đến các phương thức tương ứng trên tầng Model để thực thi việc truy xuất Database một cách phù hợp.
Đó là mô hình 3 lớp rất phổ biến trong lập trình hiện nay. Kiến thức của tác giả bài viết còn có hạn, không tránh khỏi sai sót, xin vui lòng bổ sung nếu thiếu sót và có những vấn đề không đúng
Vì khuya nên hẹn các bạn vào ngày mai mình sẽ nêu phần ví dụ
Thân ái.
MVC là gì, là viết tắt của Model, View, Controller.
Đây là cách người ta phân một ứng dụng ra làm 3 phần có chức năng khác nhau để dễ quản lí và phát triển các ứng dụng.
Tầng View là tầng ở vị trí cuối trong 3 tầng, nó đóng vai trò tạo giao diện cho người dùng. Tương tác với ứng dụng web của người dùng là tương tác trên giao diện đó là những thứ đc tạo ra, trình bày bởi tầng này.
Nhưng nếu chỉ có out put ra mà bạn không thể biết được người dùng làm gì, click, submit, gởi các HTTP request... thì ứng dụng web của bạn cũng chẳng có gì ngoài cái xác vô hồn. Khi đó để bắt đc, xử lí các sự kiện này chúng ta sẽ cần đến tầng Controller.
Tầng Controller dùng để quản lí, quyết định phương thức mà ứng dụng web của bạn sẽ đáp ứng cho các sự kiện, yêu cầu đến từ phía giao diện web của người dùng.
Đông thời tần này cũng đóng một vai trò là cầu nối đến một tầng khác đó là tầng Model, tần Controller sẽ gọi các phương thức để đáp ứng cho các yêu cầu, sự kiện đến từ phía người dùng ( tầng View) và các phương thức này gọi đến các phương thức tương ứng trên tầng Model để thực thi việc truy xuất Database một cách phù hợp.
Đó là mô hình 3 lớp rất phổ biến trong lập trình hiện nay. Kiến thức của tác giả bài viết còn có hạn, không tránh khỏi sai sót, xin vui lòng bổ sung nếu thiếu sót và có những vấn đề không đúng
Vì khuya nên hẹn các bạn vào ngày mai mình sẽ nêu phần ví dụ
Thân ái.
Bài liên quan
Đợt này em phải làm cái project bằng php.Nhưng vì một số lý do kỹ thuật, em không được phép dùng các framework có sẵn ( huhu). Em đang lọ mọ thử làm cho nó có hơi hướng của MVC. Vít ra đây các pác nào có kinh nghiệm,hoặc có nhận xét gì thì cho em thảm khảo với nhé.
Ở đây em ví dụ user insert một số thông tin(có kiểu là rule) và save nó lại.
Ở phần Model, em làm một cái DAO (data base object) để giao tiếp với DB :
ruleDAO.php
<?php
include("connectDB.php");
include ("rule.php");
class RuleDAO {
function RuleDAO (){}
function insertRule ($rule)
{
$maxInDay = $rule->getMaxInDay();
$timeOpen = $rule->getTimeOpen();
$timeClose = $rule->getTimeClose;
db_connect();
$sql = "Insert into Rule (maxInDay,timeOpen,timeClose) values ('$maxInDay','$timeOpen','$timeClose'";
$result=mysql_query ($sql);
if ( !$result )
{ die("Can't do this request SQL: ".mysql_error());
mysql_close();
return false;
}
mysql_close();
return true;
}
}
?>
ruleService.php
<?php
include("ruleDAO.php");
class RuleService {
var $ruleDao ;
//function LoginService(){}
function insertRule ($rule)
{
$ruleDao = new RuleDAO;
return $ruleDao->insertRule($rule);
}
}
?>
Control, làm các lớp action sử dụng DAO :
<?php
include("ruleDAO.php");
include("rule.php");
class RuleAction{
var $ruleSer ;
var $rule;
function insertRule($maxInDay,$timeOpen,$timeClose)
{
$ruleSer = new RuleService;
$rule = new Rule;
$rule->setRule($maxInDay,$timeOpen,$timeClose);
$result = $ruleSer->insertRule($rule);
if($result) return true;
return false;
}
}
?>
("ruleCon.php")
<?php
include ("ruleAction.php");
include("rule.php");
$ruleAction = new RuleAction;
$result = $ruleAction->insertRule($maxInDay,$timeOpen,$timeClose );
if($result) include ("finish.php");
else include ("erro.php");
?>
Phần view :
<?php include("ruleCon.php")?>
<table width="659" cellpadding="10">
<tr>
<form method=post action="ruleCon.php" >
So luong ban nhieu nhat mot ngay : <input type=text size=3 name=maxInDay>
<br>
<br> Thoi gian mo cua : <input type=text size=6 name=timeOpen >
<br>
<br> Thoi gian dong cua : <input type=text size=6 name=timeClose>
<br> Thoi gian toi da nhan hang : <input type=text size=6 name=limitTime>
<br> <input type=submit name=submit value="Oke"> <br><br>
<input type=reset name=reset value="Zrusit"> </form>
</tr>
</table>
Chậc về php em cũng chưa rành lắm (mà em cũng chỉ đc dùng php4
Các tình yêu xem hộ về ý tưởng MVC vít thế này có ổn ko ? Em vẫn thấy cái phần control có vấn đề sao sao đó mà chưa nghĩ ra
Tôi gọi việc sử dụng DAO trong PHP theo cách này là một sai lầm vì nó không tính đến cấu trúc dữ liệu giản lược trong PHP cũng như một tính năng của PHP được biết đến như là virtual properties. Chính vì thế cách code này được gọi là code smell.
Đó là chuyện bình thường thôi. Ngay cả một Java architect chuyển sang làm PHP (kiến trúc sư trưởng của dự án Jobby) cũng mắc sai lầm này. Sai lầm của những người áp dụng design pattern từ lý thuyết thay vì nhìn từ thực tế như Gang of Four hướng dẫn.
DAO được sử dụng rất khác biệt ở cộng đồng PHP so với nguyên bản gố c được các ngôn ngữ định kiểu tĩnh như Java áp dụng. Bây giờ tôi sẽ cố gắng đưa ra các nguyên nhân tại sao tri thức buộc phải có sự thay đổi từ ngôn ngữ này sang ngôn ngữ kia.
+ Java hướng vào discipline trong khi PHP hướng vào flexibility. Cho nên cái mô hình JavaBean chẳng có nghĩa gì ở PHP mà thay vào đó PHP phủ định mô hình này bằng cách đưa vào open class và virtual property.
+ First-class citizen trong Java là class thì trong PHP là array.
+ Java có xu hướng phân nhỏ trách nhiệm cho các lớp trong việc định nghĩa các cấu trúc dữ liệu cơ bản (Array, Hash, Map...) còn PHP thì có xu hướng gộp chúng lại chừng nào còn gộp được.
+ Trong phát triển ứng dụng web, Java buộc mọi thứ phải tuân thủ mô hình servlet/jsp (kể cả JSF cũng được build trên stack đó) và nó buộc developer tiếp cận user input qua một đầu mối doGet/doPost trong khi đó PHP cho phép việc tiếp cận này tham gia vào mọi ngóc ngách của chu kì thực hiện vì nó được implement ở cấp độ global.
+ Trong khi hướng vào discipline, Java thấy rằng mô hình JavaBean cho phép tạo ra ràng buộc cho các nhà phát triển tiếp cận/tạo ra các dữ liệu có thể có được để kiểm soát thiết kế và kiểm soát lỗi trong khi đó với PHP, các nhà thiết kế ngôn ngữ không cho cách thiết kế như vậy là khôn ngoan và mô hình lớp mở chứng minh điều đó. Tuy nhiên mô hình lớp mở của PHP còn discipline chán chê so với Javascript, Python và Ruby. Với open class cho property thì mô hình JavaBean bị phá sản. Cái còn lại của JavaBean chính là tooling. Nếu lập trình viên PHP muốn có tooling thì cũng nên cần nhắc đến mô hình getter/mutator này tuy nhiên phải chấp nhận: ứng dụng chậm hơn, nhiều bộ nhớ hơn, thiết kế phức tạp hơn, code nhiều hơn và công tác lập kế hoạch cũng như thiết kế đòi hỏi nhiều thời gian hơn.
+ Do là ngôn ngữ lập trình hướng đối tượng, Java buộc phải tuân thủ luồng đi các đối tượng nghĩa là trừ khi đối tượng được khai báo singleton còn nếu không, ở mỗi một ngả rẽ của chương trình, bạn phải pass ref đó theo nếu muốn tiếp cận nó trong đối tượng mới. Application scope có thể coi là một cách tiếp cận khác nhưng nó nguy hiểm vì Java không có kiến trúc shared nothing như ở PHP. PHP là một ngôn ngữ đa mô thức, nó có cách tiếp cận global ở 2 cấp độ: userland (global, $GLOBAL) và engine (extract, $_POST, $_GET, $_FILE...). Điều mở ra ở PHP nhiều điểm vào của chương trình thay vì một nhánh đơn. Đây chính là điểm tiếp cận khác biệt cần thấy khi đặt ra vấn đề Data Transfer Object. Java cần đến nó để truyền dữ liệu từ tầng này sang tầng khác còn thực sự thì PHP có cần không? DTO trong Java mang theo 1 contract còn với PHP thì không dễ (dùng __set và __get để ràng buộc cũng là một cách nhưng đó là chính ta đã cố làm vậy) huống chi ở PHP có rất nhiều cách để thực hiện DTO qua các tầng theo phạm vi global (tôi không muốn nói đến userland global --> cái này đáng tránh)
+ Sự gần gũi giữa mô hình mảng, name của HTML element và cách đặt tên bảng cũng là vấn đề rất đáng quan tâm trong PHP
Mô hình dập khuôn: FactoryFactory ->DAOFactory -> DAO -> VO -> VOInterface rõ ràng là có vấn đề với các ngôn ngữ agile như PHP mặc dù tôi thừa nhận cách làm này rất có ý nghĩa với tooling và MDA. Để tận dụng được ưu thế của mô hình discipline và tính agile của PHP, tôi thay thế VO bằng một lớp Validator và dùng array khi không cần thiết phải có một Plain Old PHP Object mà chẳng có công việc gì ngoài getter với setter.
Đây là một đoạn mã tôi viết trong Page Controller.
(còn viết tiếp, làm việc cái đã)
Em cũng thấy, Active Record và Row Data Gateway là hai khái niệm khá nhập nhằng. Theo như Martin dạy thì Active Record phức tạp hơn Row Data Gateway ở chỗ nó định nghĩa cả relationship. Còn thằng Zend Framework bảo nó implement Row Data Gateway nhưng nó cũng có relationship, có điều là nó define cái đó trong table thôi.
Em lâu nay hiểu rằng "Model" là một khái niệm "rộng lớn" và uyển chuyển chứ ko chỉ đơn thuần mấy cái như ActiveRecord, Data Mapper... (ví dụ Model wrap bên ngoài thằng DAO chẳng hạn và nó phục vụ cho những yêu cầu trong các tình huống cụ thể )
Với lại bác cho luôn ý kiến về thằng SDO của PHP. Ở cty em có nạn xài thằng này tràn lan (tức là xài cho luôn cả read-only query), em bảo mãi mà không nghe +_+ !
Cảm ơn bác trước !
Nếu em là một người có nhìu kinh nghiệm và kiến thức về php với java chắc sẽ hiểu cách giải thích và so sánh của bác. Nhưng thú thực là em mới bập vào php một thời gian. Về syntax thì em có thể tự học, nhưng về những sự khác nhau cần lưu ý để không mang java dập vào php làm mất tinh thần của php như một số ý bác nêu ra thì em chưa hiểu
Không biết bác có thể giải thích rõ hơn bằng một vài ví dụ đơn giản nhưng đưa ra được vấn đề để những người đang muốn học hỏi thêm về php như em có cơ hội tìm hiểu ?
Ví dụ như :
+Tôi gọi việc sử dụng DAO trong PHP theo cách này là một sai lầm vì nó không tính đến cấu trúc dữ liệu giản lược trong PHP cũng như một tính năng của PHP được biết đến như là virtual properties. Chính vì thế cách code này được gọi là code smell.
+Java hướng vào discipline trong khi PHP hướng vào flexibility. Cho nên cái mô hình JavaBean chẳng có nghĩa gì ở PHP mà thay vào đó PHP phủ định mô hình này bằng cách đưa vào open class và virtual property.
Bác có thể cho em một ví dụ nhỏ để làm rõ vấn đề này không ?
+Java có xu hướng phân nhỏ trách nhiệm cho các lớp trong việc định nghĩa các cấu trúc dữ liệu cơ bản (Array, Hash, Map...) còn PHP thì có xu hướng gộp chúng lại chừng nào còn gộp được.
Không biết em có hiểu sai ý bác ở đây không ? Nhưng theo như em được biết thì lập trình theo hướng đối tượng người ta chia nhỏ một vấn đề bự thành các thằng con để sử lý (cái này trong java thì em hơi hiểu hiểu ) , nhưng PHP lại gộp chúng lại ?
Bác có thể giải thích thêm cho em phần này không ?
Hầu như java em tự học là chính, nên giờ Php cũng vậy. Hy vọng các cao thủ giúp đỡ để em có cái nhìn tốt hơn và tím ra hướng và cách học php cho thích hợp
Có thể cho em học hỏi một vài ý tưởng ?
Em có đọc trong trang ONLamp.com : http://www.onlamp.com/pub/a/php/2005...mvc_intro.html
Đây là một ý tưởng làm php theo cấu trúc MVC khi không dùng các framework có sẵn.
Mong nhận được nhận xét của những người có kinh nghiệm