Database Phalcon

Phalcon \ Db adalah komponen yg bekerja dibalik Phalcon \ MVC \ Model yang menjadi kekuatan layer model dalam framework. Komponen ini terdiri dari lapisan/layer   abstraksi tingkat tinggi independen untuk sistem database yg sepenuhnya ditulis dalam bahasa C.

Komponen ini menawarkan manipulasi database yg lebih mendalam dibanding dgn komponen model tradisional.

Panduan ini tidak dimaksudkan untuk menjadi sebuah dokumentasi lengkap tentang metode yang tersedia serta argumennya. Silakan kunjungi API untuk referensi yang lengkap.

Adapter Database 

Komponen ini memanfaatkan adapter untuk mengenkapsulasi rincian sistem database yg lebih spesifik. Phalcon menggunakan PDO untuk koneksi ke database. Mesin database berikut ini yg didukung oleh Phalcon:

Nama Deskripsi API
MySQL Adalah yang paling banyak digunakan sbg sistem manajemen database relasional (RDBMS) yang berjalan sebagai server menyediakan akses multi-user ke sejumlah database Phalcon \ Db \ Adapter \ PDO \ Mysql
PostgreSQL PostgreSQL adalah sistem database relasional yg kuat & open source. Berpengalaman lebih dari 15 tahun development aktif dan arsitektur yg teruji telah memberikannya reputasi yang kuat dalam keandalan, integritas data, dan kebenaran. Phalcon \ Db \ Adapter \ PDO \ Postgresql
SQLite SQLite adalah library perangkat lunak yang mengimplementasikan, serverless, tanpa-konfigurasi, mesin database SQL transaksional yg mandiri Phalcon \ Db \ Adapter \ PDO \ Sqlite
Oracle Oracle adalah sebuah sistem manajemen database object-relational yang diproduksi dan dipasarkan oleh Oracle Corporation. Phalcon \ Db \ Adapter \ PDO \ Oracle

Menerapkan adapter Anda sendiri 

Antarmuka Phalcon \ Db \ AdapterInterface  harus diimplementasikan untuk menciptakan adapter database Anda sendiri atau extend yang sudah ada.

Dialek database 

Phalcon mengenkapsulasi rincian spesifik dari masing-masing mesin database sebagai  “Dialect”. Kemudian menyediakan fungsi umum (sama) dan SQL generator untuk adaptor.

Nama Deskripsi API
MySQL SQL dialek khusus untuk sistem database MySQL Phalcon \ Db \ Dialect \ Mysql
PostgreSQL SQL dialek khusus untuk sistem database PostgreSQL Phalcon \ Db \ Dialect \ Postgresql
SQLite SQL dialek khusus untuk sistem database SQLite Phalcon \ Db \ Dialect \ Sqlite
Oracle SQL dialek khusus untuk sistem database Oracle Phalcon \ Db \ Dialect \ Oracle

Menerapkan Dialect Anda sendiri 

Antarmuka Phalcon \ Db \ DialectInterface  harus diimplementasikan untuk menciptakan dialek database Anda sendiri atau extend yang sudah ada. 

Koneksi ke Database 

Untuk membuat koneksi yg diperlukan adalah embuat instance dr class adapter database. Proses ini hanya membutuhkan sebuah array dengan parameter koneksi. Contoh di bawah ini menunjukkan bagaimana untuk membuat koneksi sesuai dgn parameter yang diberikan, serta parameter opsional yg tersedia:

<?php

// Required
$config = array(
    "host" => "127.0.0.1",
    "username" => "mike",
    "password" => "sigma",
    "dbname" => "test_db"
);

// Optional
$config["persistent"] = false;

// Create a connection
$connection = new \Phalcon\Db\Adapter\Pdo\Mysql($config);

<?php

// Required
$config = array(
    "host" => "localhost",
    "username" => "postgres",
    "password" => "secret1",
    "dbname" => "template"
);

// Optional
$config["schema"] = "public";

