Advertisement
  1. Code
  2. PHP
  3. CodeIgniter

Membuat Aplikasi Web CodeIgniter Dari Awal

Scroll to top
Read Time: 16 min

() translation by (you can also view the original English article)

Aplikasi yang kita buat akan menjadi papan iklan sederhana, di mana pengguna dapat mendaftar, mengirim tugas, dan menawarkan hadiah untuk penyelesaiannya. Pengguna lain dapat melihat tugas yang ada, menetapkan tugas untuk dirinya sendiri, dan mendapatkan hadiah yang ditawarkan.

Tugas akan memiliki data dasar seperti judul, deskripsi, dan hadiah (sebagai parameter yang diperlukan) dan tanggal serta catatan akhir opsional. Profil pengguna hanya akan terdiri dari nama pengguna, email, dan situs web. Ayo mulai!


Pengaturan Database

Pertama, untuk data aplikasi kita akan menggunakan MongoDB sebagai server database. MongoDB adalah database berorientasi dokumen dan database NoSQL terkemuka di luar sana. Ini benar-benar terukur dan cepat, yang membuatnya hebat untuk mengelola data dalam jumlah besar.

MongoDB adalah database berorientasi dokumen dan database NoSQL terkemuka.

Untuk menggunakan MongoDB dalam aplikasi ini, saya akan menggunakan driver MongoDB CodeIgniter yang saya tulis beberapa waktu lalu, itu hanya pembungkus driver PHP MongoDB untuk meniru kerangka SQL ActiveRecord. Anda dapat menemukan file sumber untuk driver ini di repositori publik saya. Agar driver ini berfungsi dengan baik, pastikan Anda menginstal driver PHP MongoDB, jika tidak, ikuti langkah-langkah ini untuk membuatnya bekerja.

Harap dicatat bahwa menjelaskan driver di CodeIgniter dan itu di luar lingkup tutorial ini, lihat dokumentasi jika Anda memiliki keraguan. Anda hanya perlu memindahkan "mongo_db.php" di folder "config" ke folder "config" pada aplikasi Anda dan folder "Mongo_db" di folder "libraries" ke folder "libraries" di aplikasi Anda.

Konfigurasi Database

Satu-satunya file yang perlu kita edit pada titik ini adalah "mongo_db.php" file di bawah folder "config", karena instalasi mongo saya memiliki semua parameter default, saya hanya akan mengedit baris 40 dan memberikannya nama database yang ingin saya gunakan:

1
$config['mongo_db'] = 'billboard';

Itu saja untuk database, salah satu dari banyak keuntungan MongoDB adalah bahwa dokumen tidak memiliki struktur standar, sehingga bekerja tanpa kita perlu mengatur apa pun sebelum digunakan, databasenya tidak harus ada, MongoDB akan membuatnya dengan cepat ketika kita membutuhkannya.


Konfigurasi Global

Selain opsi konfigurasi reguler Anda, yang harus menyertakan base_url dan index_page jika ada, kita perlu mengatur string dan tanggal bantuan untuk autoload. Saya tidak akan memandu Anda melalui ini, karena kita memiliki lebih banyak untuk menutupi, ketika ragu mengacu pada dokumentasi.

Selain para pembantu, kita perlu mengatur kelas enkripsi karena kita akan menggunakannya untuk aplikasi kita.


Penanganan URL

Ini akan menjadi layanan RESTful dan kita membutuhkan cara untuk mengambil permintaan yang datang ke server dan menanganinya sesuai dengan itu. Kita bisa menggunakan pustaka yang ada (yang sangat bagus) tetapi untuk tujuan demonstrasi ini, saya akan membuat fungsionalitas yang saya perlukan menggunakan fitur inti CodeIgniter.

Penanganan Permintaan RESTful

Secara khusus, kita akan menggunakan kemampuan untuk memperluas kelas inti. Kita akan mulai dengan Controller, untuk bagian utama dari ekstensi ini menggunakan metode "_remap" di pengendali dasar sehingga semua pengontrol aplikasi dapat menggunakannya. Mulailah dengan membuat file MY_Controller.php di dalam folder "core" di folder "application", kita buat ini seperti pengendali CodeIgniter lainnya, sebagai berikut:

