A legjobb módja annak, hogy plugins a PHP alkalmazás

szavazat
245

Én kezdő egy új webes alkalmazás PHP és ezúttal szeretnék létrehozni, amit az emberek terjedhet segítségével egy plugin interfész.

Hogyan lehet menni az írásról „horog” a saját kódját, hogy plugins is tulajdonítanak bizonyos eseményeket?

A kérdést 01/08/2008 13:50
a forrás felhasználó
Más nyelveken...                            


8 válasz

szavazat
14

Úgy vélem, a legegyszerűbb módja az lenne, hogy kövesse Jeff saját tanácsát, és nézzen körül a meglévő kódot. Próbáld ki nézi a Wordpress, Drupal, Joomla és más jól ismert PHP-alapú CMS hogy lássák API horgok megjelenését. Így akkor is kap ötleteket lehet, hogy nem gondolt korábban, hogy a dolgok egy kicsit rubust.

A közvetlenebb válasz az lenne, hogy írjon általános fájlok, hogy azok „include_once” a saját fájlt, amely biztosítja a használhatóságot lenne szükség. Ez kell bontani kategóriák és nem biztosított egy hatalmas „hooks.php” fájlt. Legyen óvatos, mert ami végül történik, hogy a fájlokat, hogy azok tartalmazzák a végén, amelyek egyre több függőségek és a funkcionalitás javul. Próbálja tartani API függőségek alacsony. IE kevesebb fájlt számukra, hogy tartalmazza.

Válaszolt 01/08/2008 14:44
a forrás felhasználó

szavazat
148

Jól jönne egy Observer minta. Egy egyszerű funkcionális módja Ehhez:

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

Megjegyzés:

Ebben a példában a forráskódot, akkor állapítsa meg az összes bővítményt, mielőtt a tényleges forrást, amit akar meghosszabbítható. Én már bele egy példát, hogyan kell kezelni egy vagy több értéket vezetjük a plugin. A legnehezebb része ennek az írás eredeti dokumentumok, amely felsorolja, milyen érvekkel kap telt minden horog.

Ez csak az egyik módszer megvalósítása egy bővítmény rendszert PHP. Vannak jobb alternatívák, azt javaslom, nézd meg a WordPress dokumentáció további információkért.

Sajnos úgy tűnik, aláhúzás karakter helyébe HTML entitások Markdown? Tudok újra tegye ezt a kódot, ha ezt a hibát kijavítják.

Edit: Nem baj, hogy csak akkor jelenik meg, hogy akkor, amikor egy szerkeszt

Válaszolt 01/08/2008 14:46
a forrás felhasználó

szavazat
31

A horog és hallgató módszer a leggyakrabban használt, de vannak más dolgok, amit tehetünk. Attól függően, hogy mekkora a app, és aki az megy, hogy látni a kódot (ez lesz a FOSS script, vagy valami a házban) is nagyban befolyásolja, hogyan szeretné, hogy dugó.

kdeloach egy szép példa, de a végrehajtás és a horog funkció egy kicsit veszélyes. Kérném, hogy még több információt a természet a php alkalmazás az írás, és hogyan látod plugins beszerelése.

+1 kdeloach tőlem.

Válaszolt 01/08/2008 18:23
a forrás felhasználó

szavazat
13

Van egy szép nevű projekt Stickleback Matt Zandstra a Yahoo, amely kezeli a munka nagy részét kezelésére plugins PHP.

Érvényesíti a felület egy plugin osztály, támogatja a parancssori felület, és nem túl nehéz felkelni és működtetése - különösen, ha elolvassa a címlapsztori róla a PHP építész magazin .

Válaszolt 17/09/2008 20:00
a forrás felhasználó

szavazat
10

Jó tanács, hogy nézd, milyen más projektek már megtették. Sok felhívást tartalmazó bővítmények telepítése és „name” regisztrált szolgáltatások (mint a WordPress nem), így van, „pont” a kódban, ahol a tétet egy függvény, amely azonosítja regisztrált hallgatók és végrehajtja. Egy standard OO tervezés kopog az Observer minta , ami egy jó lehetőség, hogy végre egy igazán objektumorientált PHP rendszer.

A Zend Framework él sok kampós módszerek, és nagyon szépen architektúrájú. Az lenne a jó rendszer, hogy nézd meg.

Válaszolt 17/09/2008 20:38
a forrás felhasználó

szavazat
19