// Create a connection
$connection = new \Phalcon\Db\Adapter\Pdo\Postgresql($config);
<?php

// Required
$config = array(
    "dbname" => "/path/to/database.db"
);

// Create a connection
$connection = new \Phalcon\Db\Adapter\Pdo\Sqlite($config);
<?php

// Basic configuration
$config = array(
    'username' => 'scott',
    'password' => 'tiger',
    'dbname' => '192.168.10.145/orcl',
);

// Advanced configuration
$config = array(
    'dbname' => '(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=xe)(FAILOVER_MODE=(TYPE=SELECT)(METHOD=BASIC)(RETRIES=20)(DELAY=5))))',
    'username' => 'scott',
    'password' => 'tiger',
    'charset' => 'AL32UTF8',
);

// Create a connection
$connection = new \Phalcon\Db\Adapter\Pdo\Oracle($config);

Seting Tambahan Opsi PDO 

Anda dapat mengatur opsi PDO koneksi dgn memberikan parameter ‘option’:

<?php

// Create a connection with PDO options
$connection = new \Phalcon\Db\Adapter\Pdo\Mysql(array(
    "host" => "localhost",
    "username" => "root",
    "password" => "sigma",
    "dbname" => "test_db",
    "options" => array(
        PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES \'UTF8\'",
        PDO::ATTR_CASE => PDO::CASE_LOWER
    )
));

Menemukan Baris Data 

Phalcon \ Db menyediakan beberapa metode untuk query dari tabel. Sintaks SQL harus sesuai spesifikasi mesin database target dalam kasus ini:

<?php

$sql = "SELECT id, name FROM robots ORDER BY name";

// Send a SQL statement to the database system
$result = $connection->query($sql);

// Print each robot name
while ($robot = $result->fetch()) {
   echo $robot["name"];
}

// Get all rows in an array
$robots = $connection->fetchAll($sql);
foreach ($robots as $robot) {
   echo $robot["name"];
}

// Get only the first row
$robot = $connection->fetchOne($sql);

Secara default bentuk data yg diambil berupa array dengan indeks ganda, baik asosiatif dan numerik. Anda dapat mengubah perilaku/behavior ini dengan menggunakan Phalcon\Db\Result::setFetchMode(). Metode ini menerima konstanta, mendefinisikan yang jenis indeks yg diinginkan.

Konstan Deskripsi
Phalcon\Db::FETCH_NUM Mengembalikan array dengan indeks numerik
Phalcon\Db::FETCH_ASSOC Mengembalikan array dengan indeks asosiatif
Phalcon\Db::FETCH_BOTH Mengembalikan array dengan indeks baik asosiatif dan numerik
Phalcon\Db::ETCH_OBJ Kembali objek bukannya array
<?php

$sql = "SELECT id, name FROM robots ORDER BY name";
$result = $connection->query($sql);

$result->setFetchMode(Phalcon\Db::FETCH_NUM);
while ($robot = $result->fetch()) {
   echo $robot[0];
}

Method Phalcon\Db::query() mengembalikan sebuah instance dari Phalcon \ Db \ Result \ PDO . Objek ini merangkum semua fungsi untuk mengakses resultset yaitu menelusuri, mencari baris tertentu, menghitung dll

<?php

$sql = "SELECT id, name FROM robots";
$result = $connection->query($sql);

// Traverse the resultset
while ($robot = $result->fetch()) {
   echo $robot["name"];
}

// Seek to the third row
$result->seek(2);
$robot = $result->fetch();

// Count the resultset
echo $result->numRows();

Binding Parameter 

Binding Parameter juga disediakan di Phalcon \ Db . Meskipun ada sedikit dampak kinerja dengan menggunakan bind parameter, Anda dianjurkan untuk menggunakan metodologi ini sehingga dapat mengurangi kemungkinan kode Anda menjadi sasaran serangan injeksi SQL. Baik placeholder string atau urutan posisi diperbolehkan.  Parameter Binding dapat digunakan dgn cara berikut:

<?php

// Binding with numeric placeholders
$sql    = "SELECT * FROM robots WHERE name = ? ORDER BY name";
$result = $connection->query($sql, array("Wall-E"));

// Binding with named placeholders
$sql     = "INSERT INTO `robots`(name`, year) VALUES (:name, :year)";
$success = $connection->query($sql, array("name" => "Astro Boy", "year" => 1952));

Insert/Update/Delete Baris 

Untuk menyisipkan, update atau menghapus baris, Anda dapat menggunakan SQL murni (bukan PHQL) atau menggunakan fungsi yang telah disediakan:

<?php

// Inserting data with a raw SQL statement
$sql     = "INSERT INTO `robots`(`name`, `year`) VALUES ('Astro Boy', 1952)";
$success = $connection->execute($sql);

//With placeholders
$sql     = "INSERT INTO `robots`(`name`, `year`) VALUES (?, ?)";
$success = $connection->execute($sql, array('Astro Boy', 1952));

// Generating dynamically the necessary SQL
$success = $connection->insert(
   "robots",
   array("Astro Boy", 1952),
   array("name", "year")
);

// Updating data with a raw SQL statement
$sql     = "UPDATE `robots` SET `name` = 'Astro boy' WHERE `id` = 101";
$success = $connection->execute($sql);

//With placeholders
$sql     = "UPDATE `robots` SET `name` = ? WHERE `id` = ?";
$success = $connection->execute($sql, array('Astro Boy', 101));

// Generating dynamically the necessary SQL
$success = $connection->update(
   "robots",
   array("name"),
   array("New Astro Boy"),
   "id = 101"
);

// Deleting data with a raw SQL statement
$sql     = "DELETE `robots` WHERE `id` = 101";
$success = $connection->execute($sql);

//With placeholders
$sql     = "DELETE `robots` WHERE `id` = ?";
$success = $connection->execute($sql, array(101));

// Generating dynamically the necessary SQL
$success = $connection->delete("robots", "id = 101");

Transaksi dan Transaksi Bersarang 

Transaksi didukung sebagaimana menggunakan PDO. Melakukan manipulasi data dalam transaksi sering meningkatkan kinerja pada kebanyakan sistem database:

<?php

try {

    //Start a transaction
    $connection->begin();

    //Execute some SQL statements
    $connection->execute("DELETE `robots` WHERE `id` = 101");
    $connection->execute("DELETE `robots` WHERE `id` = 102");
    $connection->execute("DELETE `robots` WHERE `id` = 103");

    //Commit if everything goes well
    $connection->commit();

} catch(Exception $e) {
    //An exception has occurred rollback the transaction
    $connection->rollback();
}

Selain transaksi standar, Phalcon\Db menyediakan dukungan built-in untuk transaksi bersarang (jika sistem database yang digunakan jg mendukung). Ketika Anda memanggil begin() untuk kedua kalinya, transaksi bersarang dijalankan:

<?php

try {

    //Start a transaction
    $connection->begin();

    //Execute some SQL statements
    $connection->execute("DELETE `robots` WHERE `id` = 101");

    try {

        //Start a nested transaction
        $connection->begin();

        //Execute these SQL statements into the nested transaction
        $connection->execute("DELETE `robots` WHERE `id` = 102");
        $connection->execute("DELETE `robots` WHERE `id` = 103");

        //Create a save point
        $connection->commit();

    } catch(Exception $e) {
        //An error has occurred, release the nested transaction
        $connection->rollback();
    }

    //Continue, executing more SQL statements
    $connection->execute("DELETE `robots` WHERE `id` = 104");

    //Commit if everything goes well
    $connection->commit();

} catch(Exception $e) {
    //An exception has occurred rollback the transaction
    $connection->rollback();
}

Event Database 

Phalcon \ Db mampu mengirim event ke EventsManager jika ada. Beberapa event ketika mengembalikan boolean FALSE bisa menghentikan operasi yg sedang aktif.  Event berikut ini didukung:

Nama Acara Dipicu Bisa menghentikan operasi?
afterConnect Setelah berhasil koneksi ke sistem database Tidak
beforeQuery Sebelum mengirimkan pernyataan SQL ke sistem database Ya
afterQuery Setelah mengirimkan pernyataan SQL ke sistem database Tidak
beforeDisconnect Sebelum menutup koneksi database sementara Tidak
beginTransaction Sebelum transaksi ini akan dimulai Tidak
rollbackTransaction Sebelum transaksi ini rollbacked Tidak
commitTransaction Sebelum transaksi berkomitmen | No

Mengikatkan sebuah EventsManager untuk koneksi itu mudah, Phalcon\Db akan memicu event dengan tipe “db”:

<?php

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

$eventsManager = new EventsManager();

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

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

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

Memberhentikan operasi SQL sangat berguna jika misalnya Anda ingin menerapkan  last-resource SQL injector checker:

<?php

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

    //Check for malicious words in SQL statements
    if (preg_match('/DROP|ALTER/i', $connection->getSQLStatement())) {
        // DROP/ALTER operations aren't allowed in the application,
        // this must be a SQL injection!
        return false;
    }

    //It's ok
    return true;
});

Profiling Statement SQL 

Phalcon \ Db mencakup komponen yang disebut Phalcon \ Db \ Profiler , yang digunakan untuk menganalisis kinerja operasi database sehingga dapat mendiagnosa masalah kinerja dan menemukan kemacetan.

Database profiling sangat mudah Dengan Phalcon \ Db \ Profiler :

<?php

use Phalcon\Events\Manager as EventsManager,
    Phalcon\Db\Profiler as DbProfiler;

$eventsManager = new EventsManager();

$profiler = new DbProfiler();

//Listen all the database events
$eventsManager->attach('db', function($event, $connection) use ($profiler) {
    if ($event->getType() == 'beforeQuery') {
        //Start a profile with the active connection
        $profiler->startProfile($connection->getSQLStatement());
    }
    if ($event->getType() == 'afterQuery') {
        //Stop the active profile
        $profiler->stopProfile();
    }
});

//Assign the events manager to the connection
$connection->setEventsManager($eventsManager);

$sql = "SELECT buyer_name, quantity, product_name "
     . "FROM buyers "
     . "LEFT JOIN products ON buyers.pid = products.id";

// Execute a SQL statement
$connection->query($sql);

// Get the last profile in the profiler
$profile = $profiler->getLastProfile();

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

Anda juga dapat membuat Anda profiler class sendiri berdasarkan Phalcon \ Db \ Profiler untuk mencatat statistik real time dari statement dikirim ke sistem database:

<?php

use Phalcon\Events\Manager as EventsManager,
    Phalcon\Db\Profiler as Profiler,
    Phalcon\Db\Profiler\Item as Item;

class DbProfiler extends Profiler
{

    /**
     * Executed before the SQL statement will sent to the db server
     */
    public function beforeStartProfile(Item $profile)
    {
        echo $profile->getSQLStatement();
    }

    /**
     * Executed after the SQL statement was sent to the db server
     */
    public function afterEndProfile(Item $profile)
    {
        echo $profile->getTotalElapsedSeconds();
    }

}

//Create an EventsManager
$eventsManager = new EventsManager();

//Create a listener
$dbProfiler = new DbProfiler();

//Attach the listener listening for all database events
$eventsManager->attach('db', $dbProfiler);

Log Statement SQL 

Menggunakan komponen abstraksi tingkat tinggi seperti Phalcon \ Db untuk koneksi database, menyulitkan untuk memahami statement yang dikirim ke sistem database. Phalcon \ Logger berinteraksi dengan Phalcon \ Db , menyediakan kemampuan logging pada lapisan abstraksi database.

<?php

use Phalcon\Logger,
    Phalcon\Events\Manager as EventsManager,
    Phalcon\Logger\Adapter\File as FileLogger;

$eventsManager = new EventsManager();

