PHP uygulaması için eklentileri izin vermek en iyi yolu

oy
245

İnsanların bir eklenti arabirimi kullanarak uzatabilirsiniz şey yaratmak istiyorum etrafında PHP yeni bir web uygulaması ve bu kez başlıyorum.

İnsan nasıl eklentileri belirli etkinlikler eklemek, böylece onların koduna 'kanca' yazma konusunda gider?

Oluştur 01/08/2008 saat 13:50
kaynak kullanıcı
Diğer dillerde...                            


8 cevaplar

oy
148

Bir Gözlemci deseni kullanabilirsiniz. Basit bir işlevsel yolu Bunu gerçekleştirmek için:

<?php

/** Plugin system **/

$listeners = array();

/* Create an entry point for plugins */
function hook() {
    global $listeners;

    $num_args = func_num_args();
    $args = func_get_args();

    if($num_args < 2)
        trigger_error("Insufficient arguments", E_USER_ERROR);

    // Hook name should always be first argument
    $hook_name = array_shift($args);

    if(!isset($listeners[$hook_name]))
        return; // No plugins have registered this hook

    foreach($listeners[$hook_name] as $func) {
        $args = $func($args); 
    }
    return $args;
}

/* Attach a function to a hook */
function add_listener($hook, $function_name) {
    global $listeners;
    $listeners[$hook][] = $function_name;
}

/////////////////////////

/** Sample Plugin **/
add_listener('a_b', 'my_plugin_func1');
add_listener('str', 'my_plugin_func2');

function my_plugin_func1($args) {
    return array(4, 5);
}

function my_plugin_func2($args) {
    return str_replace('sample', 'CRAZY', $args[0]);
}

/////////////////////////

/** Sample Application **/

$a = 1;
$b = 2;

list($a, $b) = hook('a_b', $a, $b);

$str  = "This is my sample application\n";
$str .= "$a + $b = ".($a+$b)."\n";
$str .= "$a * $b = ".($a*$b)."\n";

$str = hook('str', $str);
echo $str;
?>

Çıktı:

This is my CRAZY application
4 + 5 = 9
4 * 5 = 20

Notlar:

Bu örnek, kaynak kodu için, size uzatılabilir olmak istiyorum gerçek kaynak kodundan önce tüm eklentileri beyan etmelidir. Ben tek veya birden çok değerin eklentisine geçirilen işlemek için nasıl bir örneğini de bulabilirsiniz. Bu en zor kısmı her kancaya geçmiş olsun hangi argümanlar listeler gerçek belgelere yazıyor.

Bu PHP'de bir eklenti sistemi gerçekleştirerek sadece bir yöntemdir. Daha iyi alternatifler Ben daha fazla bilgi için WordPress Belgeleri kontrol önermek vardır.

Maalesef, karakterler Markdown HTML kuruluşlar tarafından değiştirilir alt çizgi belirir? Bu hata düzeltildi aldığında bu kodu yeniden gönderebilir.

Düzenle: düzenlerken Boş ver, sadece bu şekilde görünür

Cevap 01/08/2008 saat 14:46
kaynak kullanıcı

oy
51

O halde sen dinleme görevi işlemek için sınıf yöntemlerini değiştirmek ve jenerik şey istiyorum gerektirir çünkü Gözlemci deseni istemiyoruz diyelim. Ve en Kullanmak istemiyorum diyelim extendszaten başka sınıftan sınıfınızda devralan olabilir çünkü miras. Bunu yapmak için genel bir yol olması harika olmaz mıydı çok çaba olmadan herhangi bir sınıf takılabilir ? İşte nasıl:

<?php

////////////////////
// PART 1
////////////////////

class Plugin {

    private $_RefObject;
    private $_Class = '';

    public function __construct(&$RefObject) {
        $this->_Class = get_class(&$RefObject);
        $this->_RefObject = $RefObject;
    }

    public function __set($sProperty,$mixed) {
        $sPlugin = $this->_Class . '_' . $sProperty . '_setEvent';
        if (is_callable($sPlugin)) {
            $mixed = call_user_func_array($sPlugin, $mixed);
        }   
        $this->_RefObject->$sProperty = $mixed;
    }