Itt egy olyan megközelítés, amit használnak, ez egy kísérlet arra, hogy másolni Qt jelek / slot mechanizmus egyfajta Observer minta. Tárgyak bocsátanak ki jeleket. Minden jel egy azonosító a rendszerben - ez áll a küldő id + objektum nevét Minden jel lehet binded a vevők, ami egyszerűen egy „lehívható” Ön használja egy busz osztály a jeleket bárki érdekelt részesülő Ha valami megtörténik, akkor a „küldés” jelet. Az alábbiakban és példa megvalósítása

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

?>
Válaszolt 25/09/2008 22:29
a forrás felhasználó

szavazat
51

Tehát mondjuk nem szeretné az Observer minta, mert ahhoz, hogy változtassa meg osztály módszerek kezelni a feladatot hallgat, és szeretne valami általános. És mondjuk nem akarja használni, extendsöröklés, mert lehet, hogy már örökli az osztályban néhány más osztályban. Nem lenne jó, hogy egy általános módja annak, hogy minden osztályban dugaszolható különösebb erőfeszítés nélkül ? Itt van, hogyan:

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

Az 1. részben ez az, amit lehetnek egy require_once()hívást a tetején a PHP script. Betölti az osztályokat, hogy valamit is csatlakoztatható.

A 2. rész, ott töltünk egy osztály. Megjegyzés Nem kell semmit tennie, hogy az osztály, amely jelentősen eltér az Observer minta.

A 3. rész, ott váltunk mi osztály körül létre „dugaszolható” (azaz, támogatja a plugin, hogy menjünk felülírja osztály módszerek és tulajdonságok). Így például, ha van egy web app, lehet, hogy egy plugin adatbázis, és akkor lehet aktiválni plugins itt. Figyeljük meg azt is a Dog_bark_beforeEvent()funkciót. Ha én meg $mixed = 'BLOCK_EVENT', mielőtt a return, akkor blokkolja a kutyát ugatás és azt is blokkolja a Dog_bark_afterEvent mert nem lenne semmilyen esemény.

A 4. rész, ez a normál működés kódot, de észreveszi, hogy mit is gondol futna nem fut ilyen egyáltalán. Például, a kutya nem jelenti be nevét, mint „Fido”, de a „Coco”. A kutya nem mondom, hogy „miau”, de a „Woof”. És ha azt szeretné, hogy nézd meg a kutya nevére utólag, úgy találja, hogy „különböző” helyett „Coco”. Mindazok felülbírálja adtak a 3. részben.

Tehát hogyan működik ez? Nos, nézzük zárja ki eval()(ami mindenki azt mondja, hogy „rossz”), és zárja ki, hogy ez nem egy Observer minta. Tehát így működik az alattomos üres nevű osztályt dugaszolható, amely nem tartalmazza a módszerek és tulajdonságok által használt Dog osztályban. Így, mivel ez bekövetkezik, a mágikus módszerek részt számunkra. Ezért a 3. és 4. mi szórakozz a tárgy származó dugaszolható osztály, nem a kutya osztályban is. Ehelyett hagyja, hogy a Plugin osztályt nem a „megható” a kutya objektum számunkra. (Ha ez valamilyen tervezési minta nem tudni - kérem tudassa velem.)

Válaszolt 01/06/2009 06:59
a forrás felhasználó

szavazat
7

Meglep, hogy a legtöbb választ itt úgy tűnik, hogy úgy alakítsák körülbelül bővítmények helyi a webes alkalmazás, azaz a bővítmények futó helyi webszervert.

Mi a helyzet, ha akarta, hogy a bővítmények futtatását egy másik - távoli - szerver? A legjobb módja ennek az lenne, hogy olyan formában, amely lehetővé teszi, hogy meghatározza a különböző URL-eket, hogy hívnák, ha bizonyos események történnek az alkalmazás.

Különböző események küldene különböző alapuló információkat az esetben, ha most történt.

Ily módon, akkor csak annyit kell tennie a curl hívást a URL hogy nyújtottak be kérelmet (pl https protokollon keresztül), ahol a távoli szerver feladatok elvégzésére információk alapján küldték az alkalmazás.

Ez két előnye van:

  1. Nem kell, hogy a fogadó minden kódot a helyi szerver (biztonság)
  2. A kód lehet távoli szervereken (bővíthetőség) különböző nyelveken más, akkor a PHP (hordozhatóság)
Válaszolt 22/04/2013 08:41
a forrás felhasználó

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