Events Manager Phalcon

Tujuan dari Events Manager Phalcon adalah untuk mencegat pelaksanaan berbagai komponen dari framework dengan menciptakan “hook poin”. Poin kait ini memungkinkan pengembang untuk mendapatkan informasi status, memanipulasi data atau mengubah aliran eksekusi selama prosesi komponen.

Contoh Penggunaan 

Dalam contoh berikut, kita menggunakan EventsManager untuk mendengarkan peristiwa yang dihasilkan dalam koneksi MySQL yg dikelola oleh Phalcon \ Db . Pertama, kita perlu objek pendengar untuk melakukan hal ini. Kita menciptakan sebuah kelas yg metodenya sesuai dgn nama event yg hendak didengar:

<?php

class MyDbListener
{

    public function afterConnect()
    {

    }

    public function beforeQuery()
    {

    }

    public function afterQuery()
    {

    }

}

Kelas baru ini dapat dibuat verbose bila kita butuhkan. EventsManager akan menjadi antarmuka antara komponen dan kelas pendengar kita, menawarkan titik kait berdasarkan metode yang kita didefinisikan dalam kelas pendengar kita:

<?php

use Phalcon\Events\Manager as EventsManager,
    Phalcon\Db\Adapter\Pdo\Mysql as DbAdapter;

$eventsManager = new EventsManager();

//Create a database listener
$dbListener = new MyDbListener();

//Listen all the database events
$eventsManager->attach('db', $dbListener);

$connection = new DbAdapter(array(
    "host" => "localhost",
    "username" => "root",
    "password" => "secret",
    "dbname" => "invo"
));

//Assign the eventsManager to the db adapter instance
$connection->setEventsManager($eventsManager);

//Send a SQL command to the database server
$connection->query("SELECT * FROM products p WHERE p.status = 1");

Dalam rangka untuk log semua pernyataan SQL yg dieksekusi oleh aplikasi kita, kita perlu menggunakan event “afterQuery”. Parameter pertama dilewatkan ke pendengar event berisi informasi kontekstual tentang peristiwa yang sedang berjalan, yang kedua adalah koneksi itu sendiri.

<?php

use Phalcon\Logger\Adapter\File as Logger;

class MyDbListener
{

    protected $_logger;

    public function __construct()
    {
        $this->_logger = new Logger("../apps/logs/db.log");
    }

    public function afterQuery($event, $connection)
    {
        $this->_logger->log($connection->getSQLStatement(), \Phalcon\Logger::INFO);
    }

}

Sebagai bagian dari contoh ini, kami juga akan menerapkan Phalcon \ Db \ Profiler untuk mendeteksi pernyataan SQL yang lebih lama untuk dieksekusi dari yang diharapkan:

<?php

use Phalcon\Db\Profiler,
    Phalcon\Logger,
    Phalcon\Logger\Adapter\File;

class MyDbListener
{

    protected $_profiler;

    protected $_logger;

    /**
     * Creates the profiler and starts the logging
     */
    public function __construct()
    {
        $this->_profiler = new Profiler();
        $this->_logger = new Logger("../apps/logs/db.log");
    }

    /**
     * This is executed if the event triggered is 'beforeQuery'
     */
    public function beforeQuery($event, $connection)
    {
        $this->_profiler->startProfile($connection->getSQLStatement());
    }

    /**
     * This is executed if the event triggered is 'afterQuery'
     */
    public function afterQuery($event, $connection)
    {
        $this->_logger->log($connection->getSQLStatement(), Logger::INFO);
        $this->_profiler->stopProfile();
    }

    public function getProfiler()
    {
        return $this->_profiler;
    }

}

Data profil yang dihasilkan dapat diambil dari pendengar:

<?php

//Send a SQL command to the database server
$connection->execute("SELECT * FROM products p WHERE p.status = 1");

foreach ($dbListener->getProfiler()->getProfiles() as $profile) {
    echo "SQL Statement: ", $profile->getSQLStatement(), "\n";
    echo "Start Time: ", $profile->getInitialTime(), "\n";
    echo "Final Time: ", $profile->getFinalTime(), "\n";
    echo "Total Elapsed Time: ", $profile->getTotalElapsedSeconds(), "\n";
}

Dengan cara yang sama kita dapat mendaftar fungsi lambda untuk melakukan tugas bukannya kelas pendengar yang terpisah (seperti terlihat di atas):

<?php

//Listen all the database events
$eventManager->attach('db', function($event, $connection) {
    if ($event->getType() == 'afterQuery') {
        echo $connection->getSQLStatement();
    }
});

Menciptakan komponen yang memicu Events 

Anda dapat membuat komponen dalam aplikasi Anda yang memicu peristiwa ke EventsManager. Akibatnya, mungkin ada pendengar yang bereaksi terhadap peristiwa tsb saat dihasilkan. Pada contoh berikut kita sedang menciptakan komponen yang disebut “MyComponent”. Komponen ini compatible dgn EventsManager; ketika metode nya “someTask” dijalankan memicu dua peristiwa untuk setiap pendengar di EventsManager ini:

<?php

use Phalcon\Events\EventsAwareInterface;

class MyComponent implements EventsAwareInterface
{

    protected $_eventsManager;

