2008-12-01 26 views
6

Tôi có điều này được đánh dấu là PHP nhưng chỉ vì tôi sẽ sử dụng mã PHP để hiển thị sự cố của mình.Làm cách nào để xử lý các mẫu cho các trang web MVC?

Vì vậy, tôi có một số mã như thế này cho bộ điều khiển:

switch ($page) 
{ 
    case "home": 
     require "views/home.php"; 
     break; 
    case "search": 
     require "views/search.php"; 
     break; 
} 

Rõ ràng có nhiều trang nhưng điều này nên minh họa vấn đề của tôi. Có một tiêu đề, điều hướng và chân trang chung cho cả hai trang này (và cho tất cả các trang trên trang web cho vấn đề đó). Tôi có nên sử dụng nhiều câu lệnh yêu cầu không? Dự đoán đầu tiên của tôi là:

switch ($page) 
{ 
    case "home": 
     require "templates/header.php"; 
     require "templates/navigation.php"; 
     require "views/home.php"; 
     require "templates/footer.php"; 
     break; 
    case "search": 
     require "templates/header.php"; 
     require "templates/navigation.php"; 
     require "views/search.php"; 
     require "templates/footer.php"; 
     break; 
} 

Bằng cách nào đó ruột của tôi cho tôi biết điều này không chính xác.

Trả lời

5

Bộ điều khiển chỉ nên thiết lập dữ liệu cho chế độ xem và chọn chế độ xem sẽ hiển thị. Chế độ xem phải chịu trách nhiệm bố cục của trang, bao gồm các trang được chia sẻ. Tôi thích mẫu đầu tiên của bạn trong giây lát.

+2

Đó không trả lời câu hỏi của tôi, tôi không nghĩ rằng có cùng tiêu đề/chân trang/điều hướng trên cả hai tệp trong thông minh. Đặc biệt là nó blatantly bất chấp nguyên tắc DRY. –

+0

Không nhất thiết. ASP.NET MVC cung cấp các trang chủ cho phép cả hai tách mối quan tâm (đó là những gì tôi đã nói về) và nguyên tắc DRY được duy trì. Không biết đủ về các khung công tác php để biết nếu có một khung với một tính năng tương tự. Đối với tôi duy trì SOC quan trọng hơn DRY – tvanfosson

1

Có, bạn phải có phần đầu trang, chân trang, v.v. được tách ra.

Đối với ví dụ cụ thể bạn hiển thị, điều này có hiệu quả hơn không?

require "templates/header.php"; 
    require "templates/navigation.php"; 
    require "views/$page.php"; 
    require "templates/footer.php"; 

(Trường hợp $ trang là 'nhà', 'tìm kiếm', vv)

-2

Có bất kỳ lý do cụ thể tại sao bạn không sử dụng một khuôn khổ MVC như Symfony hoặc CakePHP?

Tôi biết điều này không trả lời trực tiếp câu hỏi, nhưng có thể hữu ích.

+1

