by Abu Zubayr

Setup Vue Js di Laravel dalam Satu Project

Langkah-Langkah Setup Vue Js di Laravel dalam 1 Project
Bismillah

Sebagai seorang fullstack developer, terkadang kita merasa kurang nyaman ketika develop sebuah aplikasi yang memiliki dua buah project yang berbeda. Dimana satu project sebagai backend dan satu-nya lagi sebagai frontend.

Sebelum munculnya berbagai framework dan library untuk frontend seperti vue, react, angular dll, biasanya seorang fullstack developer hanya bekerja disatu project saja. Biasanya untuk urusan tampilan, framework yang memakai konsep MVC (Model View Controller) maka letaknya adalah di bagian direktori view. Sebagai contoh, untuk laravel sendiri yang memakai konsep MVC, maka pengaturan tampilan berada di bagian resources/views secara default. Namun setelah kemunculan framework ataupun library frontend tadi, maka untuk frontend biasanya memiliki project tersendiri yang sudah bundling didalamnya node modules.

Dari permasalahan diatas agar proses develop menjadi mudah untuk seorang fullstack, maka solusinya adalah menyatukan backend dan frontend didalam sebuah project. Untuk laravel sendiri, ada sebuah node modules yang berfungsi untuk menyatukan Vue js ataupun library lainnya kedalam project laravel yakni laravel-mix. Mungkin di framework php lain seperti Codeigniter, Yii dan yang lainnya juga memiliki cara tersendiri untuk melakukan hal tersebut.

Baiklah, sebelum melakukan melakukan setup penggabungan library Vue dengan Laravel. Beberapa tools yang harus terinstal di laptop atau pc anda adalah node js dan composer. Jika belum terinstal, maka lakukan proses penginstalan keduanya terlebih dahulu.

Disini saya akan mencontohkan setup mulai dari awal yang dimulai dari pembuatan project laravel terlebih dahulu. Langkah-langkahnya adalah seperti berikut ini :
  • Buka terminal/command line, kemudian buat sebuah project laravel baru dengan cara memasukkan perintah berikut :
  • composer create-project laravel/laravel nama-project-anda
    Disini saya menggunakan composer untuk membuat project laravel. Selain menggunakan composer ada cara lain yang bisa anda lihat langsung di website resminya di https://laravel.com/docs/8.x/installation.
  • Setelah selesai, buka editor favorit anda kemudian tambahkan project yang sudah anda buat tadi kedalam editor tersebut.
  • Edit file package.json dibagian devDependencies, ubah menjadi seperti dibawah ini :
  •    "devDependencies": {
            "laravel-mix": "^6.0.6",
            "axios": "^0.21",
            "lodash": "^4.17.19",
            "postcss": "^8.1.14",
            "vue": "^3.2.26",
            "vue-loader": "^16.8.3",
            "vue-template-compiler": "^2.6.14",
            "vue-router": "^4.0.12"
        }
    Dibagian ini kita memasukkan modules yang dibutuhkan yakni vue, vue-loader, vue-template-compiler dan vue-router.
  • Setelah selesai, di terminal/command line masukkan perintah :
  • npm install
  • Kemudian masukkan lagi perintah dibawah ini :
  • npm run watch
    Perintah diatas gunanya adalah untuk melakukan compile script vue secara otomatis jika ada perubahan pada source code vue yang kita buat. Pastikan proses ini berhasil dan tidak terjadi error.
  • Selanjutnya jika sudah berhasil, buat sebuah direktori baru dengan nama `components` didirektori `resources/js`. Didalam direktori `components` tadi buat sebuah file dengan nama `App.vue`. Selanjutnya isi file tersebut dengan source code sederhana seperti dibawah ini :
  • <template>
        <div class='container'>
            <h1>Selamat Datang</h1>
        </div>
    </template>
  • Setelah itu edit file wellcome.blade.php yang berada didirektori resources/views/wellcome.blade.php sehingga menjadi seperti dibawah ini :
  • <html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
        <head>
            <meta charset="utf-8">
            <meta name="viewport" content="width=device-width, initial-scale=1">
            <title>Laravel | Vue js</title>
            <link href="{{ mix('/css/app.css') }}" rel="stylesheet"/>
        </head>
        <body>
            <div id="app">
                <App/>
            </div>
            <script src="{{ mix('js/app.js') }}"></script>
        </body>
    </html>
  • Kembali ke terminal anda, jalankan server local laravel dengan perintah :
  • php artisan serve
  • Buka browser, kemudian masuk ke url local laravel tadi di http://localhost:8000. Jika berhasil, maka akan muncul halaman index-nya seperti gambar dibawah ini :
  • Localhost laravel with vue frontend
Sampai disini kita sudah berhasil menggabungkan laravel dengan vue js. Di tutorial selanjutnya insyaAllah kita akan membahas bagaimana supaya request dari browser client bisa dibaca oleh router vue js. Jika ada pertanyaan mengenai postingan Setup Vue Js di Laravel dalam Satu Project silahkan ditanyakan dikolom komentar. Source code dari project ini sendiri bisa diakses melalui github di https://github.com/sardiabuzubayr/sample-vue-laravel

Demikian, semoga bermanfaat wassalamualaikum warahmatullah wabarakaatuh.
Share:

Trigger Database, Fungsi dan Manfaatnya

Trigger Database, Fungsi dan Manfaatnya
Bismillah...

Pada kasus tertentu, terkadang kita menginginkan sebuah script sql tertentu di eksekusi ketika terjadi proses insert, update ataupun delete di database. Pada aplikasi kasir misalnya, saat kasir menginput barang yang dibeli oleh customer di mesin kasir dan proses transaksi tersebut berhasil dilakukan, maka stok barang yang dibeli tentu akan berkurang. Atau contoh lain seperti anda berbelanja disebuah online shop misalnya, barang atau item yang anda checkout akan otomatis berkurang stoknya di penjual. Nah, sekarang bagaimanakah menerapkan sistem tersebut? Jika terjadi proses seperti ini kita akan melakukan update stok di tabel barang atau item. Mungkin selama ini anda banyak melakukannya di dalam source code aplikasi secara langsung. Memang tidak mengapa melakukan hal seperti itu didalam source code langsung, akan tetapi ada cara yang lebih baik dan efisien yang bisa anda terapkan yakni dengan menggunakan trigger database.

Apa itu trigger, apa fungsi dan manfaatnya ? Trigger adalah kumpulan script sql yang dieksekusi secara otomatis ketika terjadi proses DML (Data Manipulation Language) seperti insert, update dan delete di pada sebuah tabel. Umumnya trigger memiliki opsi apakah script sql akan di eksekusi sebelum atau sesudah, atau kedua-duanya.

Fungsi Trigger :
  • Mengeksekusi script sql secara otomatis ketika terjadi perubahan pada sebuah tabel.
  • Menjaga integritas data.
  • Mencegah proses perubahan yang tidak dibenarkan atau tidak sah.

Manfaat Trigger :
  • Aplikasi yang dibuat menjadi lebih cepat jika dibandingkan menulis langsung script sql di kode program.
  • Reusable, artinya ketika terjadi migrasi atau perpindahan bahasa pemrograman maka kita tidak perlu menulis ulang script sql di source code aplikasi.
  • Mudah untuk di maintenance.

