Cách tốt nhất để bắt đầu một lớp trong plugin WP?


89

Tôi đã tạo một plugin và tất nhiên là tôi, tôi muốn đi theo cách tiếp cận OO đẹp. Bây giờ những gì tôi đã làm là tạo lớp này và sau đó ngay bên dưới tạo một thể hiện của lớp này:

class ClassName {

    public function __construct(){

    }
}

$class_instance = new ClassName();  

Tôi giả sử có một cách WP nhiều hơn để bắt đầu lớp này, và sau đó tôi tình cờ thấy mọi người nói rằng họ thích có một init()chức năng hơn một __construct(). Và tương tự, tôi tìm thấy một vài người sử dụng hook sau:

class ClassName {

    public function init(){

    }
}
add_action( 'load-plugins.php', array( 'ClassName', 'init' ) );

Điều gì thường được coi là cách tốt nhất để tạo một cá thể lớp WP khi tải và có điều này như là một biến có thể truy cập toàn cầu?

LƯU Ý: Là một điểm thú vị, tôi nhận thấy rằng trong khi register_activation_hook()có thể được gọi từ bên trong __construct, thì không thể gọi từ bên trong init()ví dụ thứ hai. Có lẽ ai đó có thể khai sáng cho tôi về điểm này.

Chỉnh sửa: Cảm ơn tất cả các câu trả lời, rõ ràng có một chút tranh luận về cách xử lý việc khởi tạo trong chính lớp, nhưng tôi nghĩ nói chung có một sự đồng thuận khá tốt add_action( 'plugins_loaded', ...);là cách tốt nhất để thực sự khởi động ...

Chỉnh sửa: Chỉ để gây nhầm lẫn các vấn đề, tôi cũng đã thấy điều này được sử dụng (mặc dù tôi sẽ không sử dụng phương pháp này cho mình vì biến một lớp OO độc đáo thành một chức năng dường như đánh bại điểm của nó):

// Start up this plugin
add_action( 'init', 'ClassName' );
function ClassName() {
    global $class_name;
    $class_name = new ClassName();
}

1
Về lần chỉnh sửa cuối cùng, nếu nó được chứa trong cùng một tệp plugin với lớp, nó sẽ trở nên hơi vô dụng. Bạn cũng có thể khởi tạo lớp theo phương thức tôi mô tả. Ngay cả khi nó trong một tập tin riêng biệt, nó vẫn hơi vô nghĩa. Chỉ sử dụng trường hợp tôi có thể thấy là nếu bạn muốn tạo một hàm bao bọc cho phép bạn khởi tạo một lớp bên ngoài các tệp plugin của bạn, trong các chủ đề, v.v. Mặc dù vậy, tôi phải hỏi logic nào nằm sau điều đó bởi vì việc sử dụng đúng các điều kiện và móc nối sẽ cho phép kiểm soát hạt tốt đối với việc khởi tạo cho phép bạn tập trung vào việc sử dụng plugin thay thế.
Adam

Tôi đồng ý với điều này, nhưng tôi nghĩ rằng nó đáng để đưa vào khi tôi tìm thấy nó trong một vài plugin WP.
kalpaitch

Câu trả lời:


60

Câu hỏi hay, có một số cách tiếp cận và nó phụ thuộc vào những gì bạn muốn đạt được.

Tôi thường làm;

add_action( 'plugins_loaded', array( 'someClassy', 'init' ));

class someClassy {

    public static function init() {
        $class = __CLASS__;
        new $class;
    }

    public function __construct() {
           //construct what you see fit here...
    }

    //etc...
}

Một ví dụ sâu sắc hơn xuất hiện do kết quả của một số cuộc thảo luận gần đây về chính chủ đề này trong phòng trò chuyện có thể được nhìn thấy trong ý chính này của thành viên WPSE toscho .

Cách tiếp cận xây dựng trống.

