Bir PHP uygulama için eklentileri sağlamak için en iyi yol

7 Cevap php

PHP yeni bir web uygulaması başladım ve bu sefer ben insanların bir eklenti arabirimi kullanarak uzatabilirsiniz şey yaratmak istiyorum. Eklentileri belirli olaylar eklemek böylece nasıl biri kendi koduna 'kanca' yazma konusunda gidiyor?

7 Cevap

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

<?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;

?>

Output:

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

Notes:

Bu örnek kaynak kodu, size uzatılabilir olmak istediğiniz asıl kaynak kodu önce tüm eklentileri bildirmeniz gerekir. Ben eklenti geçirilen tek veya çoklu değerleri işlemek için nasıl bir örnek ekledim. Bu zor kısmı argümanlar her kancaya geçmiş olsun ne listeler gerçek belgelere yazıyor.

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

Sorry, it appears underscore characters are replaced by HTML entities by Markdown? I can re-post this code when this bug gets fixed.

Edit: Nevermind, it only appears that way when you are editing

Yani bu dinleme görevini işlemek için sınıf yöntemleri değiştirmek gerektirir çünkü Observer deseni istemiyorum diyelim, ve genel bir şey istiyorum. Ve en sen zaten bazı diğer sınıftan kendi sınıfında miras olabilir, çünkü extends devralma kullanmak istemiyorum diyelim. Bunu yapmak için genel bir yol var harika olmaz mıydı any class pluggable without much effort? İş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, bu sizin PHP script üstünde bir Require_once () çağrısı ile içerebilir budur. Bu takılabilir bir şey yapmak için sınıfları yükler.

Biz sınıf yüklemek nerede Bölüm 2, budur. Ben Observer desen önemli ölçüde farklıdır sınıf, özel bir şey yapmak yoktu unutmayın.

Bölüm 3'te, biz (yani, bize sınıfı yöntemlerini ve özelliklerini geçersiz izin eklentileri destekler) "geçmeli" olma haline etrafında bizim sınıf geçmek nerede. Eğer bir web uygulaması var ise, örneğin, bir eklenti kayıt olabilir ve burada eklentileri aktive olabilir. Aynı zamanda "Dog_bark_beforeEvent" fonksiyonu dikkat edin. Ben return deyimi önce $ karışık = 'BLOCK_EVENT' ayarlarsanız, bu havlayan gelen köpek engeller ve herhangi bir olay olmaz, çünkü aynı zamanda Dog_bark_afterEvent bloke olur.

Bölüm 4'te, bu normal bir işlem kodu, ama ne aday olacağını düşündüğünüz hiç böyle çalışmaz dikkat edin. Örneğin, köpek o 'fino' olarak adı duyurmak değil, ama 'Coco'. Köpek 'miyav' demek, ama 'Hav' değildir. Sonradan köpeğin adının bakmak istediğinizde, bunu yerine 'Coco' ve 'Farklı' bulmak. Tüm bu overrides Bölüm 3'te verilmiştir.

Peki bu nasıl çalışır? Peki,) (en eval ekarte edelim (herkes "kötü" olan diyor) ve bir Observer desen olmadığını ekarte. Yani, o inşaat yolu Köpek sınıfı tarafından kullanılan yöntemleri ve özellikleri içermez Geçmeli denilen sinsi boş sınıftır. Bu meydana beri Böylece, sihirli yöntemler bizi meşgul edecek. Bu yüzden parça 3 ve Geçmeli sınıfından değil Köpek sınıfı kendisinden türetilmiş nesne ile 4 biz bir karmaşa içinde. Bunun yerine, biz Plugin sınıfı bizim için Köpek nesne üzerinde "dokunaklı" yapalım. (Ben bilmem tasarım deseni çeşit varsa - bana bildirin lütfen.)

hook ve listener yöntemi en yaygın olarak kullanılan, ancak yapabileceğiniz başka şeyler vardır. App boyutu ve kim (bu FOSS komut, ya da evde bir şey olacak) Eğer eklentileri izin vermek istiyorum nasıl büyük ölçüde etkileyecektir kodunu görmek izin vereceğim bağlı.

kdeloach güzel bir örnek vardır, ama onun uygulanması ve kanca işlevi biraz güvensiz olduğunu. Eğer php app yazma niteliği daha fazla bilgi vermek için ben rica ediyorum, Ve bakın nasıl eklentileri içeri uydurma

+1 Benden kdeloach için.

İyi tavsiye diğer projeler yaptım nasıl bakmaktır. Eklentileri yüklü ve onların "ismini" hizmetleri için kayıtlı (wordpress gibi yapar) sahip böylece kayıtlı dinleyicileri tanımlar ve onları yürütür bir işlevi çağırmak nerede kodunuzu "noktaları" için birçok çağrı. Standart OO tasarım pıtır gerçekten odaklı nesne PHP sistemde uygulamak için iyi bir seçenek olacağını, Observer Pattern olduğunu.

Zend Framework birçok çengel yöntemleri kullanır ve çok güzel mimarili edilir. O bakmak için iyi bir sistem olacaktır.

Ben kolay yolu Jeff'in kendi tavsiye takip ve mevcut kodu etrafına bir göz olacağına inanıyorum. Onların API kanca bakmak ve nasıl hissettiğini görmek için Wordpress, Drupal, Joomla ve diğer iyi bilinen PHP tabanlı CMS bakarak deneyin. Bu şekilde bile işler biraz daha rubust yapmak için önce düşünce değil olabilir fikir edinebilirsiniz.

Daha doğrudan bir cevap Genel dosyaları yazmak için olacağını onlar gerekir kullanılabilirliğini sağlayacak kendi dosyasına "include_once" olur. Bu kategoriye bölünmüştür ve bir MASİF "hooks.php" dosyasında sağlanan DEĞİL olacaktır. Ne oluyor bitiyor onlar daha bağımlılıkları ve işlevsellik sahip sona içeren dosyalar geliştirir, çünkü olsa da dikkatli olun. Düşük API bağımlılıkları tutmaya çalışın. I.E onları dahil etmek için daha az dosya.

PHP eklentileri işleme için çok iş kolları Yahoo Matt Zandstra tarafından Stickleback denilen düzgün bir proje var.

Eğer PHP architect magazine bu konuda kapak hikayesini okumak, - özellikle bir eklenti sınıfın arayüzü, bir komut satırı arabirimini destekliyor ve çok kalkmak zor ve çalışan değildir zorlar.

Ben burada cevapların çoğu web uygulaması için yerel eklentileri, yani yerel web sunucusu çalıştırmak eklentileri hakkında dişli gibi görünüyor şaşırıyorum.

Ne eklentileri farklı bir çalıştırmak istedim hakkında - uzak - sunucuya? Bunu yapmanın en iyi yolu, belirli olaylar uygulama ortaya çıktığında denilen olacağını farklı URL'ler tanımlamak için izin veren bir form sağlamak olacaktır.

Farklı olaylar sadece vuku olaya dayalı farklı bilgi göndermek istiyorum.

Bu şekilde, sadece uzaktan sunucuları uygulama tarafından gönderilen olmuştur bilgilere dayalı görevleri gerçekleştirebilirsiniz nerede (https gibi) uygulamanıza sağlanmıştır URL'ye bir cURL çağrı yapmak istiyorum.

Bunun iki faydası vardır:

  1. Eğer yerel sunucu (güvenlik) üzerinde herhangi bir kod barındırmak zorunda değilsiniz
  2. Kodu farklı dillerde uzak sunuculara (uzamayı) diğer ardından PHP (taşınabilirlik) olabilir