2009-04-27 29 views
36

Giống như hầu hết các nhà phát triển web những ngày này, tôi hoàn toàn tận hưởng những lợi ích của kiến ​​trúc MVC vững chắc cho các ứng dụng web và các trang web. Khi làm MVC với PHP, tự động tải rõ ràng là cực kỳ tiện dụng.PHP tự động tải và đặt tên chiến lược

Tôi đã trở thành người hâm mộ của spl_autoload_register chỉ đơn giản là xác định một hàm __autoload() duy nhất, vì điều này rõ ràng là linh hoạt hơn nếu bạn kết hợp các mô-đun cơ sở khác nhau. Tuy nhiên, tôi chưa bao giờ cảm thấy tuyệt vời về các chức năng tải mà tôi viết. Chúng liên quan đến việc kiểm tra chuỗi và quét thư mục để tìm kiếm các lớp có thể tải. Ví dụ: giả sử tôi có một ứng dụng có đường dẫn cơ sở được xác định là PATH_APP và cấu trúc đơn giản với các thư mục có tên là models, viewscontrollers. Tôi thường sử dụng cấu trúc đặt tên theo đó các tệp có tên là IndexView.phpIndexController.php bên trong thư mục thích hợp và các mô hình thường không có lược đồ cụ thể theo mặc định. Tôi có thể có một chức năng nạp cho cấu trúc này như thế này mà được đăng ký với spl_autoload_register:

public function MVCLoader($class) 
{ 
    if (file_exists(PATH_APP.'/models/'.$class.'.php')) { 
     require_once(PATH_APP.'/models/'.$class.'.php'); 
     return true; 
    } 
    else if (strpos($class,'View') !== false) { 
     if (file_exists(PATH_APP.'/views/'.$class.'.php')) { 
      require_once(PATH_APP.'/views/'.$class.'.php'); 
      return true; 
     } 
    } 
    else if (strpos($class,'Controller') !== false) { 
     if (file_exists(PATH_APP.'/controllers/'.$class.'.php')) { 
      require_once(PATH_APP.'/controllers/'.$class.'.php'); 
      return true; 
     } 
    } 
    return false; 
} 

Nếu nó không được tìm thấy sau đó, tôi có thể có một chức năng để quét thư mục con trong thư mục các mô hình. Tuy nhiên, tất cả các if/else-ing, chuỗi kiểm tra và quét thư mục có vẻ không hiệu quả với tôi, và tôi muốn cải thiện nó.

Tôi rất tò mò về cách đặt tên tệp và các chiến lược tự động tải mà các nhà phát triển khác có thể sử dụng. Tôi đang tìm kiếm đặc biệt cho các kỹ thuật tốt để sử dụng cho tự động tải hiệu quả, và không phải lựa chọn thay thế để tự động tải.

Trả lời

28

Đây là những gì tôi đã được sử dụng trong tất cả các dự án của tôi (cất thẳng từ nguồn gốc của người cuối cùng):

public static function loadClass($class) 
{ 
    $files = array(
     $class . '.php', 
     str_replace('_', '/', $class) . '.php', 
    ); 
    foreach (explode(PATH_SEPARATOR, ini_get('include_path')) as $base_path) 
    { 
     foreach ($files as $file) 
     { 
      $path = "$base_path/$file"; 
      if (file_exists($path) && is_readable($path)) 
      { 
       include_once $path; 
       return; 
      } 
     } 
    } 
} 

Nếu tôi tìm kiếm SomeClass_SeperatedWith_Underscores nó sẽ tìm kiếm SomeClass_SeperatedWith_Underscores.php tiếp theo SomeClass /SeperatedWith/Underscores.php bắt nguồn từ mỗi thư mục trong đường dẫn bao gồm hiện tại.

EDIT: Tôi chỉ muốn đưa ra ở đó rằng tôi sử dụng điều này cho hiệu quả trong phát triển, và không nhất thiết phải xử lý thời gian. Nếu bạn có PEAR trên con đường của bạn thì với điều này bạn chỉ có thể sử dụng các lớp và không cần phải bao gồm chúng khi bạn cần chúng.

Tôi có xu hướng giữ các lớp của mình trong một hệ thống phân cấp các thư mục, với dấu gạch dưới chia tách các không gian tên ... Mã này cho phép tôi giữ cấu trúc tệp đẹp và gọn gàng nếu tôi muốn, hoặc để tiêm một tệp lớp nhanh mà không cần thư mục lồng nhau tôi muốn (cho thêm một hoặc hai lớp duy nhất để một thư viện mà nó là bị đơn, nhưng không phải là một phần của dự án tôi hiện đang làm việc trên.)

+3

pimp +1 cho độ lạnh – Louis

+0

Tôi chắc chắn thích cách tiếp cận gạch dưới. Nó làm cho dịch từ lớp sang tập tin hiệu quả hơn nhiều. – zombat

+3