Selanjutnya kita akan membahas tentang cara bagaimana membuat trigger serta menghapusnya. Dan dilanjutkan dengan contoh studi kasus sederhana untuk penerapan pembuatan trigger tersebut.

  1. Membuat Trigger
  2. Untuk membuat trigger caranya adalah dengan mengeksekusi script sql seperti dibawah ini :
    DELIMITER $$
    CREATE TRIGGER `nama_trigger` {BEFORE | AFTER} {INSERT | UPDATE | DELETE} ON `nama_tabel`  FOR EACH ROW
    BEGIN
    # … Bagian script sql yang akan dieksekusi
    END
    $$
    Penjelasan :
    • Insert
    • Trigger ketika insert merupakan sebuah kondisi dimana kita menjalankan script sql ketika perintah insert pada sebuah tabel dieksekusi. Trigger di proses insert terdapat dua buah kejadian, yakni BEFORE dan AFTER. BEFORE akan di eksekusi sebelum perintah insert dijalankan, sedangkan AFTER sendiri akan di eksekusi ketika perintah insert selesai dijalankan. Pada saat membuat trigger, bagian script yang kita eksekusi biasanya perlu mengambil nilai field dari tabel yang berubah tersebut. Cara mengambil nilai field tersebut adalah dengan keyword NEW dan diikuti dengan nama field ditabel.
    • Update
    • Trigger update akan dieksekusi ketika perintah update di jalankan pada sebuah tabel. Sama seperti trigger insert, trigger update juga terdapat dua buah kejadian yakni BEFORE dan AFTER. Perbedaannya adalah trigger update terdapat keyword NEW dan OLD sedangkan trigger insert hanya keyword NEW saja. Dimana keyword NEW digunakan untuk mengambil field tabel yang baru saja diubah nilainya, sedangkan keyword OLD digunakan untuk mengambil nilai field sebelum diubah.
    • Delete
    • Terakhir adalah trigger delete. Trigger ini akan di eksekusi ketika data pada sebuah tabel dihapus. Sama seperti kedua trigger diatas, trigger ini juga memiliki dua buah kejadian. Perbedaannya adalah trigger delete hanya memiliki keyword OLD untuk mengambil nilai field.

  3. Menghapus Trigger
  4. Untuk menghapus trigger, caranya adalah dengan mengeksekusi script sql seperti dibawah ini :
    DROP TRIGGER `nama_trigger`;
    Untuk melihat trigger yang pernah dibuat sebelumnya, caranya adalah dengan mengeksekusi script sql :
    SHOW TRIGGERS;
Diakhir postingan ini kita akan mencoba membuat trigger sederhana. Pada kasus ini kita akan mengupdate stok barang secara otomatis ketika barang tersebut dijual, diubah atau dihapus. Sekarang buatlah 2 buah tabel seperti dibawah ini :
Erd inventory sederhana
Untuk mempermudah langsung saja copas script berikut ini untuk membuat tabel diatas, ditutorial ini saya menggunakan MySQL atau Maria DB sebagai database:
CREATE TABLE items (
	id_item INT(10) NOT NULL AUTO_INCREMENT,
	nama_item VARCHAR(100) NULL DEFAULT NULL,
	harga FLOAT(15,2) NULL DEFAULT NULL,
	stok INT(10) NULL DEFAULT NULL,
	PRIMARY KEY (id_item) USING BTREE
);

CREATE TABLE transaction (
	id_transaction INT(10) NOT NULL AUTO_INCREMENT,
	id_item INT(10) NOT NULL,
	qty INT(10) NULL DEFAULT '1',
	total FLOAT(15,2) NULL DEFAULT NULL,
	PRIMARY KEY (id_transaction) USING BTREE,
	INDEX FK__items (id_item) USING BTREE,
	CONSTRAINT FK__items FOREIGN KEY (id_item) REFERENCES items (id_item) ON UPDATE NO ACTION ON DELETE NO ACTION
);

INSERT INTO `items` (`id_item`, `nama_item`, `harga`, `stok`) VALUES
(1, 'Gula', 11000.00, 10), (2, 'Kopi', 5000.00, 20), (3, 'Susu', 8000.00, 25), (4, 'Indomie', 2500.00, 15);
Dari tabel diatas kita akan membuat trigger dengan rule sebagai berikut :
  • Stok di tabel items akan otomatis ter-update pada saat dilakukan insert, update ataupun delete di tabel transaction.
  • Sebelum melakukan insert, cek terlebih dahulu stok di tabel items. Dimana stok di tabel items tidak boleh kurang dari 0 pada saat terjadi transaksi di tabel transaction.
  • Pada saat melakukan update data di tabel transaction, jika jumlah qty yang baru di masukkan lebih kecil dari qty yang sebelumnya (qty lama), maka stok yang ada di tabel items akan otomatis bertambah, begitu juga sebaliknya stok akan berkurang jika qty baru lebih besar dari qty sebelumnya.
  • Pada saat setelah terjadi proses delete, stok di tabel items akan otomatis bertambah.
Dari rule diatas maka kita akan membuat trigger INSERT BEFORE, UPDATE BEFORE dan DELETE AFTER pada tabel transaction.
  1. INSERT BEFORE
  2. Trigger yang pertama yang akan kita buat adalah trigger insert before. Trigger ini sendiri akan melakukan pengecekan pada saat ada penambahan baris data baru di tabel transaction, dimana jika qty yang akan dijual dikurangi stok yang ada di item tidak boleh kurang dari nol. Script sql-nya adalah seperti dibawah ini :
    DELIMITER $$
    CREATE TRIGGER `transaction_insert_before` BEFORE INSERT ON `transaction` FOR EACH ROW BEGIN
    SET @stok = (SELECT stok FROM items WHERE id_item = NEW.id_item);
    SET @sisa = @stok - NEW.qty;
    IF @sisa < 0 THEN
    	SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Warning: stok tidak cukup'; 
    END IF;
    UPDATE items SET stok = @sisa WHERE id_item = NEW.id_item;
    END
    $$
    Pada script diatas kita membuat trigger dengan nama `transaction_insert_before` ditabel transaction. Pada baris berikutnya kita membuat variabel `@stok` dan mengisinya dengan stok yang ada di tabel items, sesuai dengan id_item yang dimasukkan ditabel transaction. Selanjutnya kita membuat variabel sisa yang isinya adalah hasil pengurangan antara stok dengan qty yang dimasukkan dari tabel transaction. Kemudian dicek apakah hasil pengurangan tadi kurang dari nol? Jika iya, maka kita akan menghentikan operasi insert ditabel transaction dengan melemparkan pesan kesalalahan SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Warning: stok tidak cukup'; . Namun jika sisa tidak kurang dari nol, maka kita akan meng-update stok yang ada ditabel items dengan nilai yang ditampung di variabel sisa tadi. Hasilnya jika kita memasukkan qty melebihi stok yang ada ditabel items, maka akan muncul pesan kesalahan seperti ini pada saat insert transaction :
    Throw sql state error on trigger
  3. UPDATE BEFORE
  4. Trigger ini akan melakukan pengecekan pada saat tabel transaction melakukan proses update data. Dimana rule yang telah ditentukan diatas, maka script sql untuk membuat trigger update before adalah sebagai berikut :
    CREATE  TRIGGER `transaction_update_before` BEFORE UPDATE ON `transaction` FOR EACH ROW 
    BEGIN
    IF OLD.id_item = NEW.id_item THEN 
    	SET @stok = (SELECT stok FROM items WHERE id_item = OLD.id_item);
    	SET @sisa = (@stok + OLD.qty) - NEW.qty;
    	IF @sisa < 0 THEN
    		SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Warning: stok tidak cukup'; 
    	END IF;
    	UPDATE items SET stok = @sisa WHERE id_item = OLD.id_item;
    ELSE
    	SET @stok_lama = (SELECT stok FROM items WHERE id_item = OLD.id_item);
    	SET @sisa_lama = (@stok_lama + OLD.qty);
    	UPDATE items SET stok = @sisa_lama WHERE id_item = OLD.id_item;
    	SET @stok_baru = (SELECT stok FROM items WHERE id_item = NEW.id_item);
    	SET @sisa_baru = @stok_baru - NEW.qty;
    	IF @sisa_baru < 0 THEN
    		SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Warning: stok tidak cukup'; 
    	END IF;
    	UPDATE items SET stok = @sisa_baru WHERE id_item = NEW.id_item;
    END IF;
    END
    Saat membuat trigger update, kita melihat bahwa disana ada keyword NEW dan OLD. Keyword NEW disini berarti merupakan nilai sebuah field yang baru saja diubah, sedangkan OLD adalah nilai field yang sebelumnya atau yang lama. Sama seperti trigger insert, kita akan melakukan pengecekan jika kondisi tidak sesuai dengan yang diinginkan maka kita akan melemparkan pesan kesalahan dalam bentuk SIGNAL SQLSTATE '45000' .
  5. DELETE AFTER
  6. Terakhir trigger yang akan kita buat adalah trigger delete after. Trigger ini akan dieksekusi setelah proses delete terjadi. Script-nya adalah sebagai berikut :
    CREATE TRIGGER `transaction_delete_after` AFTER DELETE ON `transaction` FOR EACH ROW 
    BEGIN
    SET @stok = (SELECT stok FROM items WHERE id_item = OLD.id_item);
    SET @sisa = @stok + OLD.qty;
    UPDATE items SET stok = @sisa WHERE id_item = OLD.id_item;
    END
    Mengikuti rule yang telah dibuat sebelumnya, yakni jika ada baris data yang dihapus pada tabel transaction, maka stok pada tabel items akan bertambah sesuai dengan jumlah qty yang dihapus pada tabel transaction.