Dưới đây là một đoạn trích về ưu điểm / nhược điểm được lấy từ ý chính ở trên, ví dụ đầy đủ về cách tiếp cận của nhà xây dựng trống.

  • Ưu điểm:

    • Kiểm tra đơn vị có thể tạo các phiên bản mới mà không cần kích hoạt bất kỳ móc nào tự động. Không có Singleton.

    • Không có biến toàn cầu cần thiết.

    • Bất cứ ai muốn làm việc với phiên bản plugin chỉ có thể gọi T5_Plugin_Class_Demo :: get_instance ().

    • Dễ dàng hủy kích hoạt.

    • Vẫn OOP thực: không có phương pháp làm việc nào là tĩnh.

  • Bất lợi:

    • Có lẽ khó đọc hơn?

Theo tôi, nhược điểm là yếu kém, đó là lý do tại sao nó phải là phương pháp ưa thích của tôi, tuy nhiên không phải là cách duy nhất tôi sử dụng. Trong thực tế, một số trọng lượng nặng khác sẽ không nghi ngờ gì về chủ đề này trong thời gian ngắn về chủ đề này vì có một số ý kiến ​​tốt xung quanh chủ đề này nên được lên tiếng.


lưu ý: Tôi cần tìm ví dụ chính từ toscho đã chạy qua 3 hoặc 4 so sánh về cách khởi tạo một lớp trong một plugin xem xét ưu và nhược điểm của từng loại, mà liên kết ở trên là cách ưa thích để làm điều đó, nhưng các ví dụ khác cung cấp một sự tương phản tốt cho chủ đề này. Hy vọng toscho vẫn có trong hồ sơ.

Lưu ý: Câu trả lời của WPSE cho chủ đề này với các ví dụ và so sánh có liên quan. Cũng là giải pháp tốt nhất cho một lớp trong WordPress.

add_shortcode( 'baztag', array( My_Plugin::get_instance(), 'foo' ) );
class My_Plugin {

    private $var = 'foo';

    protected static $instance = NULL;

    public static function get_instance() {

        // create an object
        NULL === self::$instance and self::$instance = new self;

        return self::$instance; // return the object
    }

    public function foo() {

        return $this->var; // never echo or print in a shortcode!
    }
}

điều gì sẽ là sự khác biệt giữa add_action ('plugins_loaded', ...); và add_action ('load-plugins.php', ...); Ví dụ tôi đã sử dụng sau này
kalpaitch

1
Từ những gì tôi hiểu về load-plugins.php, mặc dù nó hoạt động, được liên kết với update.phptệp lõi và không phải là một phần của các hành động mặc định thông thường nên dựa vào khi liên quan đến chuỗi sự kiện xảy ra trong quá trình khởi tạo và vì lý do đó tôi thích để sử dụng những cái móc được áp dụng, trong trường hợp này plugins_loaded. Đây là những gì tôi thường đề cập đến như một ảnh chụp nhanh về những gì xảy ra khi Tham chiếu hành động . Giải thích của tôi không đầy đủ.
Adam

4
Tôi thích cách tiếp cận giống như singleton này. Tuy nhiên, tôi nghi ngờ sử dụng plugins_loaded làm hook hành động khởi tạo của bạn. Móc này có nghĩa là được chạy sau khi tất cả các plugin đã được tải. Bằng cách kết nối sau nó, bạn có thể chiếm quyền điều khiển đó và có thể gặp phải các xung đột hoặc các vấn đề về trình tự khởi động với các plugin hoặc chủ đề khác liên quan đến plugins_loaded. Tôi sẽ không tham gia bất kỳ hành động nào để chạy phương thức khởi tạo của bạn. Kiến trúc plugin được thiết kế để chạy nội tuyến, không phải trên một hành động.
Tom Auger

2
Lưu ý rằng nếu bạn sử dụng, register_activation_hook()bạn cần gọi chức năng đó trước khi plugins_loadedhành động được kích hoạt.
Geert

1
Để biết thêm thông tin, hãy xem bài đăng này từ @mikechinkel và dicuss trong các bình luận. hardcorewp.com/2012/...
bueltge

78

Đến đây đúng 2 năm sau khi câu hỏi ban đầu được hỏi, có một vài điều tôi muốn chỉ ra. (Đừng yêu cầu tôi chỉ ra nhiều thứ , bao giờ).

Móc đúng