Quấn 'mảng_unique()' quanh mảng '$ files' của bạn. Nếu không có dấu gạch dưới trong tên lớp, bạn đang thử mỗi tệp hai lần. – mpen

13

tôi hạ cánh trên giải pháp này:

tôi tạo ra một đĩa đơn tập lệnh truyền tải thư mục lớp thư viện của tôi (chứa thư mục con cho các mô-đun/hệ thống riêng biệt) và phân tích nội dung tệp tìm kiếm các định nghĩa lớp. Nếu nó tìm thấy một định nghĩa lớp trong một file php (mẫu biểu thức chính khá đơn giản), nó tạo ra một liên kết tượng trưng:

class_name.php -> actual/source/file.php 

này cho phép tôi sử dụng một, chức năng tự động load đơn giản đơn mà chỉ cần tên lớp và đường dẫn đến thư mục liên kết tượng trưng chính và không phải thực hiện bất kỳ thao tác đường dẫn/chuỗi nào.

Phần tốt nhất là tôi có thể sắp xếp lại mã nguồn hoàn toàn hoặc thêm hệ thống con mới và chỉ chạy tập lệnh tạo liên kết để mọi thứ được tự động tải.

+0

Đó có lẽ là giải pháp sáng tạo nhất mà tôi từng gặp. Đồ tốt. Chỉ cần tò mò, cách tiếp cận nền tảng sẽ như thế nào? – zombat

+4

Kể từ khi tôi bắt đầu làm việc với Linux, một trong những lỗ hổng chính của tôi với Windows là thiếu các liên kết tượng trưng. Theo như tôi biết, giải pháp này chỉ hoạt động với unixes. – grossvogel

+5

FYI, bạn có thể sử dụng 'mklink' để tạo liên kết tượng trưng trong Windows: http://www.howtogeek.com/howto/windows-vista/using-symlinks-in-windows-vista/ –

7

Nếu bạn muốn hiệu quả thì bạn không nên sử dụng tính năng tự động tải. Tính năng tự động tải là lười biếng. Bạn nên cung cấp đường dẫn rõ ràng cho các tệp bao gồm của mình khi bạn đưa chúng vào. Nếu chức năng tự động tải của bạn có thể tìm thấy các tệp này thì bạn có thể viết mã để tìm chúng một cách rõ ràng. Khi bạn đang làm việc trên phần xem của mã và sắp tải một lớp xem mới, bằng cách cho phép hàm tự động xử lý nó, trước tiên nó giả định lớp của bạn là một lớp mô hình? Điều đó không hiệu quả. Thay vì mã của bạn chỉ nên là:

include_once $this->views_path . $class . '.php'; 

Nếu bạn cần nhiều "view" con đường, làm một chức năng mà tải quan điểm:

public function load_view($class) { 
    // perhaps there's a mapping here instead.... 
    foreach ($this->views_paths as $path) { 
     $filename = $path . $class . '.php'; 
     if (file_exists($filename)) { 
      include_once $filename; 
     } 
    } 
    throw .... 
} 

Trong mọi trường hợp, tại điểm mà bao gồm xảy ra, bạn có thông tin lớn nhất/chính xác nhất về lớp bạn muốn tải. Sử dụng thông tin đó để tải lớp hoàn toàn là chiến lược tải lớp hiệu quả duy nhất. Có, bạn có thể kết thúc với nhiều biến lớp hơn hoặc (trời cấm) một số biến toàn cục. Nhưng đó là một sự cân bằng tốt hơn là lười biếng và quét các phần của hệ thống tệp cho lớp của bạn.

+10

Mặc dù bạn đúng về tải trực tiếp là tổng thể hiệu quả nhất, nhưng nó làm cho mã khó duy trì hơn. Nếu bạn thay đổi tên của một lớp học hoặc một tập tin thì sao? Hoặc nói rằng tôi có các phân đoạn xem động có thể được trình điều khiển nạp và khi một dự án tiếp tục, ngày càng có nhiều lớp xem được tạo. Mỗi khi tôi tạo ra một lớp xem, tôi không muốn phải quay trở lại và sửa đổi một bộ điều khiển để tự bao gồm nó bất cứ nơi nào nó có thể được sử dụng. Tôi đồng ý rằng tự động tải kém hiệu quả hơn tải trực tiếp, nhưng tôi đang tìm nạp tự động hiệu quả nhất. – zombat

+1

Tôi đồng ý với zombat. Sự lười biếng có thể là một điều tốt - nó còn được gọi là hoạt động hiệu quả. Đối với hiệu suất, phần cứng là rẻ. – rick

+2

Nếu bạn phải thay đổi tên của một lớp sau khi nó chạm vào sản xuất, bạn không dành đủ thời gian thiết kế trước khi viết mã. Nếu hiệu quả là quan trọng, chi tiêu nhiều thời gian hơn lên phía trước tiết kiệm nhiều thời gian hơn trong bảo trì hơn lười biếng, không-nghĩ-về-nó-at-tất cả các chức năng như autoload. – jmucchiello

Các vấn đề liên quan