Annotations Parser Phalcon

Ini adalah pertama kalinya sebuah komponen parser Anotasi ditulis dalam bahasa  C untuk PHP. Phalcon\Annotations adalah komponen multiguna Annotations Parser Phalcon yang memberikan kemudahan parsing dan cache Anotasi dalam class PHP yang akan digunakan dalam aplikasi.

Anotasi dibaca dari docblocks di dalam class, metode dan properti. Anotasi dapat ditempatkan pada setiap posisi di docblock:

<?php

/**
 * This is the class description
 *
 * @AmazingClass(true)
 */
class Example
{

    /**
     * This a property with a special feature
     *
     * @SpecialFeature
     */
    protected $someProperty;

    /**
     * This is a method
     *
     * @SpecialFeature
     */
    public function someMethod()
    {
        // ...
    }

}

Dalam contoh di atas kita menemukan beberapa Anotasi di bagian komentar, anotasi memiliki sintaks berikut:

@Annotation-Name[(param1, param2, …)]

Dan juga, anotasi dapat ditempatkan pada setiap bagian dari docblock:

<?php

/**
 * This a property with a special feature
 *
 * @SpecialFeature
 *
 * More comments
 *
 * @AnotherSpecialFeature(true)
 */

Parser ini sangat fleksibel, contoh docblock ini jg bisa digunakan:

<?php

/**
 * This a property with a special feature @SpecialFeature({
someParameter="the value", false

 })  More comments @AnotherSpecialFeature(true) @MoreAnnotations
 **/

Namun, untuk membuat kode lebih maintainable (mudah dirawat) dan dimengerti, dianjurkan untuk menempatkan anotasi pada baris2 akhir docblock:

<?php

/**
 * This a property with a special feature
 * More comments
 *
 * @SpecialFeature({someParameter="the value", false})
 * @AnotherSpecialFeature(true)
 */

Membaca Anotasi 

Sebuah reflektor diimplementasikan untuk mendapatkan anotasi yang didefinisikan pada class menggunakan antarmuka berorientasi obyek:

<?php

$reader = new \Phalcon\Annotations\Adapter\Memory();

//Reflect the annotations in the class Example
$reflector = $reader->get('Example');

//Read the annotations in the class' docblock
$annotations = $reflector->getClassAnnotations();

//Traverse the annotations
foreach ($annotations as $annotation) {

    //Print the annotation name
    echo $annotation->getName(), PHP_EOL;

    //Print the number of arguments
    echo $annotation->numberArguments(), PHP_EOL;

    //Print the arguments
    print_r($annotation->getArguments());
}

Proses pembacaan anotasi ini sangat cepat, namun, untuk alasan kinerja dianjurkan untuk menyimpan parsing anotasi ini menggunakan adaptor. Adapter men-cache anotasi yg telah diproses untuk menghindari proses parsing yg berulang-ulang.

Phalcon \ Annotations \ Adapter \ Memory digunakan dalam contoh di atas. Adaptor ini hanya men-cache anotasi sementara proses request sedang berjalan, karena itu adaptor ini lebih cocok untuk development. Ada adapter lain sbg pengganti ketika aplikasi dalam tahap production/penerapan.

Jenis Anotasi 

Anotasi dapat memiliki parameter. Sebuah parameter bisa berupa literal sederhana (string, angka, boolean, null), array, daftar hash atau penjelasan lainnya:

<?php

/**
 * Simple Annotation
 *
 * @SomeAnnotation
 */

/**
 * Annotation with parameters
 *
 * @SomeAnnotation("hello", "world", 1, 2, 3, false, true)
 */

/**
 * Annotation with named parameters
 *
 * @SomeAnnotation(first="hello", second="world", third=1)
 * @SomeAnnotation(first: "hello", second: "world", third: 1)
 */

/**
 * Passing an array
 *
 * @SomeAnnotation([1, 2, 3, 4])
 * @SomeAnnotation({1, 2, 3, 4})
 */

/**
 * Passing a hash as parameter
 *
 * @SomeAnnotation({first=1, second=2, third=3})
 * @SomeAnnotation({'first'=1, 'second'=2, 'third'=3})
 * @SomeAnnotation({'first': 1, 'second': 2, 'third': 3})
 * @SomeAnnotation(['first': 1, 'second': 2, 'third': 3])
 */

/**
 * Nested arrays/hashes
 *
 * @SomeAnnotation({"name"="SomeName", "other"={
 *      "foo1": "bar1", "foo2": "bar2", {1, 2, 3},
 * }})
 */