Để khởi tạo một lớp plugin, nên sử dụng hook thích hợp . Không có một quy tắc chung nào, bởi vì nó phụ thuộc vào những gì lớp học làm.

Việc sử dụng một hook rất sớm "plugins_loaded"thường không có ý nghĩa gì vì một hook như thế được kích hoạt cho các yêu cầu của admin, frontend và AJAX, nhưng thường thì hook sau đó tốt hơn nhiều vì nó chỉ cho phép khởi tạo các lớp plugin khi cần.

Ví dụ, một lớp làm công cụ cho các mẫu có thể được khởi tạo "template_redirect".

Nói chung, rất hiếm khi một lớp cần phải được khởi tạo trước khi "wp_loaded"bị sa thải.

Không có lớp Chúa

Hầu hết tất cả các lớp được sử dụng làm ví dụ trong các câu trả lời cũ hơn đều sử dụng một lớp có tên như "Prefix_Example_Plugin"hoặc "My_Plugin"... Điều này cho thấy có lẽ có một lớp chính cho plugin.

Chà, trừ khi một plugin được tạo bởi một lớp duy nhất (trong trường hợp đó, đặt tên theo tên plugin là hoàn toàn hợp lý), để tạo một lớp quản lý toàn bộ plugin (ví dụ: thêm tất cả các hook mà plugin cần hoặc khởi tạo tất cả các lớp plugin khác ) có thể được coi là một thực hành xấu, như một ví dụ về một đối tượng thần .

Trong mã lập trình hướng đối tượng nên có xu hướng RẮN trong đó "S" là viết tắt của "Nguyên tắc trách nhiệm đơn lẻ" .

Nó có nghĩa là mỗi lớp nên làm một điều duy nhất. Trong phát triển plugin WordPress, điều đó có nghĩa là các nhà phát triển nên tránh sử dụng một hook duy nhất để khởi tạo một lớp plugin chính , nhưng các hook khác nhau nên được sử dụng để khởi tạo các lớp khác nhau, theo trách nhiệm của lớp.

Tránh móc trong constructor

Lập luận này đã được giới thiệu trong các câu trả lời khác ở đây, tuy nhiên tôi muốn nhận xét khái niệm này và liên kết câu trả lời khác này , nơi nó đã được giải thích khá rộng rãi trong mục đích thử nghiệm đơn vị.

Gần như 2015: PHP 5.2 dành cho zombie

Kể từ ngày 14 tháng 8 năm 2014, PHP 5.3 đã kết thúc vòng đời . Nó chắc chắn đã chết. PHP 5.4 sẽ được hỗ trợ cho cả năm 2015, điều đó có nghĩa là một năm nữa tại thời điểm tôi đang viết.

Tuy nhiên, WordPress vẫn hỗ trợ PHP 5.2, nhưng không ai nên viết một dòng mã hỗ trợ phiên bản đó, đặc biệt nếu mã là OOP.

Có nhiều lý do khác nhau:

  • PHP 5.2 đã chết cách đây rất lâu, không có bản sửa lỗi bảo mật nào được phát hành cho nó, điều đó có nghĩa là nó không an toàn
  • PHP 5.3 đã thêm rất nhiều tính năng cho PHP, các hàm ẩn danh và các không gian tên über alles
  • các phiên bản mới hơn của PHP nhanh hơn rất nhiều . PHP là miễn phí. Cập nhật nó là miễn phí. Tại sao sử dụng phiên bản chậm hơn, không an toàn nếu bạn có thể sử dụng phiên bản nhanh hơn, an toàn hơn miễn phí?

Nếu bạn không muốn sử dụng mã PHP 5.4+, hãy sử dụng ít nhất 5,3+

Thí dụ

Tại thời điểm này là thời gian để xem xét các câu trả lời cũ hơn dựa trên những gì tôi đã nói cho đến đây.

Khi chúng ta không phải quan tâm đến 5.2 nữa, chúng ta có thể và nên sử dụng các không gian tên.

