2011-12-26 27 views
5

Tôi đang làm việc trên một tập lệnh và tôi cần phải làm cho tập lệnh có thể bổ sung. Bây giờ cú pháp tôi đã đi kèm và cái nào sẽ làm việc cho tôi, là làm cho nó sử dụng các lớp. Ví dụ, để tạo một plugin mới có thể chạy khi một điểm nào đó (hook) đạt được, bạn sẽ khai báo một lớp mới. Những gì tôi không chắc chắn là móc sẽ được chỉ định như thế nào trong cú pháp đó, vì vậy tôi đang tìm kiếm các gợi ý.Làm cho tập lệnh có thể được bổ sung

Cú pháp Ví ​​dụ:

<?php 
class ScriptPlugin 
{ 
    function runPlugin() {} // would be run when the time has to come to execute this plugin 
} 
?> 

Ngoài ra, nếu cú ​​pháp đó sẽ không làm việc, nó sẽ là tuyệt vời nếu các bạn có thể cho tôi một ví dụ cú pháp tốt.

+0

Bạn chưa thêm mã vào câu hỏi thực sự sẽ hiển thị cú pháp bạn hỏi. Vui lòng thêm mã đó nếu không khó nói. – hakre

+0

có thể trùng lặp của [Cách tốt nhất để cho phép các plugin cho một ứng dụng PHP] (http://stackoverflow.com/questions/42/best-way-to-allow-plugins-for-a-php-application) – hakre

Trả lời

3

Có một mẫu quan sát quan sát. Plugin sẽ tự đăng ký và sẽ nhận được thông báo khi móc được gọi.

Một điều khác có trong tâm trí là gọi lại trong PHP. Và có một số similar question already với số an answer. Nó cho thấy móc dựa trên callbacks.

Mẫu quan sát chạy hơi ngắn vì móc bạn thường muốn cung cấp những thứ như đối số và giá trị trả lại.Câu trả lời được liên kết sử dụng callbacks cũng không có cái này, vì vậy tôi đã viết một lớp ví dụ nhỏ Hooks cung cấp các móc/sự kiện có tên cho các cuộc gọi lại đã đăng ký và cách đăng ký các lớp của riêng bạn, ví dụ: một cục sạc.

Ý tưởng là khá cơ bản:

  • Một móc có một cái tên và số không hoặc nhiều callbacks đính kèm.
  • Tất cả các móc được quản lý trong lớp học Hooks.
  • Mã chính gọi móc bằng cách gọi hàm trên đối tượng Hooks.
  • Plugins (và các lớp khác) có thể đăng ký gọi lại của riêng chúng, được thực hiện với sự trợ giúp của giao diện Registerable.

Một số mã ví dụ với một plugin và hai móc:

<?php 
Namespace Addon; 

class Hooks 
{ 
    private $hooks = array(); 
    private $arguments; 
    private $name; 
    private $return; 
    public function __call($name, array $arguments) 
    { 
     $name = (string) $name; 
     $this->name = $name; 
     $this->arguments = $arguments; 
     $this->return = NULL; 
     foreach($this->getHooks($name) as $hook) 
     { 
      $this->return = call_user_func($hook, $this); 
     } 
     return $this->return; 
    } 
    public function getHooks($name) 
    { 
     return isset($this->hooks[$name]) ? $this->hooks[$name] : array(); 
    } 
    public function getArguments() 
    { 
     return $this->arguments; 
    } 
    public function getName() 
    { 
     return $this->name; 
    } 
    public function getReturn() 
    { 
     return $this->return; 
    } 
    public function setReturn($return) 
    { 
     $this->return = $return; 
    } 
    public function attach($name, $callback) 
    { 
     $this->hooks[(string) $name][] = $callback; 
    } 
    public function register(Registerable $plugin) 
    { 
     $plugin->register($this); 
    } 
} 

interface Registerable 
{ 
    public function register(Hooks $hooks); 
} 

class MyPlugin implements Registerable 
{ 
    public function register(Hooks $hooks) 
    { 
     $hooks->attach('postPublished', array($this, 'postPublished')); 
     $hooks->attach('postDisplayFilter', array($this, 'filterToUpper')); 
    } 
    public function postPublished() 
    { 
     echo "MyPlugin: postPublished.\n"; 
    } 
    public function filterToUpper(Hooks $context) 
    { 
     list($post) = $context->getArguments(); 
     return strtoupper($post); 
    } 
} 

$hooks = new Hooks(); 

$plugin = new MyPlugin(); 
$hooks->register($plugin); 

$hooks->postPublished(); 

echo $hooks->postDisplayFilter("Some post text\n"); 

tôi đã thực hiện nó theo cách này để ngăn chặn điều đó mỗi Plugin phải có một lớp cơ sở bê tông chỉ vì nó muốn tận dụng móc . Ngoài ra tất cả mọi thứ có thể đăng ký móc, điều duy nhất cần thiết là một cuộc gọi lại. Ví dụ một chức năng ẩn danh:

$hooks->attach('hookName', function() {echo "Hook was called\n";}); 

Bạn tuy nhiên có thể tạo cho mình một lớp cơ sở plugin, mà ví dụ thực hiện các register chức năng và sẽ tự động đăng ký chức năng mà có một thẻ docblock nhất định hoặc tên của một hàm

class MyNewPlugin extends PluginSuper 
{ 
    /** 
    * @hook postPublished 
    */ 
    public function justAnotherFunction() {} 

    public hookPostPublished() {} 
} 

Siêu lớp có thể sử dụng số Reflection để thêm các móc khi chạy. Tuy nhiên, sự phản chiếu có thể làm chậm mọi thứ và có thể làm cho mọi việc khó khăn hơn để gỡ lỗi.

+0

Điều này hoạt động theo cách tôi muốn nó hoạt động. Tôi đã cố gắng triển khai lớp sẽ tự động đăng ký một hàm, nó sẽ được chạy khi plugin được khởi tạo, nhưng không thành công. Rất tiếc, tôi không biết nhiều về OOP: ( –

+0

Plugin cần đăng ký chức năng của nó trên móc. Bạn có thể muốn thêm mã của bạn vào cuối câu trả lời để tôi có thể xem xét. – hakre

0

Tôi sẽ tạo một lớp trừu tượng cơ bản với các hàm cho tất cả các móc có thể được gọi.

abstract class Plugin { 
    abstract function yourHook(); 
} 

Tất cả các lớp plugin sẽ kế thừa lớp cơ sở này và sẽ tự ghi đè các hàm cơ sở đó.

class SomePlugin extends Plugin { 
    function yourHook() { 
     echo 'yourHook() Called!'; 
    } 
} 

Bây giờ khi chương trình của bạn chạy, bạn cần phải tìm tất cả những file plugin để bao gồm, và bằng cách nào đó đặt chúng vào một mảng, chẳng hạn như $plugins. Xem bài viết này: https://stackoverflow.com/a/599694/362536

foreach (glob("classes/*.php") as $filename) 
{ 
    include $filename; 
} 

(Từ Karsten)

Xác định một chức năng truy cập từ tất cả mọi thứ, chẳng hạn như registerPlugin():

function registerPlugin($classname) { 
    $plugins[] = new $classname(); 
} 

Hãy dòng trên cùng của mỗi tập tin Plugin như thế này (trước lớp học):

registerPlugin('SomePlugin'); 

Nếu bạn làm điều này, bạn sẽ có một mảng trong $plugins với các phiên bản của mỗi plugin. Vào thời điểm thích hợp, bạn có thể làm điều gì đó như sau:

foreach ($plugins as $plugin) { 
    $plugin->yourHook(); 
} 

Thay vào đó, có thể thích hợp hơn khi sử dụng interfaces trong trường hợp của bạn. Bạn nên quyết định phương pháp nào là tốt nhất cho ứng dụng của bạn.

+0

Tất cả những gì là khỏe. Đó là chính xác những gì tôi muốn đạt được. Nhưng, những gì tôi đã thất bại, là tôi không thể nhận ra tên của lớp trong tệp của plugin là gì? Tôi không nghĩ rằng nó sẽ là tốt để yêu cầu các tập tin plugin để có cùng tên như lớp học, để biết những gì tên lớp thực sự có, phải không? –

+0

Tôi thấy, một giây trong khi tôi cập nhật bài đăng của mình bằng một phương thức. – Brad

+0

Ok, tôi đã cập nhật bài đăng của mình. Điều đó có ý nghĩa hơn bây giờ không? – Brad

0

Hãy nói rằng một plugin như:

class NewsPlugin extends Plugin 
{ 
    function onCreate($title) 
    { 
    # Do some stuff 
    } 
} 

Sau đó, khi bạn tạo một tin tức mà bạn chỉ có thể gọi onCreate trên tất cả các plugin đã đăng ký.

+0

Đó là cú pháp tôi đang cố gắng đạt được. Nhưng, tôi gặp vấn đề trong việc tìm kiếm tất cả các plugin. Làm thế nào tôi có thể làm điều đó? –

+0

Tôi thường đặt tất cả trong một thư mục gọi là 'plugins' và yêu cầu tất cả chúng trong tiêu đề của tôi bằng cách sử dụng' glob'. Tất cả chúng đều mở rộng cùng một lớp cơ sở. – Cydonia7

+0

Bạn nghĩ gì nếu tôi có thể sử dụng phương thức __construct() trong lớp Plugin, vì vậy khi một cá thể mới được tạo và dựa trên lớp đó, bằng cách nào đó nó sẽ tiến hành biến $ this đến mảng plugin? –

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