    public function __get($sProperty) {
        $asItems = (array) $this->_RefObject;
        $mixed = $asItems[$sProperty];
        $sPlugin = $this->_Class . '_' . $sProperty . '_getEvent';
        if (is_callable($sPlugin)) {
            $mixed = call_user_func_array($sPlugin, $mixed);
        }   
        return $mixed;
    }

    public function __call($sMethod,$mixed) {
        $sPlugin = $this->_Class . '_' .  $sMethod . '_beforeEvent';
        if (is_callable($sPlugin)) {
            $mixed = call_user_func_array($sPlugin, $mixed);
        }
        if ($mixed != 'BLOCK_EVENT') {
            call_user_func_array(array(&$this->_RefObject, $sMethod), $mixed);
            $sPlugin = $this->_Class . '_' . $sMethod . '_afterEvent';
            if (is_callable($sPlugin)) {
                call_user_func_array($sPlugin, $mixed);
            }       
        } 
    }

} //end class Plugin

class Pluggable extends Plugin {
} //end class Pluggable

////////////////////
// PART 2
////////////////////

class Dog {

    public $Name = '';

    public function bark(&$sHow) {
        echo "$sHow<br />\n";
    }

    public function sayName() {
        echo "<br />\nMy Name is: " . $this->Name . "<br />\n";
    }


} //end class Dog

$Dog = new Dog();

////////////////////
// PART 3
////////////////////

$PDog = new Pluggable($Dog);

function Dog_bark_beforeEvent(&$mixed) {
    $mixed = 'Woof'; // Override saying 'meow' with 'Woof'
    //$mixed = 'BLOCK_EVENT'; // if you want to block the event
    return $mixed;
}

function Dog_bark_afterEvent(&$mixed) {
    echo $mixed; // show the override
}

function Dog_Name_setEvent(&$mixed) {
    $mixed = 'Coco'; // override 'Fido' with 'Coco'
    return $mixed;
}

function Dog_Name_getEvent(&$mixed) {
    $mixed = 'Different'; // override 'Coco' with 'Different'
    return $mixed;
}

////////////////////
// PART 4
////////////////////

$PDog->Name = 'Fido';
$PDog->Bark('meow');
$PDog->SayName();
echo 'My New Name is: ' . $PDog->Name;

Bölüm 1'de size bir ile içerebilir nedir require_once()PHP komut dosyası üstündeki çağrısı. Bu şey takılabilir hale getirmek için sınıfları yükler.

Biz bir sınıf yük nereye 2. Bölümünde, bu. Ben Gözlemci deseni büyük ölçüde farklıdır sınıfına, özel bir şey yapmak zorunda değildi unutmayın.

Biz "takılabilir" ortaya etrafında sınıfımızı geçmek nerede Bölüm 3'te, işte (yani, bize sınıf yöntemleri ve özellikleri geçersiz izin eklentileri destekler). Eğer bir web uygulaması varsa Dolayısıyla, örneğin, bir eklenti kayıt olabilir ve burada eklentileri aktif hale olabilir. Ayrıca dikkat edin Dog_bark_beforeEvent()fonksiyonunu. Ben ayarlarsanız $mixed = 'BLOCK_EVENT'iade ifade önce, o havlıyor köpeği engeller ve herhangi bir olay olmaz, çünkü aynı zamanda Dog_bark_afterEvent engeller.

Bölüm 4'te, bu normal operasyon şifre, ama ne düşünebilir hiç böyle çalışmaz aday olacağını dikkat edin. Örneğin, köpek 'fino' ama 'Coco' olarak adını duyurmak etmez. Köpek 'miyav' ama 'Woof' demiyor. Eğer sonradan köpeğin adının bakmak istediğinizde, bunu yerine 'Coco' arasında 'Farklı' olduğunu bulmak. Tüm bu geçersiz kılma Bölüm 3'te verilmiştir.