Để giải thích rõ hơn về nguyên tắc trách nhiệm duy nhất, ví dụ của tôi sẽ sử dụng 3 lớp, một lớp thực hiện điều gì đó ở ngoại vi, một lớp trên phụ trợ và lớp thứ ba được sử dụng trong cả hai trường hợp.

Lớp quản trị viên:

namespace GM\WPSE\Example;

class AdminStuff {

   private $tools;

   function __construct( ToolsInterface $tools ) {
     $this->tools = $tools;
   }

   function setup() {
      // setup class, maybe add hooks
   }

}

Lớp trưởng:

namespace GM\WPSE\Example;

class FrontStuff {

   private $tools;

   function __construct( ToolsInterface $tools ) {
     $this->tools = $tools;
   }

   function setup() {
      // setup class, maybe add hooks
   }

}

Giao diện công cụ:

namespace GM\WPSE\Example;

interface ToolsInterface {

   function doSomething();

}

Và một lớp Công cụ, được sử dụng bởi hai người kia:

namespace GM\WPSE\Example;

class Tools implements ToolsInterface {

   function doSomething() {
      return 'done';
   }

}

Có các lớp này, tôi có thể khởi tạo chúng bằng cách sử dụng các hook thích hợp. Cái gì đó như:

require_once plugin_dir_path( __FILE__ ) . 'src/ToolsInterface.php';
require_once plugin_dir_path( __FILE__ ) . 'src/Tools.php';

add_action( 'admin_init', function() {

   require_once plugin_dir_path( __FILE__ ) . 'src/AdminStuff.php';
   $tools = new GM\WPSE\Example\Tools;
   global $admin_stuff; // this is not ideal, reason is explained below
   $admin_stuff = new GM\WPSE\Example\AdminStuff( $tools ); 
} );

add_action( 'template_redirect', function() {

   require_once plugin_dir_path( __FILE__ ) . 'src/FrontStuff.php';
   $tools = new GM\WPSE\Example\Tools;
   global $front_stuff; // this is not ideal, reason is explained below
   $front_stuff = new GM\WPSE\Example\FrontStuff( $tools );    
} );

Phụ thuộc đảo ngược & tiêm phụ thuộc

Trong ví dụ trên, tôi đã sử dụng các không gian tên và các hàm ẩn danh để khởi tạo các lớp khác nhau ở các hook khác nhau, đưa vào thực tế những gì tôi đã nói ở trên.

Lưu ý cách không gian tên cho phép tạo các lớp được đặt tên mà không có bất kỳ tiền tố nào.

Tôi đã áp dụng một khái niệm khác đã được đề cập gián tiếp ở trên: Dependency Injection , đó là một phương pháp để áp dụng Nguyên tắc đảo ngược phụ thuộc , "D" trong từ viết tắt RẮN.

Các Toolslớp được "tiêm" trong hai lớp khác khi chúng được khởi tạo, vì vậy theo cách này nó có thể tách rời trách nhiệm.

Ngoài ra, AdminStuffFrontStuffcác lớp sử dụng gợi ý kiểu để khai báo họ cần một lớp thực hiện ToolsInterface.

Theo cách này, bản thân chúng tôi hoặc người dùng sử dụng mã của chúng tôi có thể sử dụng các triển khai khác nhau của cùng một giao diện, làm cho mã của chúng tôi không được kết hợp với một lớp cụ thể mà là một sự trừu tượng: đó chính xác là Nguyên tắc đảo ngược phụ thuộc.

Tuy nhiên, ví dụ trên có thể được cải thiện hơn nữa. Chúng ta hãy xem làm thế nào.

Trình tải tự động

Một cách tốt để viết mã OOP dễ đọc hơn là không trộn lẫn các định nghĩa (Giao diện, Lớp) với mã khác và đặt mọi loại trong tệp riêng của nó.

Quy tắc này cũng là một trong những tiêu chuẩn mã hóa PSR-1 1 .

Tuy nhiên, làm như vậy, trước khi có thể sử dụng một lớp, người ta cần phải có tệp chứa nó.

Điều này có thể áp đảo, nhưng PHP cung cấp các hàm tiện ích để tự động tải một lớp khi được yêu cầu, sử dụng một hàm gọi lại tải một tệp dựa trên tên của nó.