Demikian tutorial Trigger Database, Fungsi dan Manfaatnya. Jika ada pertanyaan silahkan ditanyakan dikolom komentar. Atau jika ada pertanyaan lain seputar programming bisa kontak saya melalui email private.sardi[dot]gmail.com, jika ada waktu luang dan bisa saya jawab maka akan saya jawab insyaAllah.
Semoga bermanfaat, wassalamualaikum warahmatullah wabarakatuh
Share:

Dimanakah Sebaiknya Menyimpan Konfigurasi di Golang?

Dimanakah Sebaiknya Menyimpan Konfigurasi di Golang?
Bismillah

Setiap aplikasi yang kita buat tentu membutuhkan settingan konfigurasi. Konfigurasi tersebut pun bermacam-macam, bisa berupa konfigurasi database, email, url aplikasi dan lain-lain. Nah, lantas bagaimanakah sebaiknya settingan tersebut dilakukan? Apakah settingan tersebut langsung ditulis di dalam source code project anda? Tentu saja tidak jawabannya. Menulis langsung konfigurasi di dalam source code aplikasi anda akan membuat proses maintenance menjadi sangat sulit dilakukan. Bayangkan saja misalnya didalam source code anda terdapat konfigurasi yang berbeda-beda file-nya, satu ada di direktori ini dan yang lainnya tersebar di berbagai direktori lainnya. Dan ketika terjadi perubahan dengan konfigurasi itu, anda harus membongkar source code tersebut dan mencarinya satu persatu. Bayangkan pula model penulisan konfigurasi seperti ini anda buat bukan hanya satu project saja, tapi juga di project lainnya anda lakukan hal yang sama. Waah, pasti pusing tujuh keliling anda dibuatnya, hal seperti ini membutuhkan waktu yang lama dan melelahkan. Lalu apa solusinya? kita bahas lebih lanjut.

Umumnya konfigurasi sebuah aplikasi ditulis didalam file tersendiri, baik berupa file dengan eksistensi .env (environment), .properties, .json atau bentuk-bentuk lainnya. Yang jelas, file konfigurasi tersebut berada diluar source code aplikasi itu sendiri. Didalam postingan ini saya akan memberikan contoh bagaimana cara membuat file konfigurasi tersebut. Saya hanya mencontohkan cara membuat file konfigurasi tersebut menggunakan bahasa Go atau Golang. Untuk bahasa lainnya anda bisa mencari dari referensi lain, secara penerapan sama insyaAllah.

Ada beberapa library atau modul yang bisa anda gunakan di golang untuk menulis file konfigurasi diantaranya adalah modul godotenv atau juga bisa menggunakan vifer. Di tutorial ini saya mencontohkan file konfigurasi tersebut ditulis di file main.go, untuk project real, biasanya konfigurasi tersebut di buat di file khusus misalnya di config atau yang lainnya.
Baiklah langsung saja kita coba mempraktekkan bagaimana cara menggunakan modul tersebut satu persatu.

  1. GODOTENV
  2. Penggunaan library ini biasanya digunakan dengan eksistensi file .env. Untuk membuat konfigurasi menggunakan library ini, langkah-langkahnya adalah sebagai berikut :
    • Di project direktori anda, buka terminal/command line kemudian masukkan perintah :
    • go get github.com/joho/godotenv
    • Setelah selesai, buat sebuah file dengan eksistensi .env
    • Didalam file tersebut, tulis isi konfigurasi anda dengan format key-value, misalnya : APP-NAME=Belajar Konfigurasi Golang dimana APP-NAME adalah key, sedangkan Belajar Konfigurasi Golang merupakan value.
    • Selanjutnya buka file main.go jika sudah ada, atau jika belum buat file baru dengan nama main.go, kemudian masukkan source code seperti dibawah ini :
    • err := godotenv.Load(".env")
      if err != nil {
          panic("Cannot load .env file")
      }
      fmt.Println("Membuka konfigurasi menggunakan file .env")
      fmt.Println("==========================================")
      fmt.Println(os.Getenv("APP-NAME"))
      fmt.Println(os.Getenv("APP-GITHUB-PROJECT"))
      fmt.Println(os.Getenv("OWNER"))

      Penjelasan :
      • godotenv.Load(“.env”), artinya kita akan memuat atau membuka file .env tersebut, yang perlu diperhatikan adalah dimana anda menyimpan file .env tersebut, pastikan path dari file tersebut sudah benar karena jika path-nya salah maka akan terjadi error.
      • os.Getenv(“”), pada fungsi inilah kita menentukan key mana yang akan dipanggil.
  3. VIPER
  4. Viper sendiri lebih luas penggunaannya tidak berpatokan hanya satu jenis tipe file konfigurasi saja. Dengan viper anda bisa menulis konfigurasi dalam format JSON, TOML, YAML, HCL, INI, env, atau properties yang biasa di pakai di bahasa Java. Pada contoh ini kita akan mencoba menggunakan format JSON dan YAML. Adapun langkah-langkah untuk membuat konfigurasi menggunakan Viper adalah sebagai berikut :
    • Di project direktori anda, buka terminal/command line kemudian masukkan perintah :
    • go get github.com/spf13/viper
    • Kemudian, buat sebuah file dengan nama config.json
    • Tulis isi konfigurasi anda didalam file tersebut seperti menulis json pada umumnya, sebagai contoh seperti dibawah ini :
    • {
          "app_name":"Belajar Konfigurasi Golang",
          "app_github_project":"https://github.com/sardiabuzubayr",
          "owner":"Abu Zubayr",
          "port":3306
      }
    • Selanjutnya buka file main.go jika sudah ada, atau jika belum buat file baru dengan nama main.go, kemudian masukkan source code seperti dibawah ini :
    • viper.SetConfigName("config")
      viper.SetConfigType("json")
      viper.AddConfigPath(".")
      err = viper.ReadInConfig()
      if err != nil {
          panic("Cannot load configuration file")
      }
      fmt.Println("Membuka konfigurasi menggunakan file json (tanpa menentukan tipe data dari konfigurasi)")
      fmt.Println(viper.Get("app_name"))
      fmt.Println(viper.Get("app_github_project"))
      fmt.Println(viper.Get("owner"))
      fmt.Println(viper.Get("port"))
      
      fmt.Println("Membuka konfigurasi menggunakan file json (dengan menentukan tipe data dari konfigurasi)")
      fmt.Println(viper.GetString("app_name"))
      fmt.Println(viper.GetString("app_github_project"))
      fmt.Println(viper.GetString("owner"))
      fmt.Println(viper.GetInt("port"))

      Penjelasan :
      • viper.SetConfigName("config"), pada baris kode ini kita menentukan apa nama file konfigurasi yang akan dibaca oleh viper.
      • viper.SetConfigType("json"), bagian ini kita menentukan apa jenis file config yang kita gunakan.
      • viper.AddConfigPath("."), bagian ini menentukan dimana posisi file konfigurasi tersebut di tempatkan.
      • viper.ReadInConfig(), baris kode ini digunakan untuk memuat file konfigurasi tersebut, jika sudah benar nama, jenis, dan dimana file tersebut disimpan maka tidak akan terjadi error dibagian ini.
      • viper.Get(""), pada fungsi inilah kita tentukan key mana yang akan dipanggil. Fungsi ini bersifat global artinya seluruh data baik yang bertipe string atau angka bisa dipanggil dengan fungsi yang sama. Atau bisa juga dengan menggunakan fungsi yang lebih spesifik misalnya GetString untuk mengambil key yang datanya adalah karakter, atau GetInt untuk data yang bertipe integer, atau masih banyak lagi tipe yang disediakan oleh viper.

      Diatas adalah contoh tipe konfigurasi dengan file json. Untuk membuat dan membaca konfigurasi dengan file yaml, caranya sama, hanya saja format file konfigurasi ditulis mengikuti format yaml. Sebagai contoh adalah sebagai berikut :
      app_name: Belajar Konfigurasi Golang
      app_github_project: https://github.com/sardiabuzubayr
      owner: Abu Zubayr
      port: 3306

      Kemudian dibagian kode SetConfigType, masukkan “yaml” sehingga menjadi seperti viper.SetConfigType("yaml").