Peki bu işler? O zaman gidip yönetmesine izin eval()( "kötü" olan herkes söylüyor) ve bir gözlemci desen olmadığını ekarte. Yani, nasıl işlediğine Köpek sınıfı tarafından kullanılan yöntemleri ve özellikleri içermez Takılabilir denilen sinsi boş sınıfıdır. Bu meydana beri Dolayısıyla, sihirli yöntemleri bizim için meşgul olacaktır. Bu yüzden parça 3 ve takılabilir sınıftan türetilen nesne ile 4 biz karmaşa içinde değil Köpek sınıfı kendisi. Bunun yerine, Eklenti sınıf bizim için Köpek nesne üzerinde "dokunma" yapalım. (Ben bilmem tasarım deseni çeşit ise - lütfen bana bildirin.)

Cevap 01/06/2009 saat 06:59
kaynak kullanıcı

oy
31

Kanca ve dinleyici yöntemi en yaygın olarak kullanılan, ancak yapabileceğimiz başka şeyler vardır. Uygulamanızın boyutuna bağlı olarak, ve sizin kodu görmek izin vermeyecek kim eklentileri izin vermek istediğiniz kadar büyük ölçüde etkileyecektir (bu FOSS komut veya evde bir şey olacak olan).

kdeloach güzel bir örnek vardır, ama onun uygulanması ve kanca işlevi biraz güvensiz. Eğer php uygulamanın özellikleri yazınızı daha bilgi vermek için ben isteyeceğini, Ve nasıl uydurma eklentileri görüyoruz.

1 benden kdeloach için.

Cevap 01/08/2008 saat 18:23
kaynak kullanıcı

oy
19

İşte kullandım bir yaklaşımdır, bu Qt sinyaller / yuvaları mekanizmadan kopyalamak için bir girişim, Observer desen bir tür. Nesne sinyalleri çıkarabilir. Her sinyal sistemindeki bir kimliği var - Ne zaman bir şey onları aldıktan Her sinyal basitçe bir "çağrılabilir" Sen ilgilenen kimseye sinyalleri geçirmek için bir otobüs sınıfını kullanmaktır alıcıları, binded edilebilir gönderenin kimliği + nesne adıyla oluşan oluyor , bir sinyal "gönderme" olmuyorsa. Aşağıda ve örnek uygulamasıdır

    <?php

class SignalsHandler {


    /**
     * hash of senders/signals to slots
     *
     * @var array
     */
    private static $connections = array();


    /**
     * current sender
     *
     * @var class|object
     */
    private static $sender;


    /**
     * connects an object/signal with a slot
     *
     * @param class|object $sender
     * @param string $signal
     * @param callable $slot
     */
    public static function connect($sender, $signal, $slot) {
        if (is_object($sender)) {
            self::$connections[spl_object_hash($sender)][$signal][] = $slot;
        }
        else {
            self::$connections[md5($sender)][$signal][] = $slot;
        }
    }


    /**
     * sends a signal, so all connected slots are called
     *
     * @param class|object $sender
     * @param string $signal
     * @param array $params
     */
    public static function signal($sender, $signal, $params = array()) {
        self::$sender = $sender;
        if (is_object($sender)) {
            if ( ! isset(self::$connections[spl_object_hash($sender)][$signal])) {
                return;
            }
            foreach (self::$connections[spl_object_hash($sender)][$signal] as $slot) {
                call_user_func_array($slot, (array)$params);
            }

        }
        else {
            if ( ! isset(self::$connections[md5($sender)][$signal])) {
                return;
            }
            foreach (self::$connections[md5($sender)][$signal] as $slot) {
                call_user_func_array($slot, (array)$params);
            }
        }

        self::$sender = null;
    }


    /**
     * returns a current signal sender
     *
     * @return class|object
     */
    public static function sender() {
        return self::$sender;
    }

}   

class User {

    public function login() {
        /**
         * try to login
         */
        if ( ! $logged ) {
            SignalsHandler::signal(this, 'loginFailed', 'login failed - username not valid' );
        }
    }

}