Sử dụng không gian tên nó trở nên rất dễ dàng, bởi vì bây giờ có thể khớp cấu trúc thư mục với cấu trúc không gian tên.

Điều đó không chỉ có thể, mà còn là một tiêu chuẩn PSR khác (hoặc tốt hơn là 2: PSR-0 hiện không được chấp nhận và PSR-4 ).

Theo các tiêu chuẩn đó, có thể sử dụng các công cụ khác nhau để xử lý tự động tải mà không cần phải mã hóa trình tải tự động tùy chỉnh.

Tôi phải nói rằng các tiêu chuẩn mã hóa WordPress có các quy tắc khác nhau để đặt tên tệp.

Vì vậy, khi viết mã cho lõi WordPress, các nhà phát triển phải tuân theo các quy tắc WP, nhưng khi viết mã tùy chỉnh thì đó là lựa chọn của nhà phát triển, nhưng sử dụng tiêu chuẩn PSR thì dễ sử dụng hơn các công cụ đã viết 2 .

Các mẫu định vị truy cập, đăng ký và dịch vụ toàn cầu.

Một trong những vấn đề lớn nhất khi khởi tạo các lớp plugin trong WordPress, là làm thế nào để truy cập chúng từ các phần khác nhau của mã.

Bản thân WordPress sử dụng cách tiếp cận toàn cầu : các biến được lưu trong phạm vi toàn cầu, khiến chúng có thể truy cập ở mọi nơi. Mỗi nhà phát triển WP gõ từ globalhàng ngàn lần trong sự nghiệp của họ.

Đây cũng là cách tiếp cận tôi sử dụng cho ví dụ trên, nhưng nó là xấu xa .

Câu trả lời này đã quá dài để cho phép tôi giải thích thêm tại sao, nhưng đọc kết quả đầu tiên trong SERP cho "biến toàn cầu xấu" là điểm khởi đầu tốt.

Nhưng làm thế nào có thể tránh các biến toàn cầu?

Có nhiều cách khác nhau.

Một số câu trả lời cũ hơn ở đây sử dụng cách tiếp cận tĩnh .

public static function instance() {

  if ( is_null( self::$instance ) ) {
    self::$instance = new self;
  }

  return self::$instance;
}

Thật dễ dàng và khá ổn, nhưng nó buộc phải triển khai mô hình cho mọi lớp chúng ta muốn truy cập.

Hơn nữa, rất nhiều lần cách tiếp cận này đặt ra vấn đề về lớp thần, bởi vì các nhà phát triển tạo ra một lớp chính có thể truy cập bằng phương thức này, và sau đó sử dụng nó để truy cập vào tất cả các lớp khác.

Tôi đã giải thích mức độ tệ của một lớp thần, vì vậy cách tiếp cận thể hiện tĩnh là một cách tốt để đi khi một plugin chỉ cần làm cho một hoặc hai lớp có thể truy cập được.

Điều này không có nghĩa là nó chỉ có thể được sử dụng cho các plugin chỉ có một vài lớp, trên thực tế, khi nguyên tắc tiêm phụ thuộc được sử dụng đúng cách, có thể tạo các ứng dụng khá phức tạp mà không cần phải truy cập toàn cầu với số lượng lớn của các đối tượng.

Tuy nhiên, đôi khi các plugin cần làm cho một số lớp có thể truy cập được và trong trường hợp đó, cách tiếp cận thể hiện tĩnh là quá mức.

Một cách tiếp cận khác có thể là sử dụng mẫu đăng ký .

Đây là một thực hiện rất đơn giản của nó:

namespace GM\WPSE\Example;

class Registry {

   private $storage = array();

   function add( $id, $class ) {
     $this->storage[$id] = $class;
   }

   function get( $id ) {
      return array_key_exists( $id, $this->storage ) ? $this->storage[$id] : NULL;
   }

}

Sử dụng lớp này có thể lưu trữ các đối tượng trong đối tượng đăng ký theo id, vì vậy có quyền truy cập vào sổ đăng ký, có thể có quyền truy cập vào tất cả các đối tượng. Tất nhiên khi một đối tượng được tạo lần đầu tiên, nó cần được thêm vào sổ đăng ký.