Source code keseluruhan terlihat seperti dibawah ini :
package main

import (
	"fmt"
	"os"

	"github.com/joho/godotenv"
	"github.com/spf13/viper"
)

func main() {
	err := godotenv.Load(".env")
	if err != nil {
		panic("Cannot load .env file")
	}
	fmt.Println("Membuka konfigurasi menggunakan file .env")
	fmt.Println("==========================================")
	fmt.Println(os.Getenv("APP-NAME"))
	fmt.Println(os.Getenv("APP-GITHUB-PROJECT"))
	fmt.Println(os.Getenv("OWNER"))

	viper.SetConfigName("config")
	viper.SetConfigType("json")
	viper.AddConfigPath(".")
	err = viper.ReadInConfig()
	if err != nil {
		panic("Cannot load configuration file " + err.Error())
	}
	fmt.Println("Membuka konfigurasi menggunakan file json (tanpa menentukan tipe data dari konfigurasi)")
	fmt.Println(viper.Get("app_name"))
	fmt.Println(viper.Get("app_github_project"))
	fmt.Println(viper.Get("owner"))
	fmt.Println(viper.Get("port"))

	fmt.Println("Membuka konfigurasi menggunakan file json (dengan menentukan tipe data dari konfigurasi)")
	fmt.Println(viper.GetString("app_name"))
	fmt.Println(viper.GetString("app_github_project"))
	fmt.Println(viper.GetString("owner"))
	fmt.Println(viper.GetInt("port"))

	viper.SetConfigName("config")
	viper.SetConfigType("yaml")
	viper.AddConfigPath(".")
	err = viper.ReadInConfig()
	if err != nil {
		panic("Cannot load configuration file " + err.Error())
	}
	fmt.Println("Membuka konfigurasi menggunakan file yaml (tanpa menentukan tipe data dari konfigurasi)")
	fmt.Println(viper.Get("app_name"))
	fmt.Println(viper.Get("app_github_project"))
	fmt.Println(viper.Get("owner"))
	fmt.Println(viper.Get("port"))

	fmt.Println("Membuka konfigurasi menggunakan file yaml (dengan menentukan tipe data dari konfigurasi)")
	fmt.Println(viper.GetString("app_name"))
	fmt.Println(viper.GetString("app_github_project"))
	fmt.Println(viper.GetString("owner"))
	fmt.Println(viper.GetInt("port"))
}


Demikian tutorial singkat mengenai Dimanakah Sebaiknya Menyimpan Konfigurasi di GolangDimanakah Sebaiknya Menyimpan Konfigurasi di Golang. Jika ada pertanyaan silahkan komen dibawah postingan ini. Jika ada kesempatan, insyaAllah saya juga akan membahas mengenai Centralize Configuration yang juga berkaitan dengan materi yang sedang kita bahas sekarang ini. Project ini juga ada saya tulis di github yang bisa dilihat di https://github.com/sardiabuzubayr/go-config.

Semoga bermanfaat, wassalamualaikum warahmatullah wabarakatuh.
Share:

Crud API di Golang Menggunakan Echo Framework dan GORM

Crud API di Golang Menggunakan Echo Framework dan GORM

Bismillah...

Walhamdulillah, pada postingan sebelumnya kita sudah membahas mengenai Rest API di Golang Menggunakan Echo Framework. Pada postingan tersebut kita telah membahas tentang dasar-dasar pembuatan rest api di golang menggunakan framework yang diklaim lebih cepat dari Gin. Nah, postingan ini merupakan lanjutan dari postingan tersebut, jika anda belum membacanya sangat disarankan untuk mengikuti tutorial sebelumnya dari awal postingan.

Baiklah, di postingan ini kita akan mencoba membuat fungsi CRUD (Create, Read Update and Delete) sederhana menggunakan salah satu library ORM yang dipakai di golang yakni GORM. Untuk mengakses dokumentasi secara lengkap anda bisa menuju ke laman website resminya di https://gorm.io. Untuk studi kasus, kita akan membuat sebuah fungsi crud untuk tabel users. Dimana tabel tersebut berisi Email, Nama, No Handphone, Alamat dan KTP.

Buatlah sebuah database (nama database bebas) kemudian buat sebuah tabel dengan nama users. Untuk mempermudah anda bisa langsung copas script pembuatan tabel di bawah ini :
CREATE TABLE users (
	email VARCHAR(100) NOT NULL,
	nama VARCHAR(50) NOT NULL,
	no_handphone VARCHAR(15) DEFAULT NULL,
	alamat TEXT DEFAULT NULL,
	ktp VARCHAR(255) DEFAULT NULL,
	PRIMARY KEY (email) USING BTREE
);