/**
 * Nested Annotations
 *
 * @SomeAnnotation(first=@AnotherAnnotation(1, 2, 3))
 */

Penggunaan Praktis 

Selanjutnya kita akan menjelaskan beberapa contoh praktis dari anotasi dalam aplikasi PHP:

Cache Enabler dengan Anotasi 

Misalkan kita sudah controller berikut dan developer ingin membuat sebuah plugin yang secara otomatis memulai cache jika action terakhir yg dieksekusi ditandai sebagai dapat di cache. Pertama-tama kita registrasi plugin dalam Dispatcher  service agar memberitahu ketika suatu rute dieksekusi:

<?php

$di['dispatcher'] = function() {

    $eventsManager = new \Phalcon\Events\Manager();

    //Attach the plugin to 'dispatch' events
    $eventsManager->attach('dispatch', new CacheEnablerPlugin());

    $dispatcher = new \Phalcon\Mvc\Dispatcher();
    $dispatcher->setEventsManager($eventsManager);
    return $dispatcher;
};

CacheEnablerPlugin adalah plugin yang mencegat setiap action yang dieksekusi dalam dispatcher sehingga dapat menghidupkan cache jika diperlukan:

<?php

/**
 * Enables the cache for a view if the latest
 * executed action has the annotation @Cache
 */
class CacheEnablerPlugin extends \Phalcon\Mvc\User\Plugin
{

    /**
     * This event is executed before every route is executed in the dispatcher
     *
     */
    public function beforeExecuteRoute($event, $dispatcher)
    {

        //Parse the annotations in the method currently executed
        $annotations = $this->annotations->getMethod(
            $dispatcher->getActiveController(),
            $dispatcher->getActiveMethod()
        );

        //Check if the method has an annotation 'Cache'
        if ($annotations->has('Cache')) {

            //The method has the annotation 'Cache'
            $annotation = $annotations->get('Cache');

            //Get the lifetime
            $lifetime = $annotation->getNamedParameter('lifetime');

            $options = array('lifetime' => $lifetime);

            //Check if there is an user defined cache key
            if ($annotation->hasNamedParameter('key')) {
                $options['key'] = $annotation->getNamedParameter('key');
            }

            //Enable the cache for the current method
            $this->view->cache($options);
        }

    }

}

Sekarang, kita dapat menggunakan anotasi dalam controller:

<?php

class NewsController extends \Phalcon\Mvc\Controller
{

    public function indexAction()
    {

    }

    /**
     * This is a comment
     *
     * @Cache(lifetime=86400)
     */
    public function showAllAction()
    {
        $this->view->article = Articles::find();
    }

    /**
     * This is a comment
     *
     * @Cache(key="my-key", lifetime=86400)
     */
    public function showAction($slug)
    {
        $this->view->article = Articles::findFirstByTitle($slug);
    }

}

Pilih template untuk render 

Dalam contoh ini kita akan menggunakan anotasi untuk memberitahu Phalcon \ MVC \ View \ Simple template apa yang harus saya diberikan setelah action tereksekusi:

Adapter Anotasi 

Komponen ini memanfaatkan adapter untuk cache atau tanpa-cache proses & olahan anotasi sehingga meningkatkan kinerja atau menyediakan fasilitas untuk development / testing:

Nama Deskripsi API
Memory anotasi cache hanya disimpan dalam memori. Ketika request berakhir, cache dibersihkan. reload anotasi dalam setiap request. Adaptor ini cocok untuk tahap development. Phalcon \ Annotations \ Adapter \ Memory
Files Anotasi yg telah diurai dan diproses disimpan secara permanen dalam file PHP untuk meningkatkan kinerja. Adaptor ini harus digunakan bersama dengan cache bytecode. Phalcon \ Annotations \ Adapter \ Files
APC Anotasi yg telah diurai dan diproses disimpan secara permanen di APC kinerja cache yang membaik. Ini adalah cepat adapter Phalcon \Annotations \ Adapter \ APC
XCache Anotasi yg telah diurai dan diproses disimpan secara permanen di XCache untuk kinerja cache yang baik. Ini adalah salah satu adapter yg cepat Phalcon \Annotations \ Adapter \ xcache

Menerapkan adapter Anda sendiri 

Antarmuka Phalcon \ Annotations \ AdapterInterface  harus diimplementasikan  untuk menciptakan adapter anotasi anda sendiri atau extend yang sudah ada.

Terjemahan dr Annotations Parser Phalcon
http://docs.phalconphp.com/en/latest/reference/annotations.html