Thí dụ:

global $registry;

if ( is_null( $registry->get( 'tools' ) ) ) {
  $tools = new GM\WPSE\Example\Tools;
  $registry->add( 'tools', $tools );
}

if ( is_null( $registry->get( 'front' ) ) ) {
  $front_stuff = new GM\WPSE\Example\FrontStuff( $registry->get( 'tools' ) );    
  $registry->add( 'front', front_stuff );
}

add_action( 'wp', array( $registry->get( 'front' ), 'wp' ) );

Ví dụ trên cho thấy rõ rằng để hữu ích, sổ đăng ký cần có thể truy cập được trên toàn cầu. Một biến toàn cục cho sổ đăng ký duy nhất không phải là rất xấu, tuy nhiên, đối với những người theo chủ nghĩa thuần túy toàn cầu, có thể thực hiện cách tiếp cận cá thể tĩnh cho một sổ đăng ký, hoặc có thể là một hàm có biến tĩnh:

function gm_wpse_example_registry() {
  static $registry = NULL;
  if ( is_null( $registry ) ) {
    $registry = new GM\WPSE\Example\Registry;
  }
  return $registry;
}

Lần đầu tiên hàm được gọi, nó sẽ khởi tạo registry, trong các cuộc gọi tiếp theo, nó sẽ trả về nó.

Một phương thức dành riêng cho WordPress khác để tạo một lớp có thể truy cập toàn cầu là trả về một thể hiện đối tượng từ bộ lọc. Một cái gì đó như thế này:

$registry = new GM\WPSE\Example\Registry;

add_filter( 'gm_wpse_example_registry', function() use( $registry ) {
  return $registry;
} );

Sau đó, mọi nơi đăng ký là cần thiết:

$registry = apply_filters( 'gm_wpse_example_registry', NULL );

Một mẫu khác có thể được sử dụng là mẫu định vị dịch vụ . Nó tương tự như mẫu đăng ký, nhưng các bộ định vị dịch vụ được chuyển đến các lớp khác nhau bằng cách sử dụng phép nội xạ phụ thuộc.

Vấn đề chính với mẫu này là nó ẩn các lớp phụ thuộc làm cho mã khó duy trì và đọc hơn.

DI container

Bất kể phương thức được sử dụng để làm cho đăng ký hoặc định vị dịch vụ có thể truy cập toàn cầu, các đối tượng phải được lưu trữ ở đó và trước khi được lưu trữ, chúng cần phải được khởi tạo.

Trong các ứng dụng phức tạp, nơi có khá nhiều lớp và nhiều lớp trong số chúng có một số phụ thuộc, các lớp khởi tạo đòi hỏi rất nhiều mã, vì vậy khả năng lỗi tăng lên: mã không tồn tại không có lỗi.

Trong những năm trước, đã xuất hiện một số thư viện PHP giúp các nhà phát triển PHP dễ dàng khởi tạo và lưu trữ các thể hiện của các đối tượng, tự động giải quyết các phụ thuộc của chúng.

Các thư viện này được gọi là Container phụ thuộc vì chúng có khả năng khởi tạo các lớp giải quyết các phụ thuộc và cũng để lưu trữ các đối tượng và trả lại chúng khi cần, hoạt động tương tự như một đối tượng đăng ký.

Thông thường, khi sử dụng các thùng chứa DI, các nhà phát triển phải thiết lập các phụ thuộc cho mỗi lớp của ứng dụng, và sau đó, lần đầu tiên một lớp là cần thiết trong mã, nó được khởi tạo với các phụ thuộc thích hợp và cùng một trường hợp được trả lại lần nữa cho các yêu cầu tiếp theo .

Một số bộ chứa DI cũng có khả năng tự động khám phá các phụ thuộc mà không cần cấu hình, nhưng sử dụng phản chiếu PHP .

Một số container DI nổi tiếng là:

và nhiều người khác.