Setelah selesai membuat tabel, langsung buka project sebelumnya. Beberapa yang akan kita lakukan adalah sebagai berikut :
  1. Membuat Koneksi Database
  2. Sebelum membuat konesi database, tambahkan terlebih dahulu modul GORM didalam project anda. Caranya adalah dengan memasukkan perintah di terminal/command line dengan :
    go get gorm.io gorm.io/driver/mysql

    Setelah selesai, buat terlebih dahulu sebuah direktori misalnya dengan nama config. Kemudian didalam direktori tersebut buat sebuah file dengan nama database.go. Isi file tersebut dengan kode seperti dibawah ini :
    package config
    
    import (
        "gorm.io/driver/mysql"
        "gorm.io/gorm"
    )
    
    var DB *gorm.DB
    
    func ConnectDB() {
        host := "localhost"
        port := "3306"
        dbname := "blogspot"
        username := "root"
        password := ""
    
        dsn := username + ":" + password + "@tcp(" + host + ":" + port + ")/" + dbname + "?charset=utf8&parseTime=true&loc=Local"
        var err error
        DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{SkipDefaultTransaction: true})
        if err != nil {
            panic("Cannot connect database")
        }
        DB.AutoMigrate()
    }

    Pada file database.go diatas, kita membuat sebuah variabel global dengan var DB *gorm.io. Variabel inilah yang nantinya akan kita gunakan untuk melakukan query ke database. Namun perlu diketahui bahwa cara penggunaan seperti ini tidak dianjurkan jika project yang dibuat dengan skala besar. Untuk project dengan skala besar disarankan untuk menerapkan clean arcitecture dimana koneksi database tidak di expose secara global, melainkan dibuat di masing-masing repository yang menyimpan database handler.

  3. Membuat Fungsi CRUD
  4. Selanjutnya kita akan membuat fungsi crud menggunakan koneksi database yang sudah dibuat sebelumnya. Supaya lebih teratur, maka fungsi crud tersebut akan saya buat terpisah dari file server.go. Untuk itu buat terlebih dahulu sebuah direktori baru lagi dengan nama model, kemudian buat sebuah file didalamnya dengan nama users.go. Didalam file ini kita akan memindahkan struct Users yang sebelumnya berada di file server.go ke file users.go. Isi dari file users.go adalah seperti dibawah ini :
    package model
    
    import "restapi/config"
    
    type Users struct {
        Email       string `json:"email" form:"email" gorm:"primaryKey"`
        Nama        string `json:"nama" form:"nama"`
        NoHandphone string `json:"no_handphone" form:"no_handphone"`
        Alamat      string `json:"alamat" form:"alamat"`
        Ktp         string `json:"ktp" form:"ktp"`
    }
    
    func (user *Users) CreateUser() error {
        if err := config.DB.Create(user).Error; err != nil {
            return err
        }
        return nil
    }
    
    func (user *Users) UpdateUser(email string) error {
        if err := config.DB.Model(&Users{}).Where("email = ?", email).Updates(user).Error; err != nil {
            return err
        }
        return nil
    }
    
    func (user *Users) DeleteUser() error {
        if err := config.DB.Delete(user).Error; err != nil {
            return err
        }
        return nil
    }
    
    func GetOneByEmail(email string) (Users, error) {
        var user Users
        result := config.DB.Where("email = ?", email).First(&user)
        return user, result.Error
    }
    
    func GetAll(keywords string) ([]Users, error) {
        var users []Users
        result := config.DB.Where("email LIKE ? OR nama LIKE ?", "%"+keywords+"%", "%"+keywords+"%").Find(&users)
    
        return users, result.Error
    }

    Penjelasan :
    • CreateUser
    • Method ini adalah method yang kita gunakan untuk melakukan insert ke database. Pada method ini memiliki penerima berupa struct Users. Artinya method CreateUser melekat pada struct Users, dan bisa diakses langsung oleh object struct tersebut. Kemudian method ini juga memiliki nilai balik atau return value berupa interface error. Method yang digunakan untuk insert data ke database melalui gorm adalah method Create, seperti yang terlihat di baris kode config.DB.Create(user). config.DB sendiri merupakan variabel koneksi database yang sebelumnya sudah kita buat di file database.go.
    • UpdateUser
    • Method ini merupakan method yang kita gunakan untuk melakukan update data ke database. Sama seperti method CreateUser, method ini juga memiliki penerima berupa struct Users. Kemudian method ini memiliki parameter berupa primary key dari tabel users yakni email. Jadi nantinya kita akan melakukan update data users berdasarkan email yang dimiliki oleh user tersebut. Yang perlu diperhatikan adalah pada bagian config.DB.Model(&Users), ini menandakan bahwa kita akan melakukan sesuatu di model atau tabel users. Kemudian dilanjutkan dengan method Where(“email = ?”, email) dimana ini merupakan filter user yang memiliki email tersebut yang akan kita update data-nya, dan dilanjutkan dengan method Updates(user) dimana method inilah yang akan melakukan perintah eksekusi update ke database.
    • DeleteUser
    • Kemudian method terakhir yang akan kita buat adalah method UpdateUser. Dimana method ini yang digunakan untuk menghapus data yang ada pada tabel users. Letak eksekusi perintah delete terdapat pada bagian config.DB.Delete(user).
    • GetOneByEmail
    • Fungsi ini digunakan untuk mengambil data di tabel users berdasarkan email. Jadi seperti yang sudah terlihat di baris kode, bahwa fungsi ini menerima parameter berupa string email. Kemudian return dari fungsi ini adalah struct Users dan error. Jika anda belum familiar dengan fungsi yang seperti ini saya kira wajar, karena saya sendiri juga baru menemukan di golang bahwa sebuah method atau fungsi bisa memiliki return value lebih dari 1 object atau nilai. Method yang digunakan gorm untuk melakukan select sendiri adalah method First. Dimana method ini akan melakukan select dengan limit 1 baris.
    • GetAll
    • Kemudian fungsi terakhir adalah fungsi GetAll. Fungsi ini merupakan fungsi yang akan kita gunakan untuk menampilkan data secara keseluruhan atau lebih dari 1 baris. Pada method ini juga saya masukkan sebuah parameter keywords, dimana parameter tersebut digunakan untuk melakukan filter dari query yang kita jalankan. Untuk return sendiri, fungsi ini memiliki 2 buah return value yakni array dari struct Users dan error.

  5. Mengubah Router
  6. Setelah selesai membuat method dan fungsi diatas, selanjutnya adalah mengubah bagian router di file server.go yang telah kita buat sebelumnya dengan kode seperti dibawah ini :
    config.ConnectDB()
    route := echo.New()
    route.POST("user/create_user", func(c echo.Context) error {
    	user := new(model.Users)
    	c.Bind(user)
    	contentType := c.Request().Header.Get("Content-type")
    	if contentType == "application/json" {
    		fmt.Println("Request dari json")
    	} else if strings.Contains(contentType, "multipart/form-data") || contentType == "application/x-www-form-urlencoded" {
    		file, err := c.FormFile("ktp")
    		if err != nil {
    			fmt.Println("Ktp kosong")
    		} else {
    			src, err := file.Open()
    			if err != nil {
    				return err
    			}
    			defer src.Close()
    			dst, err := os.Create(file.Filename)
    			if err != nil {
    				return err
    			}
    			defer dst.Close()
    			if _, err = io.Copy(dst, src); err != nil {
    				return err
    			}
    
    			user.Ktp = file.Filename
    			fmt.Println("Ada file, akan disimpan")
    		}
    	}
    	response := new(Response)
    	if user.CreateUser() != nil { // method create user
    		response.ErrorCode = 10
    		response.Message = "Gagal create data user"
    	} else {
    		response.ErrorCode = 0
    		response.Message = "Sukses create data user"
    		response.Data = *user
    	}
    	return c.JSON(http.StatusOK, response)
    })
    
    route.PUT("user/update_user/:email", func(c echo.Context) error {
    	user := new(model.Users)
    	c.Bind(user)
    	response := new(Response)
    	if user.UpdateUser(c.Param("email")) != nil { // method update user
    		response.ErrorCode = 10
    		response.Message = "Gagal update data user"
    	} else {
    		response.ErrorCode = 0
    		response.Message = "Sukses update data user"
    		response.Data = *user
    	}
    	return c.JSON(http.StatusOK, response)
    })
    
    route.DELETE("user/delete_user/:email", func(c echo.Context) error {
    	user, _ := model.GetOneByEmail(c.Param("email")) // method get by email
    	response := new(Response)
    
    	if user.DeleteUser() != nil { // method update user
    		response.ErrorCode = 10
    		response.Message = "Gagal menghapus data user"
    	} else {
    		response.ErrorCode = 0
    		response.Message = "Sukses menghapus data user"
    	}
    	return c.JSON(http.StatusOK, response)
    })
    
    route.GET("user/search_user", func(c echo.Context) error {
    	response := new(Response)
    	users, err := model.GetAll(c.QueryParam("keywords")) // method get all
    	if err != nil {
    		response.ErrorCode = 10
    		response.Message = "Gagal melihat data user"
    	} else {
    		response.ErrorCode = 0
    		response.Message = "Sukses melihat data user"
    		response.Data = users
    	}
    	return c.JSON(http.StatusOK, response)
    })
    
    route.Start(":9000")

    Di baris kode diatas, saya membuat sebuah struct Response. Isinya adalah sebagai berikut :
    type Response struct {
        ErrorCode int         `json:"error_code" form:"error_code"`
        Message   string      `json:"message" form:"message"`
        Data      interface{} `json:"data"`
    }

    Pada kode diatas, yang perlu anda perhatikan adalah pada bagian yang saya beri tanda komentar //. Pada bagian tersebutlah merupakan method dan fungsi yang kita panggil dari file users.go.
    Setelah selesai seluruhnya, sekarang kita lakukan pengujian terhadap api yang sudah dibuat menggunakan postman.
    1. Endpoint (user/create_user) POST
    2. Pengujian Rest Api Golang dengan Request multipart/form-data
      Pengujian menggunakan Content-Type : multipart/form-data
      Pengujian Rest Api Golang dengan Request application/json
      Pengujian menggunakan Content-Type : application/json

    3. Endpoint (user/update_user/:email) PUT
    4. Pengujian Rest Api Golang method PUT

    5. Endpoint (user/delete_user) DELETE
    6. Pengujian Rest Api Golang method DELETE

    7. Endpoint (user/search_user) GET
    8. Pengujian Rest Api Golang method GET tanpa parameter
      Request tanpa query params
      Pengujian Rest Api Golang method GET dengan query parameter
      Request dengan query params