$logger = new FileLogger("app/logs/db.log");

//Listen all the database events
$eventsManager->attach('db', function($event, $connection) use ($logger) {
    if ($event->getType() == 'beforeQuery') {
        $logger->log($connection->getSQLStatement(), Logger::INFO);
    }
});

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

//Execute some SQL statement
$connection->insert(
    "products",
    array("Hot pepper", 3.50),
    array("name", "price")
);

Seperti di atas, aplikasi / file log / db.log akan berisi sesuatu seperti ini:

[Sun, 29 Apr 12 22:35:26 -0500][DEBUG][Resource Id #77] INSERT INTO products
(name, price) VALUES ('Hot pepper', 3.50)

Menerapkan Logger Anda sendiri 

Anda dapat menerapkan class logger Anda sendiri untuk query database, dengan menciptakan sebuah kelas yang mengimplementasikan metode tunggal yang disebut “log”. Metode ini (harus) menerima string sebagai argumen pertama. Anda kemudian dapat memberikan objek logging Anda ke Phalcon\Db::setLogger(), dan sejak saat itu pada setiap pernyataan SQL dieksekusi akan memanggil metode tersebut untuk di-log.

Perincian Tables / Views 

Phalcon \ Db juga menyediakan metode untuk mengambil informasi rinci tentang tabel dan view:

<?php

// Get tables on the test_db database
$tables = $connection->listTables("test_db");

// Is there a table 'robots' in the database?
$exists = $connection->tableExists("robots");

// Get name, data types and special features of 'robots' fields
$fields = $connection->describeColumns("robots");
foreach ($fields as $field) {
    echo "Column Type: ", $field["Type"];
}

// Get indexes on the 'robots' table
$indexes = $connection->describeIndexes("robots");
foreach ($indexes as $index) {
    print_r($index->getColumns());
}

// Get foreign keys on the 'robots' table
$references = $connection->describeReferences("robots");
foreach ($references as $reference) {
    // Print referenced columns
    print_r($reference->getReferencedColumns());
}

Penjelasan tabel sangat mirip dengan  perintah MySQL describe, berisi informasi berikut:

Indeks Deskripsi
Field Nama Field
Type Kolom Type
Key Adalah kolom bagian dari primary key atau indeks?
Null Apakah kolom memungkinkan nilai null?

Metode untuk mendapatkan informasi tentang view juga diterapkan untuk setiap sistem database yang didukung:

<?php

// Get views on the test_db database
$tables = $connection->listViews("test_db");

// Is there a view 'robots' in the database?
$exists = $connection->viewExists("robots");

Create/Alter/Drop Tabel 

Sistem database yang berbeda (MySQL, PostgreSQL dll) menawarkan kemampuan untuk membuat, mengubah atau menghapus tabel dengan menggunakan perintah seperti CREATE, ALTER atau DROP. Namun sintaks SQL untuk perintah tersebut berbeda sesuai sistem database yang digunakan. Phalcon \ Db menawarkan antarmuka yang seragam untuk mengubah tabel, tanpa perlu membedakan sintaks SQL berdasarkan sistem penyimpanan target.

Membuat Tabel 

Contoh berikut ini menunjukkan bagaimana untuk membuat tabel:

<?php

use \Phalcon\Db\Column as Column;

$connection->createTable(
    "robots",
    null,
    array(
       "columns" => array(
            new Column("id",
                array(
                    "type"          => Column::TYPE_INTEGER,
                    "size"          => 10,
                    "notNull"       => true,
                    "autoIncrement" => true,
                )
            ),
            new Column("name",
                array(
                    "type"    => Column::TYPE_VARCHAR,
                    "size"    => 70,
                    "notNull" => true,
                )
            ),
            new Column("year",
                array(
                    "type"    => Column::TYPE_INTEGER,
                    "size"    => 11,
                    "notNull" => true,
                )
            )
        )
    )
);

Phalcon \ Db :: createTable () menerima sebuah array asosiatif yg menggambarkan tabel. Kolom didefinisikan dengan class Phalcon \ Db \ Column . Tabel di bawah ini menunjukkan pilihan yang tersedia untuk mendefinisikan kolom:

Pilihan Deskripsi Opsional
“Type” Jenis kolom. Harus Kolom konstan Phalcon \ Db \ (lihat di bawah untuk daftar) Tidak
“Primary” Benar jika kolom merupakan bagian dari primary tabel Ya
“Size” Beberapa jenis kolom seperti VARCHAR atau INTEGER mungkin memiliki ukuran tertentu Ya
“scale” Kolom DECIMAL atau NUMBER mungkin memiliki skala untuk menentukan berapa banyak desimal harus disimpan Ya
“Unsigned” Kolom INTEGER dapat signed atau unsigned. Opsi ini tidak berlaku untuk jenis kolom lain Ya
“NotNull” Kolom dapat menyimpan nilai null? Ya
“Autoincrement” Dengan kolom atribut ini akan diisi secara otomatis dengan auto-increment integer. Hanya satu kolom dalam tabel dapat memiliki atribut ini. Ya
“bind” Salah satu yang BIND_TYPE_ * konstanta menceritakan bagaimana kolom harus diikat sebelum menyimpannya Ya
“first” Kolom harus ditempatkan pada posisi pertama dalam urutan kolom Ya
“after” Kolom harus ditempatkan setelah kolom yang ditunjukkan Ya

Phalcon \ Db mendukung jenis kolom database berikut:

  • Phalcon \ Db \ Kolom :: TYPE_INTEGER
  • Phalcon \ Db \ Kolom :: TYPE_DATE
  • Phalcon \ Db \ Kolom :: TYPE_VARCHAR
  • Phalcon \ Db \ Kolom :: TYPE_DECIMAL
  • Phalcon \ Db \ Kolom :: TYPE_DATETIME
  • Phalcon \ Db \ Kolom :: TYPE_CHAR
  • Phalcon \ Db \ Kolom :: TYPE_TEXT

Array asosiatif yg diberikan ke Phalcon \ Db :: createTable () dapat memiliki key berikut sebagai opsi tambahan:

Indeks Deskripsi Opsional
“columns” Sebuah array dengan satu set kolom tabel didefinisikan dengan Phalcon \ Db \ Column Tidak
“Indexes” Sebuah array dengan satu set indeks tabel didefinisikan dengan Phalcon \ Db \ Indexes Ya
“references” Sebuah array dengan satu set referensi tabel (kunci asing) didefinisikan dengan Phalcon \ Db \ Reference Ya
“options” Sebuah array dengan satu set pilihan pembuatan tabel. Pilihan ini sering berhubungan dengan sistem database di mana migrasi itu dihasilkan. Ya

Mengubah Tabel 

Sebagaimana aplikasi Anda tumbuh, Anda mungkin perlu untuk mengubah database Anda, sebagai bagian dari refactoring atau menambahkan fitur baru. Tidak semua sistem database memungkinkan untuk memodifikasi kolom yang ada atau menambahkan kolom diantara yang sudah ada. Phalcon \ Db dibatasi oleh keterbatasan sistem database tersebut.

<?php

use Phalcon\Db\Column as Column;

// Adding a new column
$connection->addColumn("robots", null,
    new Column("robot_type", array(
        "type"    => Column::TYPE_VARCHAR,
        "size"    => 32,
        "notNull" => true,
        "after"   => "name"
    ))
);

// Modifying an existing column
$connection->modifyColumn("robots", null, new Column("name", array(
    "type" => Column::TYPE_VARCHAR,
    "size" => 40,
    "notNull" => true,
)));

// Deleting the column "name"
$connection->deleteColumn("robots", null, "name");

Menghapus Tabel 

Contoh untuk menghapus tabel:

<?php

// Drop table robot from active database
$connection->dropTable("robots");

//Drop table robot from database "machines"
$connection->dropTable("robots", "machines");