Tôi muốn chỉ ra rằng đối với các plugin đơn giản, chỉ liên quan đến một vài lớp và các lớp không có nhiều phụ thuộc, có lẽ nó không đáng để sử dụng các thùng chứa DI: phương thức cá thể tĩnh hoặc một sổ đăng ký có thể truy cập toàn cầu là những giải pháp tốt, nhưng đối với các plugin phức tạp lợi ích của một container DI trở nên rõ ràng.

Tất nhiên, ngay cả các đối tượng chứa DI phải có thể truy cập được để sử dụng trong ứng dụng và với mục đích đó, có thể sử dụng một trong các phương thức được thấy ở trên, biến toàn cục, biến đối tượng tĩnh, trả về đối tượng qua bộ lọc, v.v.

Nhà soạn nhạc

Để sử dụng DI container thường có nghĩa là sử dụng mã bên thứ 3. Ngày nay, trong PHP, khi chúng ta cần sử dụng lib bên ngoài (vì vậy không chỉ các thùng chứa DI, mà bất kỳ mã nào không phải là một phần của ứng dụng), chỉ cần tải xuống và đưa nó vào thư mục ứng dụng của chúng tôi không được coi là một cách làm tốt. Ngay cả khi chúng tôi là tác giả của đoạn mã khác.

Việc tách mã ứng dụng khỏi các phụ thuộc bên ngoài là dấu hiệu của tổ chức tốt hơn, độ tin cậy tốt hơn và độ tinh khiết của mã tốt hơn .

Trình soạn thảo , là tiêu chuẩn thực tế trong cộng đồng PHP để quản lý các phụ thuộc PHP. Cũng là một xu hướng chính trong cộng đồng WP, đó là một công cụ mà mọi nhà phát triển PHP và WordPress ít nhất nên biết, nếu không sử dụng.

Câu trả lời này đã có kích thước cuốn sách để cho phép thảo luận thêm, và thảo luận về Nhà soạn nhạc ở đây có lẽ không có chủ đề, nó chỉ được đề cập vì sự hoàn chỉnh.

Để biết thêm thông tin truy cập vào trang Composer và nó cũng có giá trị cho một đọc này minisite giám tuyển bởi @Rarst .


1 PSR là các quy tắc tiêu chuẩn PHP được phát hành bởi Nhóm khung công tác PHP

2 Trình soạn thảo (một thư viện sẽ được đề cập trong câu trả lời này) trong số những thứ khác cũng chứa tiện ích trình tải tự động.


1
Một lưu ý nữa, rằng PHP 5.3 cũng đã hết tuổi thọ. Một máy chủ có trách nhiệm sẽ cung cấp ít nhất 5,4 dưới dạng tùy chọn nếu không phải là mặc định
Tom J Nowell

2
"Kể từ ngày 14 tháng 8 năm 2014, PHP 5.3 đã hết tuổi thọ. Nó chắc chắn đã chết." Là dòng đầu tiên trong "PHP 5.2 dành cho zombie" @TomJNowell
gmazzap

3
Chỉ cần tự hỏi, những gì bạn sẽ chỉ ra một "rất nhiều thứ" trông như thế nào? ;-)
MikeSchinkel

Trong nỗ lực tránh các biến toàn cục, tôi thích ý tưởng về mẫu Registry với biến & hàm tĩnh. Lần đầu tiên hàm được gọi, nó sẽ khởi tạo registry, trong các lần gọi tiếp theo, nó sẽ trả về nó.
Michael Ecklund

10

Tôi sử dụng cấu trúc sau:

Prefix_Example_Plugin::on_load();

/**
 * Example of initial class-based plugin load.
 */
class Prefix_Example_Plugin {

    /**
     * Hooks init (nothing else) and calls things that need to run right away.
     */
    static function on_load() {

        // if needed kill switch goes here (if disable constant defined then return)

        add_action( 'init', array( __CLASS__, 'init' ) );
    }

    /**
     * Further hooks setup, loading files, etc.
     *
     * Note that for hooked methods name equals hook (when possible).
     */
    static function init(  ) {


    }
}