Demikian tutorial Crud API di Golang Menggunakan Echo Framework dan GORM. Jika ada pertanyaan silahkan ditanyakan dikolom komentar dibawah. Untuk project juga sudah saya post di github bisa di cek di https://github.com/sardiabuzubayr/restapi-gorm.
Semoga bermanfaat, wassalamualaikum warahmatullah wabarakatuh
Share:

Rest API di Golang Menggunakan Echo Framework

Rest API di Golang Menggunakan Echo Framework
Bismillah...
Perkembangan teknologi dewasa ini sangatlah cepat, dulu kita sering menggunakan Soap sebagai protokol untuk pertukaran data lintas platform, akan tetapi seiiring berjalannya waktu, protokol tersebut pelan-pelan mulai ditinggalkan karena kemunculan protokol baru untuk pertukaran data yakni Rest API yang menawarkan kecepatan yang lebih baik dari pendahulunya.

Pada postingan ini saya akan membuat sebuah contoh penggunaan rest api dengan menggunakan bahasa golang, khususnya dengan menggunakan framework echo. Mengapa saya menggunakan golang untuk membuat rest api ini? Jawabannya karena saya sedang mempelajari bahasa golang, hhhee. Saya tertarik mempelajari bahasa golang karena dari segi kecepatannya sangat luar biasa cepat jika dibandingkan dengan bahasa lain. Sebelumnya saya pernah membandingkan rest api golang dengan php (framework Lumen). Hasilnya sangat beda jauh dari segi kecepatan. Pada simple case, lumen memerlukan 100 - 200 ms untuk merespon sebuah permintaan dan mengembalikan dalam bentuk json. Akan tetapi golang hanya memerlukan waktu 3 - 10 ms untuk untuk merespon permintaan tersebut. Kemudian dengan menggunakan J-Meter untuk test permintaan secara concurent atau request secara bersamaan (1000 - 2000 request secara bersamaan), hasil yang didapat semakin jauh berbeda. Lumen memerlukan 6000 an ms atau 6 second keatas, akan tetapi golang masih dibawah 1 second. Luarrr biasa, hal inilah yang mendorong saya untuk mempelajari lebih lanjut mengenai golang dan tentu harapan kedepannya adalah menggunakan golang ini sebagai bahasa utama saya disisi backend.

Didalam bahasa golang sendiri, secara default sudah menyediakan sebuah package net/http. Didalam package tersebut sudah tersedia untuk  web server, routing, templating dan lainnya. Akan tetapi untuk lebih mempermudah saya menggunakan framework tambahan yaitu echo framework. Dokumentasi dari framework ini secara lengkap bisa diakses di https://echo.labstack.com. Echo sendiri mengklaim bahwa dirinya lebih baik dari Gin framework yang juga merupakan framework untuk develop website di go. Ini bisa dilihat dari github echo framework di https://github.com/labstack/echo.

Baiklah langsung saja, ditulisan ini saya akan memasukkan beberapa hal yang umum kita gunakan di rest api seperti POST, PUT, GET dan DELETE. Disini saya tidak memasukkan data yang dikirim kedalam database. Akan tetapi hanya sekedar mengirim dan membaca data secara statis saja. InsyaAllah pada kesempatan lain saya akan membuat rest api ini lengkap dengan database, yassarallahu li.