class App {
    public static function onFailedLogin($message) {
        print $message;
    }
}


$user = new User();
SignalsHandler::connect($user, 'loginFailed', array($Log, 'writeLog'));
SignalsHandler::connect($user, 'loginFailed', array('App', 'onFailedLogin'));

$user->login();

?>
Cevap 25/09/2008 saat 22:29
kaynak kullanıcı

oy
14

Ben kolay yolu Jeff'in kendi tavsiyesine uyup mevcut kodu etrafına bir göz atmak olacağına inanıyorum. Wordpress, Drupal, Joomla ve bakarak deneyin diğer iyi bilinen PHP tabanlı CMS adlı kendi API kanca bakmak ve nasıl hissettiğini görmek için. Hatta şeyleri biraz daha rubust yapmak için daha önce düşünmemiştim olabilir fikir edinebilirsiniz Bu şekilde.

Bir daha doğrudan yanıt kendi dosyasına "include_once" onlar gerekir kullanılabilirlik sağlayacak ediyorum Genel dosyaları yazmak olacaktır. Bu kategoriye bölünmüştür ve bir MASİF "hooks.php" dosyasında verilen DEĞİL olacaktır. Ne oluyor biter içerdikleri dosyaları daha bağımlılıkları ve işlevsellik geliştirir sahip sonunda yani, çünkü, gerçi dikkatli olun. Düşük API bağımlılıkları tutmaya çalışın. Onlar için IE az Eklenecek dosya.

Cevap 01/08/2008 saat 14:44
kaynak kullanıcı

oy
13

Denilen düzgün bir projem var Stickleback PHP eklentileri ele İşin çoğunu kolları Yahoo Matt Zandstra tarafından.

Bu bir eklenti sınıfının arayüzü, bir komut satırı arayüzü destekler ve çok kalkmak sert ve koşu değil zorlar - Eğer bu konuda kapak hikayesini okumak, özellikle PHP mimarı dergisi .

Cevap 17/09/2008 saat 20:00
kaynak kullanıcı

oy
10

İyi tavsiye yapmış nasıl diğer projeler bakmaktır. Yüklenen eklentileri ve onların "ismini" sahibi olmak için birçok çağrı hizmetleri için kayıtlı (gibi wordpress yapar) böylece size kayıtlı dinleyicileri tanımlar ve bunları yürüten bir işlevi çağırmak kodunuzda "noktaları" var. Standart bir OO tasarım pıtır olan Gözlemci Desen gerçekten nesne yönelimli PHP sisteminde uygulamak için iyi bir seçenek olacaktır.

Zend Framework birçok çengel yöntemler kullanmaktadır ve çok güzel architected edilir. Yani bakmak için iyi bir sistem olacaktır.

Cevap 17/09/2008 saat 20:38
kaynak kullanıcı

oy
7

Burada cevapların çoğu web uygulaması için yerel olan eklentilerin, yani yerel web sunucusu üzerinde çalışan eklentiler hakkında dişli gibi görünüyor şaşırıyorum.

Ne eklentileri farklı üzerine yapmak isterse hakkında - uzak - sunucunun? Bunu yapmanın en iyi yolu, belirli olaylar uygulamanızda ortaya çıktığında aranmak farklı URL'ler tanımlamak için izin veren bir formu temin etmek olacaktır.

Farklı olaylar sadece vuku etkinliğe dayalı farklı bilgileri gönderir.

Bu şekilde, sadece uzak sunucular uygulamanız tarafından gönderilen bilgilere dayalı görevleri gerçekleştirebilirsiniz nerede (örneğin https üzerinden) uygulamanıza sağlanmıştır URL'ye bir cURL çağrı yapmak istiyorum.

Bunun iki faydası:

  1. Eğer yerel sunucuda herhangi bir kod barındırması gerekmez (güvenlik)
  2. Kod farklı dillerde uzak sunuculara (genişletilebilirlik) üzerinde olabilir diğer ardından PHP (taşınabilirlik)
Cevap 22/04/2013 saat 08:41
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more