Ghi chú:

  • đã xác định địa điểm cho những thứ cần phải chạy ngay lập tức
  • vô hiệu hóa / ghi đè cho các chỉnh sửa là dễ dàng (bỏ một initphương thức)
  • Tôi không nghĩ rằng tôi đã từng sử dụng / đối tượng cần thiết của lớp plugin - yêu cầu phải theo dõi nó, v.v; Đây thực sự là không gian tên giả theo mục đích, không phải OOP (hầu hết thời gian)

Tuyên bố miễn trừ trách nhiệm Tôi chưa sử dụng các bài kiểm tra đơn vị ( rất nhiều điều trên bản đồ của tôi) và tôi nghe rằng tĩnh có thể ít được ưa thích hơn đối với chúng. Làm nghiên cứu của bạn về điều này nếu bạn cần đơn vị kiểm tra nó.


3
Tôi biết những người lớn trong thử nghiệm đơn vị thực sự không thích các giải pháp tĩnh / đơn lẻ. Tôi nghĩ rằng nếu bạn hoàn toàn hiểu những gì bạn đang cố gắng đạt được bằng cách sử dụng tĩnh và ít nhất nhận thức được sự phân nhánh của việc đó thì việc thực hiện các phương pháp đó là hoàn toàn tốt. Các chủ đề hay xoay quanh vấn đề này tại Stack Overflow
Adam

Điều này làm tôi thực sự suy nghĩ. Vậy tại sao lại sử dụng Classes và không chỉ quay lại các hàm tiền tố đơn giản. Chúng ta làm điều này chỉ để có tên hàm / phương thức sạch hơn? Tôi có nghĩa là có chúng được lồng với một b4 "tĩnh" chúng có dễ đọc hơn nhiều không? Khả năng xảy ra xung đột tên là tương tự như đối với một tên lớp duy nhất nếu bạn sử dụng tiền tố propper hoặc tôi có thiếu thứ gì không?
James Mitch

1
@JamesMitch có, các phương thức tĩnh hầu hết chỉ là các hàm với không gian tên giả như được sử dụng trong WP. Tuy nhiên, các lớp có một số lợi thế so với các hàm thuần túy ngay cả trong trường hợp này, chẳng hạn như tự động tải và kế thừa. Gần đây tôi đã chuyển từ các phương thức tĩnh và hướng tới các đối tượng khởi tạo thực được tổ chức bởi thùng chứa phụ thuộc.
Hết

3

Tất cả phụ thuộc vào chức năng.

Tôi đã từng tạo một plugin đăng ký tập lệnh khi hàm tạo được gọi vì vậy tôi phải nối nó vào wp_enqueue_scriptshook.

Nếu bạn muốn gọi nó khi functions.phptệp của bạn được tải, bạn cũng có thể tự tạo một cá thể $class_instance = new ClassName();như bạn đã đề cập.

Bạn có thể muốn xem xét tốc độ và sử dụng bộ nhớ. Tôi không nhận thức được bất kỳ điều gì, nhưng tôi có thể tưởng tượng có những cái móc chưa được khám phá trong một số trường hợp. Bằng cách tạo cá thể của bạn tại hook đó, bạn có thể tiết kiệm một số tài nguyên máy chủ.


Thật tuyệt, cảm ơn vì điều đó, tôi cho rằng có hai điểm cho câu hỏi trên. Cái khác là liệu __construct có phù hợp hay không init () là cách tốt hơn để khởi tạo lớp.
kalpaitch

1
Tôi muốn dùng một init()phương thức tĩnh để thể hiện của lớp được gọi trong phạm vi của lớp thay vì một phạm vi khác mà bạn có thể ghi đè lên các biến hiện có.
Tim S.

0

Tôi biết đây là một vài năm tuổi, nhưng trong khi đó php 5.3 hỗ trợ các phương thức ẩn danh , vì vậy tôi đã nghĩ ra điều này:

add_action( 'plugins_loaded', function() { new My_Plugin(); } );

và bằng cách nào đó tôi thích nó nhất. Tôi có thể sử dụng các hàm tạo thông thường và không cần xác định bất kỳ phương thức "init" hoặc "on_load" nào làm xáo trộn các cấu trúc OOP của tôi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.