Disini saya berasumsi anda sudah menginstal golang, jika belum bisa menginstal langsung dari website resmi golang di https://go.dev . Baiklah jika sudah terinstall di laptop atau pc anda kita akan langsung mulai :
  1. Buat sebuah direktori/folder beri saja namanya restapi misalnya
  2. Kemudian buka terminal atau command line anda dan masukkan perintah go mod init restapi
  3. go mod init restapi
    Dari perintah di atas akan menghasilkan sebuah file go.mod. Didalam file ini seluruh modul yang akan kita gunakan akan di definisikan di file tersebut.
  4. Setelah itu tambahkan modul echo framework dengan perintah :
  5. go get github.com/labstack/echo/v4
    Perintah diatas kita gunakan untuk menambahkan sebuah modul baru yakni modul echo framework tadi.
  6. Selanjutnya buka editor kesayangan anda, disini saya menggunakan Visual Studio Code. Didalam project directory anda, buat sebuah file dengan nama server.go.
  7. Didalam file server.go kita akan membuat sebuah struct yang memuat entitas user seperti email, nama, no_handphone, alamat dan ktp. Berikut adalah isi dari struct tersebut :
  8. type Users struct {
        Email       string `json:"email" form:"email"`
        Nama        string `json:"nama" form:"nama"`
        NoHandphone string `json:"no_handphone" form:"no_handphone"`
        ALamat      string `json:"alamat" form:"alamat"`
        Ktp         string `json:"ktp" form:"ktp"`
    }
    Pada struct diatas, kita sudah mendefinisikan entitas user. Yang perlu anda perhatikan adalah pada keyword json dan form. Keyword diatas berarti kita menentukan nama variabel yang digunakan untuk pertukaran data di rest api nantinya. Dimana keyword json ini akan terbaca pada saat data yang kita kirimkan dengan Content-Type application/json. Kemudian form akan terbaca jika Content-Type yang dikirim berupa multipart/form-data atau application/x-www-form-urlencoded.
  9. Kemudian di file yang sama, kita akan menginisialisasi fungsi dari framework echo yang akan kita gunakan sebagai web server sekaligus routing dari api yang kita buat. Tambahkan baris kode dibawah ini :
  10. func main() {
    	route := echo.New()
    	route.POST("user/create_user", func(c echo.Context) error {
    		…
    	})
    	route.PUT("user/update_user/:email", func(c echo.Context) error {
    		…
    	})
    	route.DELETE("user/delete_user/:email", func(c echo.Context) error {
    		…
    	})
    	route.GET("user/search_user", func(c echo.Context) error {
    		…
    	})
    	route.Start(":9000")
    }
    Pada source code diatas di function main, kita deklarasikan sebuah variabel route dengan inisialisasi function echo.New(). Function tersebut merupakan instance dari framework echo. Kemudian dilanjutkan kita definisikan method-method seperti POST, PUT, DELETE dan GET yang selanjutnya akan kita tulis kode didalamnya satu persatu.
  11. Selanjutnya dibagian method POST kita akan definisikan bahwa method tersebut akan menerima request dalam bentuk Content-Type application/json ataupun multipart/form-data. Sehingga baris kode pada method tersebut menjadi seperti berikut ini :
  12. 	user := new(Users)
            c.Bind(user)
            contentType := c.Request().Header.Get("Content-type")
            if contentType == "application/json" {
                fmt.Println("Request dari json")
            } else if strings.Contains(contentType, "multipart/form-data") || contentType == "application/x-www-form-urlencoded" {
                file, err := c.FormFile("ktp")
                if err != nil {
                    fmt.Println("Ktp kosong")
                } else {
                    src, err := file.Open()
                    if err != nil {
                        return err
                    }
                    defer src.Close()
                    dst, err := os.Create(file.Filename)
                    if err != nil {
                        return err
                    }
                    defer dst.Close()
                    if _, err = io.Copy(dst, src); err != nil {
                        return err
                    }
    
                    user.Ktp = file.Filename
                    fmt.Println("Ada file, akan disimpan")
                }
            }
            response := struct {
                Message string
                Data    Users
            }{
                Message: "Sukses melakukan penambahan data",
                Data:    *user,
            }
            return c.JSON(http.StatusOK, response)
    Penjelasan :
    • user := new(Users). Keyword new merupakan instance dari sebuah struct dalam hal ini Users. Variabel user menampung data pointer bertipe struct User.
      c.Bind(user) . Merupakan fungsi yang disediakan oleh framework echo untuk melakukan binding field yang dikirim oleh client kedalam sebuah interface.
      Cara diatas juga bisa diganti dengan kode seperti ini :
      var user Users
      c.Bind(&user)
    • contentType := c.Request().Header.Get("Content-type") digunakan untuk mengetahui jenis Content-Type apa yang dikirim oleh client.
    • Pada bagian selanjutnya hanya berupa pengecekan apa jenis content-type tadi. Kemudian khusus bagian :
      else if strings.Contains(contentType, "multipart/form-data") || contentType == "application/x-www-form-urlencoded" { …. } didalam blok kode tersebut saya mengecek apakah ada file yang dikirim, karena untuk Content-Type json tidak bisa mengirim data dalam bentuk file. Jika ada file yang dikirim, maka akan saya simpan file tersebut. Selanjutnya nama file yang dikirim tadi akan saya masukkan ke variabel ktp.
    • return c.JSON(http.StatusOK, user) merupakan response yang akan dikembalikan ke client yakni dalam bentuk json dari struct user tadi.
      http.StatusOK merupakan response code 200 yang dikembalikan ke client.
  13. Beralih ke method selanjutnya yakni method PUT. Pada method PUT ini umumnya digunakan untuk pengupdatan/perubahan data. Pada method ini masukkan kode berikut :
  14. 	user := new(Users)
            c.Bind(user)
            user.Email = c.Param("email")
            // do something here ....
            response := struct {
                Message string
                Data    Users
            }{
                Message: "Sukses mengupdate data",
                Data:    *user,
            }
            return c.JSON(http.StatusOK, response)
    Penjelasan :
    • c.Param(“email”) digunakan untuk mengambil parameter dari url. Dalam hal ini parameter yang ada di method PUT tersebut adalah email.
  15. Kemudian dibagian method DELETE. Method ini digunakan untuk melakukan penghapusan data. Sama seperti method PUT, biasanya method DELETE juga menyertakan sebuah ID untuk identifikasi data mana yang akan dihapus. Isi dari method DELETE seperti berikut ini :
  16. 	user := new(Users)
            user.Email = c.Param("email")
            // do something here ....
            response := struct {
                Message string
                ID      string
            }{
                Message: "Sukses menghapus data",
                ID:      user.Email,
            }
            return c.JSON(http.StatusOK, response)
  17. Terakhir adalah method GET. Method ini biasanya digunakan untuk melakukan request data ke server. Dan biasanya method ini juga mengirimkan sebuah query parameter. Berikut adalah contohnya :
  18. 	user := new(Users)
            user.Email = c.QueryParam("keywords")
            user.Nama = "Abu Zubayr"
            user.ALamat = "Jalan Jalan"
            user.Ktp = "file.jpg"
            // do something here ....
            response := struct {
                Message string
                Data    Users
            }{
                Message: "Sukses melihat data",
                Data:    *user,
            }
            return c.JSON(http.StatusOK, response)
  19. Setelah selesai menulis seluruhnya. Saatnya melakukan pengujian menggunakan Postman. Terlebih dahulu, jalankan server anda dengan membuka command line lalu masukkan perintah go run server.go

Hasil pengujian rest api adalah sebagai berikut :

  1. Endpoint (user/create_user) POST
  2. Endpoint (user/create_user) POST json
    - Diatas adalah contoh request post method dengan data yang dikirim dalam bentuk json (Content-Type : application/json). Kemudian jika menggunakan Content-Type : multipart/form atau application/x-www-form-urlencoded, maka request-nya adalah seperti gambar dibawah ini :
    Endpoint (user/create_user) POST form
    - Diatas pada field ktp diisi terisi sebuah file yang dikirim. Untuk pengiriman file sendiri, tidak bisa dilakukan dengan Content-Type : application/json.
  3. Endpoint (user/update_user/:email) PUT
  4. Endpoint (user/update_user/:email) PUT
    - Terlihat di endpoint method diatas terdapat parameter email fulan@gmail.com. Parameter inilah yang dibaca go dengan kode c.Param(“email”).
  5. Endpoint (user/delete_user/:email) DELETE
  6. Endpoint (user/delete_user/:email) DELETE
  7. Endpoint (user/search_user) GET
  8. Endpoint (user/search_user) GET
Demikian, hasil yang didapat dari pengujian api menggunakan postman. Untuk source code full dari aplikasi diatas adalah sebagai berikut :
package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
    "strings"

    "github.com/labstack/echo/v4"
)

type Users struct {
    Email       string `json:"email" form:"email"`
    Nama        string `json:"nama" form:"nama"`
    NoHandphone string `json:"no_handphone" form:"no_handphone"`
    ALamat      string `json:"alamat" form:"alamat"`
    Ktp         string `json:"ktp" form:"ktp"`
}