1
<?php
2
if( !defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' );
3
4
class MY_Controller extends CI_Controller {
5
6
}

Sekarang di pengontrol ini kita akan menggunakan metode CodeIgniter _remap untuk memroses setiap permintaan yang dibuat ke server. Di dalam kelas yang baru kita buat, tambahkan metode berikut:

1
public function _remap( $param ) {
2
    $request = $_SERVER['REQUEST_METHOD'];
3
4
    switch( strtoupper( $request ) ) {
5
        case 'GET':
6
            $method = 'read';
7
            break;
8
        case 'POST':
9
            $method = 'save';
10
            break;
11
        case 'PUT':
12
            $method = 'update';
13
            break;
14
        case 'DELETE':
15
            $method = 'remove';
16
            break;
17
        case 'OPTIONS':
18
            $method = '_options';
19
            break;
20
    }
21
22
    $this->$method( $id );
23
}

Beberapa hal yang perlu diperhatikan di sini, pertama, ada beberapa kata kerja REST yang kami abaikan (seperti PATCH), karena saya mendemonstrasikan pembuatan aplikasi REST, saya tidak ingin menambahkan hal-hal yang dapat membuat ini lebih rumit daripada itu perlu. Kedua, kita tidak mempertimbangkan kasus di mana pengontrol tidak menerapkan metode tertentu, yang sangat mungkin bahwa ini bisa terjadi. Sekarang, kita bisa menambahkan metode default untuk menangani permintaan semacam itu, tetapi agar kita tidak menambahkan terlalu banyak kerumitan, mari kita biarkan seperti ini. Ketiga, kita menerima variabel param dalam deklarasi metode, mari kita alamat itu, dan kemudian saya akan menjelaskan permintaan OPTIONS. Di atas pernyataan switch, tambahkan kode berikut:

1
if ( preg_match( "/^(?=.*[a-zA-Z])(?=.*[0-9])/", $param ) ) {
2
    $id = $param;
3
} else {
4
    $id = null;
5
}

Ekspresi reguler ini cocok dengan string apa pun yang terdiri dari huruf besar dan huruf kecil dan angka apa pun. Ini digunakan untuk memeriksa apakah string MongoDB _id diberikan sebagai parameter, sekali lagi, ini bukan cara paling aman atau pemeriksaan yang paling menyeluruh, tetapi demi kesederhanaan, kita akan tetap seperti itu.

OPSI Permintaan

Karena kita sedang membangun layanan web dan aplikasi klien sebagai bagian yang terpisah, masuk akal bahwa keduanya akan di-host di domain yang berbeda, jadi akan memungkinkan CORS di back-end dan ini berarti, antara lain, bahwa aplikasi akan merespons dengan benar atas permintaan OPTIONS.

Ketika sebuah aplikasi web dibuat dengan BackboneJS (dan beberapa kerangka lain) mencoba untuk membuat permintaan asynchronous ke server jauh, ia mengirimkan permintaan OPTIONS sebelum mengirim permintaan sebenarnya yang seharusnya dikirim. Antara lain, klien memberi tahu server dari mana ia mengirim permintaan, jenis permintaan apa yang akan dikirimkan, dan konten yang diharapkannya. Setelah itu, terserah kepada server untuk mengirim klien tanggapan di mana ia mengakui permintaan atau menolaknya.

Karena layanan back-end, terlepas dari pengontrol apa yang dipanggil, akan menerima permintaan OPTIONS ini, masuk akal untuk menerapkan metode untuk meresponsnya di pengendali basis kita. Tambahkan metode berikut di bawah (atau di atas) metode _remap di controller.

1
private function _options() {
2
    $this->output->set_header( 'Access-Control-Allow-Origin: *' );
3
    $this->output->set_header( "Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS" );
4
    $this->output->set_header( 'Access-Control-Allow-Headers: content-type' );
5
    $this->output->set_content_type( 'application/json' );
6
    $this->output->set_output( "*" );
7
}

Idealnya, hanya mengizinkan beberapa domain untuk membuat permintaan kepada kita, yang akan diperiksa header request_headers untuk melihat apakah kita menerimanya dan akan memeriksa jenis konten yang diharapkan, oleh klien untuk melihat apakah kita mendukungnya, tetapi sekali lagi, ini adalah aplikasi yang tidak begitu rumit dan kita melewatkan kasus tepi ini.


Mengelola Output

Untuk menyelesaikan pengendali dasar, mari buat metode yang akan digunakan setiap pengontrol untuk mengirim hasilnya kembali ke klien. Di kelas pengendali dasar, tambahkan metode berikut:

1
protected function _format_output( $output = null ) {
2
    $this->output->set_header( 'Access-Control-Allow-Origin: *' );
3
4
    if( isset( $output->status ) && $output->status == 'error' ) {
5
        $this->output->set_status_header( 409, $output->desc );
6
    }
7
    $this->_parse_data( $output );
8
9
    $this->output->set_content_type( 'application/json' );
10
    $this->output->set_output( json_encode( $output ) );
11
}

Sekali lagi, agar BackboneJS memproses respons server, harus mengetahui bahwa host-nya diterima oleh server, maka header Allow-Origin, kemudian, jika hasilnya salah, kita menetapkan header status yang menunjukkan ini. Status ini akan menjadi lebih jelas ketika kita membuat model back-end. Selanjutnya kita menggunakan helper parse_data, yang akan menjadi metode pribadi (yang akan kita tulis sebentar) tetapi biarkan saya melewati itu untuk sementara waktu, kemudian kita mengatur tipe konten sebagai JSON dan akhirnya kita menyandikan respon sebagai objek JSON . Sekali lagi, di sini kita dapat (dan seharusnya) mendukung format output lain (seperti XML).

Sekarang mari kita buat metode helper parse_data (dan saya akan menjelaskannya setelah itu), tambahkan kode berikut ke pengendali dasar:

1
private function _parse_data( &$data ) {
2
    if ( ! is_array( $data ) && ! is_object( $data ) )
3
        return $data;
4
5
    foreach ( $data as $key => $value ) {
6
        if ( is_object( $value ) || is_array( $value ) ) {
7
            if( is_object( $data ) ) {
8
                $data->{$key} = $this->_parse_data( $value );
9
            } else {
10
                $data[ $key ] = $this->_parse_data( $value );
11
            }
12
        }
13
14
        if ( isset( $value->sec ) ) {
15
            if( is_object( $data ) ) {
16
                $data->{$key} = date( 'd.m.Y', $value->sec );
17
            } else {
18
                $data[ $key ] = date( 'd.m.Y', $value->sec );
19
            }
20
        }
21
22
        if ( is_object( $value ) && isset( $value->{'$id'} ) ) {
23
            if( is_object( $data ) ) {
24
                $data->{$key} = $value->__toString();
25
            } else {
26
                $data[ $key ] = $value->__toString();
27
            }
28
        }
29
    }
30
31
    return $data;
32
}

Pertama, perhatikan bahwa kita hanya mem-parsing data untuk array dan objek, dan kita melakukannya secara rekursif. Penguraian awal ini berkaitan dengan fakta bahwa MongoDB menggunakan tanggal dan ID sebagai objek, tetapi klien kita tidak memerlukan informasi ini. Sekarang untuk kasus ID, kita hanya butuh nilai stringnya, maka panggilan metode toString, maka nilainya memiliki properti '$id'. Setelah itu kita mengubah tanggal menjadi format days.month.year, ini dilakukan untuk kenyamanan dalam desain aplikasi klien, sekali lagi, bukan pendekatan yang paling fleksibel tetapi berfungsi untuk contoh ini.


Penanganan Input

Karena kita mengirim JSON kembali ke aplikasi klien, itu hanya logis bahwa menerima data dalam format JSON juga. CodeIgniter tidak mendukung ini secara default seperti Laravel, faktanya, CodeIgniter bahkan tidak mendukung put dan delete params. Hal ini terutama karena kerangka kerja tidak dimaksudkan untuk layanan RESTful, namun upaya yang diperlukan untuk menyesuaikannya sangat minimal dibandingkan dengan manfaatnya, setidaknya dari sudut pandang saya.

Jadi kita akan mulai dengan mendukung data JSON yang dikirim BackboneJS. Buat file baru di dalam folder "core", kali ini akan diberi nama "MY_Input.php" dan itu akan memiliki struktur dasar berikut:

1
<?php
2
if( !defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' );
3
4
class MY_Input extends CI_Input {
5
6
}

Sekarang setiap kali kita menggunakan input $this->input aplikasi kita, kita akan mengacu pada kelas ini, kita akan membuat beberapa metode baru dan mengganti beberapa yang sudah ada. Pertama, kita akan menambahkan dukungan untuk data JSON, tambahkan metode berikut ke kelas baru.

1
public function json() {
2
    if ( !self::$request_params ) {
3
        $payload    = file_get_contents( 'php://input' );
4
5
        if ( is_array( $payload ) ) {
6
            self::$request_params   = $payload;
7
        } else if ( ( substr( $payload, 0, 1 ) == "{" ) && ( substr( $payload, ( strlen( $payload ) - 1 ), 1 ) == "}" ) ) {
8
            self::$request_params   = json_decode( $payload );
9
        } else {
10
            parse_str( $payload, self::$request_params );
11
        }
12
    }
13
14
    return (object) self::$request_params;
15
}

$request_params adalah variabel statis yang digunakan untuk menyimpan string permintaan/data yang dikirim oleh klien. Ini statis untuk menjadikannya objek yang independen sehingga kita dapat mengaksesnya dari pengontrol apa pun pada waktu tertentu. Data diperoleh dari php://input stream daripada $_POST global. Ini dilakukan untuk mendapatkan data yang dikirim melalui PUT dan DELETE permintaan juga. Akhirnya, payload yang diperoleh diperiksa untuk memeriksa apakah itu array, objek JSON dikodekan, atau string kueri, dan itu diproses sesuai. Hasilnya kemudian dikembalikan sebagai objek.

Agar metode ini berfungsi, kita perlu membuat variabel $request_params statis, tambahkan deklarasinya ke bagian atas kelas.

1
private static $request_params  = null;

Menangani Permintaan Reguler

Selanjutnya, kita perlu mengganti metode post dari kelas masukan reguler untuk menggunakan payload JSON baru daripada $_POST global, tambahkan metode berikut ke kelas Masukan baru.

1
public function post( $index = NULL, $xss_clean = FALSE ) {
2
    $request_vars   = ( array ) $this->json();
3
    if ( $index === NULL && !empty( $request_vars ) ) {
4
        $post       = array();
5
        foreach( array_keys( $request_vars ) as $key ) {
6
            $post[$key]  = $this->_fetch_from_array( $request_vars, $key, $xss_clean );
7
        }
8
        return $post;
9
    }
10
    return $this->_fetch_from_array( $request_vars, $index, $xss_clean );
11
}

Ini hampir sama dengan metode post dari kelas CI_Input asli, dengan perbedaan adalah bahwa ia menggunakan metode JSON baru kita daripada $_POST global untuk mengambil data postingan. Sekarang mari kita lakukan hal yang sama untuk metode PUT.

1
public function put( $index = NULL, $xss_clean = FALSE ) {
2
    $request_vars   = ( array ) $this->json();
3
    if ( $index === NULL && !empty( $request_vars ) ) {
4
        $put = array();
5
        foreach( array_keys( $request_vars ) as $key ) {
6
            $put[$key]   = $this->_fetch_from_array( $request_vars, $key, $xss_clean );
7
        }
8
        return $put;
9
    }
10
    return $this->_fetch_from_array( $request_vars, $index, $xss_clean );
11
}

Dan kemudian kita juga membutuhkan metode DELETE:

1
public function delete( $index = NULL, $xss_clean = FALSE ) {
2
    $request_vars   = ( array ) $this->json();
3
    if ( $index === NULL && !empty( $request_vars ) ) {
4
        $delete = array();
5
        foreach( array_keys( $request_vars ) as $key ) {
6
            $delete[$key]   = $this->_fetch_from_array( $request_vars, $key, $xss_clean );
7
        }
8
        return $delete;
9
    }
10
    return $this->_fetch_from_array( $request_vars, $index, $xss_clean );
11
}

Sekarang secara teknis, benar-benar tidak perlu untuk metode tambahan ini, karena metode post dapat menangani params dalam permintaan PUT dan DELETE, tetapi secara semantis itu lebih baik (menurut saya).

Ini yang kita perlukan untuk kelas Input kustom. Sekali lagi kita mengabaikan kasus-kasus tepi di sini, seperti permintaan multi bagian, meskipun itu tidak terlalu sulit untuk menangani itu dan masih mempertahankan fungsi yang diperoleh di sini, tetapi, demi kesederhanaan kita akan tetap seperti itu.


Base Model

Untuk mengakhiri perluasan kelas inti, mari buat model dasar yang akan diterapkan oleh setiap model dalam aplikasi, ini hanya untuk menghindari pengulangan tugas umum untuk setiap model. Seperti ekstensi kelas inti lainnya, inilah model dasar barebone kita:

1
<?php
2
if( !defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' );
3
4
class MY_Model extends CI_Model {
5
6
}

Model dasar ini hanya akan melayani tujuan pengaturan dan mengambil kesalahan. Tambahkan metode berikut untuk menetapkan kesalahan model:

1
protected function _set_error( $desc, $data = null ) {
2
    $this->_error           = new stdClass();
3
    $this->_error->status   = 'error';
4
    $this->_error->desc     = $desc;
5
    if ( isset( $data ) ) {
6
        $this->_error->data = $data;
7
    }
8
}

Seperti yang Anda lihat, metode ini menggunakan variabel instance $error, jadi mari kita tambahkan deklarasinya ke bagian atas kelas model dasar.

1
protected $_error;

Akhirnya, untuk membuatnya tetap terstruktur, mari kita buat metode pengambil untuk properti ini.

1
public function get_error() {
2
    return $this->_error;
3
}

Sesi Penanganan

Pengontrol Sesi

Untuk bagian terakhir dari tutorial ini, kita akan membuat controller dan model untuk menangani sesi pengguna.

Pengontrol untuk sesikita akan menanggapi setiap permintaan POST yang dibuat ke sumber Session, karena session tidak dapat diambil setelah pembuatan, atau diperbarui secara langsung, pengontrol ini hanya akan menanggapi permintaan POST dan DELETE. Harap dicatat bahwa mengirim permintaan lain ke sumber daya akan mengakibatkan kesalahan server, kita tidak berurusan dengan kasus tepi di sini, tetapi ini dapat dengan mudah dihindari dengan memeriksa apakah metode yang disebut ada di file MY_Controller kita dan menetapkan nama metode default jika sumber daya tidak mendukung permintaan tersebut.

Di bawah ini Anda akan menemukan struktur untuk pengontrol Session kita:

1
<?php
2
if ( !defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' );
3
4
class Session extends MY_Controller {
5
6
    public function __construct() {}
7
8
    public function save() {}
9
10
    public function remove( $id = null ) {}
11
}

Perhatikan bahwa kontroler ini memperluas kelas MY_Controller daripada kelas CI_Controller biasa, kita melakukan ini untuk menggunakan metode _remap dan fungsi lain yang dibuat sebelumnya. OK, jadi sekarang mari kita mulai dengan konstruktor.

1
public function __construct() {
2
    parent::__construct();
3
4
    $this->load->model( 'session_model', 'model' );
5
}

Konstruktor sederhana ini hanya memanggil konstruktor induknya (karena setiap pengontrol dalam CodeIgniter harus melakukannya) dan kemudian memuat model pengontrol. Kode untuk metode save adalah sebagai berikut.

1
public function save() {
2
    $result = $this->model->create();
3
    if ( !$result ) {
4
        $result = $this->model->get_error();
5
    }
6
    $this->_format_output( $result );
7
}

Dan kemudian kode untuk metode remove:

1
public function remove( $id = null ) {
2
    $result = $this->model->destroy( $id );
3
    if ( !$result ) {
4
        $result = $this->model->get_error();
5
    }
6
    $this->_format_output( $result );
7
}

Kedua metode hanya mendelegasikan tugas yang ada di tangan ke model, yang menangani manipulasi data aktual. Dalam aplikasi dunia nyata, validasi data yang diperlukan dan pemeriksaan sesi akan dilakukan di controller, dan tugas-tugas umum seperti pemeriksaan sesi harus diimplementasikan dalam pengendali dasar.

Model Session

Sekarang mari kita lanjutkan ke model session. Inilah struktur dasarnya:

1
<?php
2
if ( !defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' );
3
4
class Session_Model extends MY_Model {
5
6
    public function __construct() {}
7
8
    public function create() {}
9
10
    public function destroy( $id ) {}
11
}

Seperti pengontrol, model ini memperluas kelas MY_Model alih-alih kelas CI_Model reguler, ini dilakukan untuk menggunakan metode umum yang telah dibuat sebelumnya. Sekali lagi, mari kita mulai dengan konstruktor.

1
public function __construct() {
2
    $this->load->driver( 'mongo_db' );
3
}

Dalam hal ini, kita hanya memuat driver Mongo_db, yang telah kita bahas sebelumnya. Sekarang kita akan melanjutkan dengan metode yang bertugas menghancurkan session.

1
public function destroy( $id ) {
2
    $filters    = array( '_id' => $this->mongo_db->gen_id( $id ) );
3
4
    $query     = $this->mongo_db->get_where( 'sessions', $filters );
5
    if ( $query->num_rows() == 0 ) {
6
        $this->_set_error( 'INVALID_CREDENTIALS' );
7
        return false;
8
    }
9
10
    $this->mongo_db->remove( 'sessions', $filters );
11
    return 'SESSION_TERMINATED';
12
}

Dalam metode ini kita memeriksa apakah ada sesi untuk session_id yang diberikan, dan jika demikian kita berusaha menghapusnya, mengirim pesan sukses jika semuanya berjalan baik, atau menetapkan kesalahan dan mengembalikan kesalahan jika ada yang salah. Perhatikan bahwa ketika menggunakan session_id kita menggunakan metode khusus $this->mongo_db->gen_id, ini karena seperti yang saya sebutkan sebelumnya, ID di MongoDB adalah objek, jadi kita menggunakan string id untuk membuatnya.

Akhirnya, mari kita tulis metode create yang akan membungkus bagian satu dari seri tutorial ini.

1
public function create() {
2
    $query      = $this->mongo_db->get_where( 'users', array( 'email' => $this->input->post( 'email' ) ) );
3
    if ( $query->num_rows() != 1 ) {
4
        $this->_set_error( 'INVALID_CREDENTIALS' );
5
        return false;
6
    }
7
8
    $this->load->library( 'encrypt' );
9
    $user   = $query->row();
10
    $salt   = $this->encrypt->decode( $user->salt );
11
    if ( $user->pass != sha1( $this->input->post( 'pass' ) . $salt ) ) {
12
        $this->_set_error( 'INVALID_CREDENTIALS' );
13
        return false;
14
    }
15
16
    $this->mongo_db->remove( 'sessions', array( 'user_id' => $user->_id->__toString() ) );
17
18
    $session    = array(
19
        'timestamp'     => now(),
20
        'user_id'       => $user->_id->__toString(),
21
        'persistent'    => $this->input->post( 'persistent' )
22
    );
23
24
    if ( !$this->mongo_db->insert( 'sessions', $session ) ) {
25
        $this->_set_error( 'ERROR_REGISTERING_SESSION' );
26
        return false;
27
    }
28
29
    $result                 = new stdClass();
30
    $result->id             = $this->mongo_db->insert_id();
31
    $result->user_id        = $user->_id->__toString();
32
33
    return $result;
34
}

Pertama-tama, kita memeriksa bahwa ada pengguna yang terkait dengan email yang diberikan. Kemudian kita memecahkan kode salt terkait pengguna (yang akan saya jelaskan di bagian kedua dari seri ini ketika kami mencakup pendaftaran pengguna) dan memeriksa bahwa kata sandi yang diberikan sesuai dengan kata sandi yang disimpan pengguna.

Kita kemudian menghapus sesi sebelumnya yang terkait dengan pengguna dan membuat objek sesi baru. Jika kita memeriksa sesi secara menyeluruh, kita akan menambahkan hal-hal seperti bidang user_agent, ip_address, last_activity, dan seterusnya ke objek ini. Akhirnya, kita mengirim kembali ke klien sesi dan ID pengguna untuk sesi baru.


Kesimpulan

Ini adalah tutorial yang agak panjang, kita membahas banyak topik, bahkan memiliki lebih banyak lagi untuk dibahas. Mudah-mudahan sekarang Anda memiliki pemahaman yang lebih baik dari layanan RESTful atau stateless dan bagaimana membuat layanan seperti itu dengan CodeIgniter, dan mungkin, Anda mungkin juga telah mengambil beberapa ide baru yang dapat Anda berikan kepada fungsionalitas inti kerangka.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.