Đừng quên [Zend] (http://framework.zend.com/) – Zoredache

-2

Nếu bạn đang sử dụng các trang PHP thẳng làm mẫu của mình, về cơ bản bạn có thể đặt biến toàn cầu/phiên để giữ trang bạn muốn. Bạn sẽ có trang php "mẫu chính" bao gồm các phần tử đầu trang và chân trang, sau đó gọi bao gồm cho trang $. Một cái gì đó như thế này trong bộ điều khiển:

$_SESSION['page'] = sanitize_input($_GET['page']); 
require "templates/main.php"; 

và sau đó trong main.php template file:

require "templates/header.php"; 
require "templates/navigation.php"; 
require "views/{$_SESSION['page']}.php"; 
require "templates/footer.php"; 
+0

Một chút tò mò về lý do tại sao điều này bị bỏ phiếu khi nó trả lời trực tiếp câu hỏi của OP. Nếu anh ta không muốn sử dụng định dạng này, hãy sử dụng công cụ mẫu hoặc khung công tác. Bất kỳ cách nào khác sẽ dẫn đến mã lặp lại. Không được sử dụng – Alarion

+0

$ _SESSION tại đây. Chúng tôi không mang dữ liệu đến yêu cầu tiếp theo. Nếu không, bạn đang đi đúng hướng. – Preston

+0

Tôi chỉ sử dụng nó như một ví dụ đơn giản. Lưu trữ nó trong một cấu trúc dữ liệu của một số loại để các trang bao gồm có thể tham khảo nó là tốt. Tôi không thích mang theo các biến "toàn cục" thông thường. *nhún vai* – Alarion

0

Dưới đây là một phiên bản đơn giản như thế nào tôi làm mẫu với dự án hiện tại của tôi, nếu nó sử dụng bất kỳ:

class Template { 
    var $pagename = 'index'; 

    function __construct() { 
     $this->pagename = basename($_SERVER['SCRIPT_NAME'], '.php'); 
     register_shutdown_function(array($this, 'do_output')); 
    } 

    function do_output() { 
     $this->header(); 
     $this->display($this->pagename); 
     $this->footer(); 
    } 

    function __call($template, array $params) { 
     call_user_func(array($this, 'display'), $template, params); 
    } 

    function display($template, array $params = null) { 
     include "templates/$template.php"; 
    } 
} 

Ý tưởng đằng sau đó là bạn có thể viết "include 'Template.inc'; new Template;" và nó sắp xếp cho do_output() để chạy ở cuối tập lệnh tự động. Có một vài điều còn sót lại từ nó giống như phương thức được sử dụng để truyền các biến cho mẫu.

Bạn đã đề cập bạn không sử dụng PHP, và có một vài PHP-isms trong đó: register_shutdown_function() đảm bảo các mẫu được gọi trước đối tượng destructors nhưng sau script chính và các cuộc gọi đến $ this- > header()/footer() là các hàm gọi hàm ma thuật chỉ hiển thị ('header') và hiển thị ('footer'), chúng có nghĩa là bị ghi đè.

Tất nhiên không có gì sai khi sử dụng công tắc như ví dụ bạn đã đăng, nhưng bạn không cần đầu trang/chân trang bên trong mỗi câu lệnh trường hợp. Một cái gì đó như thế này sẽ làm điều tương tự:

require "templates/header.php"; 
require "templates/navigation.php"; 
switch ($page) 
{ 
    case "home": 
     require "views/home.php"; 
     break; 
    case "search": 
     require "views/search.php"; 
     break; 
} 
require "templates/footer.php"; 

...hoặc bạn có thể thay thế công tắc() bằng thứ gì đó dựa trên tên tệp như tôi đã sử dụng ở trên, nếu nó hoạt động theo cách trang của bạn được thiết lập. Một chuyển đổi là cách an toàn nhất nếu bạn có kế hoạch thực hiện nó thông qua các tham số URL.

0

Bạn đang lặp lại mã. Đây không phải là ý tưởng hay. Để ở gần ví dụ ban đầu của bạn, một cái gì đó như thế này chắc chắn sẽ thích hợp hơn:

require "templates/header.php"; 
require "templates/navigation.php"; 

switch ($page) { 
    case "home": 
     require "views/home.php"; 
     break; 
    case "search": 
     require "views/search.php"; 
     break; 
} 

require "templates/footer.php"; 

Thật khó để đưa ra thêm lời khuyên mà không cần biết thêm về cách tiếp cận kiến ​​trúc của bạn. Ví dụ nó sẽ được khuyến khích để có một phần của bộ điều khiển, mà chỉ đơn giản là chuẩn bị đầu ra, ở một nơi rất trung tâm và để bắt đầu đệm đầu ra trước khi bao gồm các mẫu xem. Bằng cách đó bạn có thể lưu trữ đầu ra trong một biến mà bạn có thể muốn xử lý thêm trước khi trả về nội dung của nó trong phản hồi HTTP.

0

Tôi đồng ý với tvanfosson và muốn giải thích lý do và cách nó liên quan đến MVC.

Vấn đề với ví dụ thứ hai là bộ điều khiển được hiển thị cách chế độ xem được tạo. Theo nghĩa hẹp, bộ điều khiển điều chỉnh các đầu vào cho khung nhìn và chuyển chúng vào nó, và không có gì hơn.

Cách suy nghĩ thực tế về điều này là nếu chế độ xem thay đổi tùy thuộc vào yêu cầu ứng dụng hoặc chính yếu tố đầu vào. Ví dụ: nếu chế độ xem được tạo là cho cửa sổ bật lên JavaScript, có thể (và có thể sẽ) sử dụng một bộ tiêu đề, chân trang, CSS, meta, v.v. Với ví dụ thứ hai, tất cả những gì được hiển thị với bộ điều khiển . Trong lần đầu tiên, đó là chế độ xem ai biết cách tạo chế độ xem - đó chính xác là điểm.

Để lấy thêm ví dụ của mình, hãy tưởng tượng rằng cửa sổ bật lên JavaScript được thiết kế lại thành chế độ xem trang đầy đủ hoặc được cấu trúc lại cho AJAX (hoặc câu hỏi pop-up/page/AJAX được xác định bởi đầu vào, chẳng hạn như yếu tố ẩn trong một trường). Bây giờ bạn đang tách rời bộ điều khiển vì chế độ xem đã thay đổi. Nó không phải là quá nhiều mà bạn đã vi phạm MVC, nhưng bạn không nên có bothered với nó ở nơi đầu tiên.

0

Nếu tất cả các tên tập tin của bạn phù hợp với yêu cầu xem/trang của bạn như thể hiện trong ví dụ của bạn thì bạn chỉ cần một dòng và không switch tuyên bố:

require "templates/header.php"; 
require "templates/navigation.php"; 
require 'views/' . $page . '.php'; // <-- one-liner 
require "templates/footer.php"; 
Các vấn đề liên quan