func main() {
    route := echo.New()
    route.POST("user/create_user", func(c echo.Context) error {
        user := new(Users)
        c.Bind(user)
        contentType := c.Request().Header.Get("Content-type")
        if contentType == "application/json" {
            fmt.Println("Request dari json")
        } else if strings.Contains(contentType, "multipart/form-data") || contentType == "application/x-www-form-urlencoded" {
            file, err := c.FormFile("ktp")
            if err != nil {
                fmt.Println("Ktp kosong")
            } else {
                src, err := file.Open()
                if err != nil {
                    return err
                }
                defer src.Close()
                dst, err := os.Create(file.Filename)
                if err != nil {
                    return err
                }
                defer dst.Close()
                if _, err = io.Copy(dst, src); err != nil {
                    return err
                }

                user.Ktp = file.Filename
                fmt.Println("Ada file, akan disimpan")
            }
        }
        response := struct {
            Message string
            Data    Users
        }{
            Message: "Sukses melakukan penambahan data",
            Data:    *user,
        }
        return c.JSON(http.StatusOK, response)
    })

    route.PUT("user/update_user/:email", func(c echo.Context) error {
        user := new(Users)
        c.Bind(user)
        user.Email = c.Param("email")
        // do something here ....
        response := struct {
            Message string
            Data    Users
        }{
            Message: "Sukses mengupdate data",
            Data:    *user,
        }
        return c.JSON(http.StatusOK, response)
    })

    route.DELETE("user/delete_user/:email", func(c echo.Context) error {
        user := new(Users)
        user.Email = c.Param("email")
        // do something here ....
        response := struct {
            Message string
            ID      string
        }{
            Message: "Sukses menghapus data",
            ID:      user.Email,
        }
        return c.JSON(http.StatusOK, response)
    })

    route.GET("user/search_user", func(c echo.Context) error {
        user := new(Users)
        user.Email = c.QueryParam("keywords")
        user.Nama = "Abu Zubayr"
        user.ALamat = "Jalan Jalan"
        user.Ktp = "file.jpg"
        // do something here ....
        response := struct {
            Message string
            Data    Users
        }{
            Message: "Sukses melihat data",
            Data:    *user,
        }
        return c.JSON(http.StatusOK, response)
    })

    route.Start(":9000")
}

Untuk tutorial dasar Rest API di Golang Menggunakan Echo Framework cukup sampai disini. Untuk project ini sendiri juga sudah saya post di github bisa di cek di https://github.com/sardiabuzubayr/simple-echo-restapi.
Semoga bermanfaat, wassalamualaikum warahmatullah wabarakatuh
Share:

Cara Deploy Laravel, Codeigniter dan Framework PHP Lainnya di Docker

Cara Deploy Laravel, Codeigniter dan Framework PHP Lainnya di Docker
Bismillah…
Beberapa tahun belakangan kita tentu sering mendengar istilah docker dan kontainerisasi. Nah pada tulisan saya kali ini kita akan langsung mempraktekkan bagaimana cara men-deploy atau memasang website yang sebelumnya sudah kita buat kedalam sebuah container. Sebelum memulai, ada baiknya kita mengerti terlebih dahulu apa itu container dan apa itu docker.
  • Container
  • Container yang dimaksud disini merupakan wadah yang digunakan untuk menempatkan seluruh kebutuhan aplikasi baik itu web server, database ataupun kebutuhan lainnya yang dibutuhkan oleh aplikasi kita tadi supaya bisa berjalan layaknya di komputer lokal.

  • Docker
  • Docker merupakan salah satu platform yang bisa digunakan sebagai container/wadah untuk menempatkan seluruh kebutuhan software yang kita butuhkan. Docker seperti halnya sebuah VM yang berjalan di mesin virtual, hanya saja docker lebih ringan daripada VM yang membutuhkan resource lebih besar daripada docker.

    Dengan menggunakan docker, kita bebas memilih versi bahasa pemrograman, database, library dan software lainnya tanpa khawatir terjadi bentrok antara 1 aplikasi dengan aplikasi lainnya, karena docker bersifat isolate dimana konfigurasi sebuah project anda tidak akan mengganggu konfigurasi dan kebutuhan project yang lain.

    Misalnya saya memiliki 2 buah project, dimana project 1 menggunakan php versi 7.4 sedangkan project kedua menggunakan php versi 8.0 maka antara 2 project tersebut tidak mungkin terjadi bentok karena masing-masing project sudah memiliki container dan konfigurasi terisolasi masing-masing.

Nah, setelah mengetahui pengertian diatas, sekarang kita akan memulai untuk proses deploy. Disini saya akan men-deploy sebuah project aplikasi web dengan bahasa pemrograman php dimana aplikasi ini menggunakan nginx sebagai web server dan MySQL sebagai database. Kita akan lakukan konfigurasi di file tersendiri untuk masing-masing tools tersebut. Untuk php dan nginx disini saya menggunakan varian alpine linux, karena image docker dari alpine ini paling ringan dan paling kecil untuk ukuran filenya dibandingkan dengan image lainnya.

Berikut adalah langkah-langkah untuk melakukan deploy website ke docker :
  1. Didalam project website anda, buat sebuah direktori/folder bernama docker-config kemudian tambahkan lagi didalamnya direktori mysql, nginx dan php seperti berikut ini:
  2. Deploy php ke docker
  3. Didalam direktori mysql, buat sebuah direktori baru dengan nama db. Kemudian tempatkan di dalam direktori db ini database dari website yang anda buat sebelumnya.
  4. Selanjutnya beralih ke direktori nginx, buat sebuah file docker dengan nama web.dockerfile. Kemudian masukkan konfigurasi seperti dibawah ini didalam file tersebut :
  5. FROM nginx:1.21.4-alpine
    
    ADD ./docker-config/nginx/vhost.conf /etc/nginx/conf.d/default.conf
  6. Masih di direktori yang sama, tambahkan lagi sebuah file vhost.conf, dimana file ini berisi konfigurasi untuk nginx.
  7. server {
        listen 80;
        index index.php index.html;
        root /var/www/public/public;
    
        location / {
            try_files $uri /index.php?$args;
        }
    
        location ~ \.php$ {
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass app:9000;
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_path_info;
        }
    }
  8. Beralih ke direktori php yang sudah dibuat sebelumnya, buat sebuah file php.dockerfile, lalu masukkan konfigurasi seperti dibawah ini :
  9. FROM php:8.0.5-fpm-alpine
    
    RUN docker-php-ext-install mysqli pdo pdo_mysql && docker-php-ext-enable pdo_mysql
  10. Selanjutnya kembali ke direktori awal project. Lalu buat sebuah file docker-compose.yml. Didalam file inilah kita akan mendeklarasikan seluruh kebutuhan guna menjalankan website kita tadi.
  11. version: '3'
    services:
      web:
        build:
          context: ./
          dockerfile: ./docker-config/nginx/web.dockerfile 
        container_name: inventory-webserver
        volumes:
          - ./:/var/www/public
        ports:
          - "8080:80"
        networks:
          - app-network
      
      app:
        build:
          context: ./
          dockerfile: ./docker-config/php/php.dockerfile
        container_name: inventory
        volumes:
          - ./:/var/www/public
        networks:
          - app-network
        links:
          - database
        depends_on:
          - database
    
      database:
        image: mariadb
        container_name: inventory_database
        restart: unless-stopped
        tty: true
        ports:
          - "3307:3306"
        environment:
          MYSQL_DATABASE: inventory_sample
          MYSQL_ROOT_PASSWORD: 12345
          SERVICE_NAME: mysql
          SERVICE_TAGS: dev
        volumes:
          - dbdata:/var/lib/mysql/
          - ./docker-config/mysql/db:/docker-entrypoint-initdb.d
        networks:
          - app-network
    
    networks:
      app-network:
        driver: bridge
    volumes:
      dbdata:
        driver: local
        
  12. Setelah seluruh file tersebut dibuat, jalankan docker-compose di terminal/command line anda dengan perintah :
  13. docker-compose up
  14. Tunggu hingga proses selesai, dan jalankan website anda di http://localhost:8080
Demikianlah tutorial cara deploy laravel, codeigniter dan framework PHP lainnya di docker. Untuk project contoh bisa langsung dilihat di repository github saya di https://github.com/sardiabuzubayr/inventory_sample. Semoga bermanfaat, Wassalamualaikum warahmatullah wabarakaatuh.
Share:
DigitalOcean Referral Badge
www.domainesia.com
Powered by Blogger.