    public function setEventsManager($eventsManager)
    {
        $this->_eventsManager = $eventsManager;
    }

    public function getEventsManager()
    {
        return $this->_eventsManager;
    }

    public function someTask()
    {
        $this->_eventsManager->fire("my-component:beforeSomeTask", $this);

        // do some task

        $this->_eventsManager->fire("my-component:afterSomeTask", $this);
    }

}

Perhatikan bahwa peristiwa yang dihasilkan oleh komponen ini diawali dengan “my-componen”. Ini adalah kata yang unik yang membantu kita mengidentifikasi peristiwa yang dihasilkan dari komponen tertentu. Anda bahkan dapat menghasilkan peristiwa di luar komponen dengan nama yang sama. Sekarang mari kita membuat pendengar untuk komponen ini:

<?php

class SomeListener
{

    public function beforeSomeTask($event, $myComponent)
    {
        echo "Here, beforeSomeTask\n";
    }

    public function afterSomeTask($event, $myComponent)
    {
        echo "Here, afterSomeTask\n";
    }

}

Pendengar hanyalah sebuah kelas yang mengimplementasikan salah satu dari semua peristiwa dipicu oleh komponen. Sekarang mari kita membuat semuanya bekerja sama:

<?php

//Create an Events Manager
$eventsManager = new Phalcon\Events\Manager();

//Create the MyComponent instance
$myComponent = new MyComponent();

//Bind the eventsManager to the instance
$myComponent->setEventsManager($eventsManager);

//Attach the listener to the EventsManager
$eventsManager->attach('my-component', new SomeListener());

//Execute methods in the component
$myComponent->someTask();

Sebagaimana “someTask” dijalankan, dua metode dalam pendengar akan dieksekusi, menghasilkan output sebagai berikut:

Here, beforeSomeTask
Here, afterSomeTask

Data tambahan juga dapat diberikan ketika memicu suatu peristiwa dengan menggunakan parameter ketiga “fire”:

<?php

$eventsManager->fire("my-component:afterSomeTask", $this, $extraData);

Dalam pendengar parameter ketiga juga menerima data ini:

<?php

//Receiving the data in the third parameter
$eventManager->attach('my-component', function($event, $component, $data) {
    print_r($data);
});

//Receiving the data from the event context
$eventManager->attach('my-component', function($event, $component) {
    print_r($event->getData());
});

Jika pendengar hanya tertarik untuk mendengarkan jenis tertentu event Anda dapat melampirkan pendengar langsung:

<?php

//The handler will only be executed if the event triggered is "beforeSomeTask"
$eventManager->attach('my-component:beforeSomeTask', function($event, $component) {
    //...
});

Propagasi Event / Pembatalan 

Banyak pendengar dapat ditambahkan ke event manager yang sama, ini berarti bahwa untuk jenis yang sama event banyak pendengar bisa dikaitkan. Para pendengar akan diberitahu dalam urutan saat mereka terdaftar dalam EventsManager. Beberapa event dapat dibatalkan, menunjukkan bahwa bisa jadi event dihentikan mencegah pendengar lain akan diberitahu tentang event tersebut:

<?php

$eventsManager->attach('db', function($event, $connection){

    //We stop the event if it is cancelable
    if ($event->isCancelable()) {
        //Stop the event, so other listeners will not be notified about this
        $event->stop();
    }

    //...

});

Secara default event yang dibatalkan, bahkan sebagian besar peristiwa yang dihasilkan oleh framework dapat dibatalkan/cancelable. Anda dapat memicu event yg tidak dapat dibatalkan dengan memberikan “false” pada parameter keempat “fire”:

<?php

$eventsManager->fire("my-component:afterSomeTask", $this, $extraData, false);

Prioritas pendengar 

Saat memasang pendengar Anda dapat mengatur prioritas tertentu. Dengan fitur ini Anda dapat melampirkan pendengar menunjukkan urutan di mana mereka harus dipanggil:

<?php

$evManager->enablePriorities(true);

$evManager->attach('db', new DbListener(), 150); //More priority
$evManager->attach('db', new DbListener(), 100); //Normal priority
$evManager->attach('db', new DbListener(), 50); //Less priority

Mengumpulkan Responses 

Manajer acara dapat mengumpulkan setiap respon dikembalikan oleh setiap pendengar diberitahu, contoh ini menjelaskan cara kerjanya:

<?php

use Phalcon\Events\Manager as EventsManager;

$evManager = new EventsManager();

//Set up the events manager to collect responses
$evManager->collectResponses(true);

//Attach a listener
$evManager->attach('custom:custom', function() {
    return 'first response';
});

//Attach a listener
$evManager->attach('custom:custom', function() {
    return 'second response';
});

//Fire the event
$evManager->fire('custom:custom', null);

//Get all the collected responses
print_r($evManager->getResponses());

Contoh di atas menghasilkan:

Array ( [0] => first response [1] => second response )

Menerapkan Anda sendiri EventsManager 

antarmuka Phalcon \ Events \ ManagerInterface  harus diimplementasikan untuk menciptakan EventsManager Anda sendiri menggantikan yang disediakan oleh Phalcon.

Terjemahan dr Events Manager Phalcon http://docs.phalconphp.com/en/latest/reference/events.html