Aplikasi E-Commerce Laravel 6 #1: Schema Database

Aplikasi E-Commerce Laravel 6 #1: Schema Database

Pendahuluan

Beberapa waktu telah berlalu, sejak Laravel 6 release yang membuat banyak sekali pembaca Daengweb.id melayangkan request agar membahas versi terbaru ini. Seperti biasanya, membahas apa saja yang terbaru dari setiap versi, sudah sangat lazim dan banyak dibahas oleh teman-teman content creator lainnya.

Kami ingin tetap konsisten dengan "style" yang dibawa sejak pertama kali muncul yakni membahasnya dengan menggunakan study case. Lain sisi, masih ada tanggung jawab untuk menyelesaikan case yang sedang berjalan sehingga kami fokus untuk menyelesaikan case tersebut terlebih dahulu. Meskipun penutupnya agak dipaksakan karena masih ada beberapa materi yang belum dibahas, tapi it's okay karena bisa menjadi challenge bagi teman-teman untuk menambahkannya sendiri.

Kembali ketopik pembahasan dimana pada seri ini kita akan mengangkat case Aplikasi E-Commerce menggunakan Laravel 6. Materi ini murni menggunakan Laravel dan tidak akan dipadu-padankan dengan framework lainnya, misalnya Vue.js. Tujuannya adalah untuk membantu teman-teman yang sedang belajar Laravel dan tertatih-tatih belajarnya karena harus memahami Laravel & Vue.js dalam waktu bersamaan.

Baca Juga: Aplikasi Live Streaming Ceramah Menggunakan Flutter

Membuat Schema Database

Seperti biasanya, kita akan membuat gambaran awal yang akan dijadikan panduan dalam membuat aplikasi, yakni dengan membuat gambaran database-nya. Meskipun pada akhirnya, schema yang ada masih bersifat sementara dan masih akan mengalami perubahan seiiring berjalannya proses development.

laravel ecommerce - struktur database

Tahap pertama, kita install Laravel 6 terlebih dahulu dengan command:

composer create-project --prefer-dist laravel/laravel dw-ecommerce

Catatan: Pastikan web server kamu sudah sesuai server requirements dari Laravel.

Buka project Laravel-nya dan sesuaikan informasi database pada file .env, khususnya pada line dibawah

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=dw-ecommerce
DB_USERNAME=root
DB_PASSWORD=

Catatan: DB_PASSWORD di-isi jika database kamu dilindungi oleh password. Jika tidak, maka biarkan kosong.

Buka phpmyadmin atau apapun database management kamu, kemudian buat database baru sesuai nama database yang kamu masukkan pada bagian DB_DATABASE, dalam hal ini adalah dw-ecommerce.

Tahap selanjutnya adalah membuat schema database menggunakan salah satu fitur andalan dari Laravel, yakni Migrations. Dengan Migration memungkinkan kamu untuk membuat struktur database secara langsung melalui code, sehingga seluruh perubahan struktur akan terpantau oleh Migration. Apabila terjadi perpindahan perangkat atau bekerja secara tim, maka kamu tidak perlu mengirimkan struktur database secara manual karena akan secara otomatis berpindah ketika menjalankan fitur migrate.

Pada command line, jalankan command berikut satu persatu secara bergantian.

php artisan make:model Category -m
php artisan make:model Product -m
php artisan make:model Customer -m
php artisan make:model Province -m
php artisan make:model City -m
php artisan make:model District -m
php artisan make:model Order -m
php artisan make:model OrderDetail -m

Command diatas akan me-generate Model beserta Migration-nya dan semua file yang dihasilkan akan ditempatkan sesuai dengan folder-nya masing-masing. Adapun untuk model akan disimpan kedalam folder app, sedangkan migration akan disimpan kedalam folder database/migrations.

Lupakan sejenak persoalan Model, karena pada seri pertama ini kita tidak akan menggunakannya. Jika dilihat kedalam folder database/migrations maka kita akan menemukan semua file yang telah di-generate, dimana 3 file pertama adalah bawaan dari Laravel, sedangkan file selanjutnya adalah file Migration yang baru saja kita generate.

Setelah file migration-nya didapatkan, maka tugas kita selanjutnya adalah memasukkan code kedalam masing-masing file tersebut. Adapun 3 file pertama tidak akan kita ubah untuk saat ini, maka perubahan pertama akan dimulai dari file ke-4 dan seterusnya. Buka file xxxx_xx_xx_create_categories_table.php, kemudian modifikasi menjadi:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateCategoriesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
  
    //METHOD INI DIGUNAKAN KETIKA MIGRATE DIJALANKAN
    public function up()
    {
        //JADI KETIKA MIGRATE DIJALANKAN, KITA AKAN MEMBUAT TABLE BERNAMA categories
        Schema::create('categories', function (Blueprint $table) {
            //ADAPUN FIELDNYA ADALAH MASING-MASING DIBAWAH INI
            $table->bigIncrements('id');
            $table->string('name'); //STRING SAMA DENGAN VARCHAR
            
            //JADI KITA AKAN MEMBUAT CATEGORI INI MEMILIKI ANAK KATEGORI
            //SEHINGGA DIBUAT STRUKTUR DIMANA KATEGORI YANG MEMILIKI parent_id
            //ADALAH KATEGORI ANAK, SEBALIKNYA JIKA KATEGORI ITU parent_id NYA NULL
            //MAKA DIA ADALAH KATEGORI INDUK
            $table->unsignedBigInteger('parent_id')->nullable();
            $table->string('slug');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
  
    //SEDANGKAN METHOD INI DIGUNAKAN KETIKA ROLLBACK ATAU REFRESH DATABASE DIJALANKAN
    public function down()
    {
        Schema::dropIfExists('categories'); //BAGIAN INI KITA AKAN MENGHAPUS DATABASE DIATAS
        //INGAT FUNGSI INI HANYA AKAN BERJALAN KETIKA KITA MENJALANKAN FUNGSI ROLLBACK ATAU YANG SEJENISNYA
    }
}

Bagian selanjutnya adalah buka file xxxx_xx_create_products_table.php dan modifikasi code-nya menjadi.

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateProductsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        //JADI KITA AKAN MEMBUAT TABLE products
        Schema::create('products', function (Blueprint $table) {
            //DENGAN FIELD DIBAWAH INI
            $table->bigIncrements('id');
            $table->string('name');
            $table->string('slug');
          
            //ADAPUN category_id NYA NNTI AKAN MERUJUK KE TABLE categories
            //DIMANA UNTUK SAAT INI BELUM AKAN DIBAHAS RELASI ANTAR TABLE-NYA
            $table->unsignedBigInteger('category_id');
            $table->text('description')->nullable();
            $table->string('image');
            $table->integer('price');
            $table->integer('weight');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('products');
    }
}

Setelah table products selesai, maka bagian selanjutnya adalah table customers. Buka file xxxx_xx_create_customers_table.php dan tambahkan code.

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateCustomersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        //BUAT TABLE customers
        Schema::create('customers', function (Blueprint $table) {
            //DENGAN FIELD SEBAGAI BERIKUT
            $table->bigIncrements('id');
            $table->string('name');
            $table->string('email')->unique(); //FIELD INI DIBUAT UNIK UNTUK MENGHINDARI DUPLIKAT DATA
            $table->string('phone_number');
            $table->string('address');
            $table->unsignedBigInteger('district_id'); //FIELD INI AKAN MERUJUK PADA TABLE districts NANTINYA UNTUK MENGAMBIL DATA KOTA CUSTOMER
            $table->boolean('status')->default(false); //TIPENYA BOOLEAN, DENGAN NILAI DEFAULT ADALAH FALSE
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('customers');
    }
}

Adapun 3 table selanjutnya adalah table yang akan mengurusi data wilayah. Pertama adalah data provinces, buka file xxxx_xx_xx_create_provinces_table.php dan modifikasi menjadi

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateProvincesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
      //BUAT TABLE provinces 
        Schema::create('provinces', function (Blueprint $table) {
            //YANG AKAN BERISI LIST DATA NAMA PROPINSI
            $table->bigIncrements('id');
            $table->string('name');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('provinces');
    }
}

Table selanjutnya akan meng-handle data kota atau kabupaten. Buka file xxxx_xx_xx_create_cities_table.php dan modifikasi menjadi

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateCitiesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        //BUAT TABLE cities
        Schema::create('cities', function (Blueprint $table) {
            //DENGAN FIELD DIBAWAH INI
            $table->bigIncrements('id');
            $table->unsignedBigInteger('province_id'); //FIELD INI AKAN MERUJUK KE TABLE provinces
            $table->string('name');
            $table->string('type');
            $table->string('postal_code');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('cities');
    }
}

Table terakhir yang akan meng-handle data wilayah adalah table districts, dimana table ini akan berisi data kecamatan. Buka file xxxx_xx_xx_create_districts_table.php

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateDistrictsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        //BUAT TABLE districts
        Schema::create('districts', function (Blueprint $table) {
            //DENGAN FIELD DIBAWAH INI
            $table->bigIncrements('id');
            $table->unsignedBigInteger('province_id'); //FIELD INI AKAN MERUJUK KE TABLE PROVINCES
            $table->unsignedBigInteger('city_id'); // FIELD INI AKAN MERUJUK KE TABLE CITIES
            $table->string('name');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('districts');
    }
}

Dua bagian terakhir adalah table orders dan order_details dimana kedua table ini akan menyimpan informasi terkait pesanan dan detail pesanan setiap pelanggan nantinya. Pertama, buka file xxxx_xx_xx_create_orders_table.php dan modifikasi menjadi

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateOrdersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
      //BUAT FILE orders
        Schema::create('orders', function (Blueprint $table) {
            //DAN FIELDNYA ADALAH DIBAWAH INI
          
            $table->bigIncrements('id');
            $table->string('invoice')->unique();
            $table->string('customer_id');
          
            //BAGIAN INI MUNGKIN ADA YANG BERTANYA, KOK INFO INI DISIMPAN LAGI?
            //SEDANGKAN SUDAH ADA RELASI KE TABLE CUSTOMERS
            //HAL INI DILAKUKAN, JIKA SUATU SAAT CUSTOMER MENGUBAH PROFILENYA
            //SEHINGGA DATA ORDER TIDAK IKUT BERUBAH, JADI PERLU DISIMPAN INFONYA
            //KETIKA ORDER ITU DIBUAT SEBAGAI SALINAN INFORMASI
            $table->string('customer_name');
            $table->string('customer_phone');
            $table->string('customer_address');
            $table->unsignedBigInteger('district_id'); //FIELD INI AKAN MERUJUK KE TABLE districts
            $table->integer('subtotal');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('orders');
    }
}

Dan bagian terakhir adalah detail_orders, buka file xxxx_xx_xx_create_order_details_table.php

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateOrderDetailsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        //AKAN MEMBUAT TBALE order_details
        Schema::create('order_details', function (Blueprint $table) {
            //DENGAN FIELD DIBAWAH INI
            $table->bigIncrements('id');
            $table->unsignedBigInteger('order_id'); //FIELD INI AKAN MERUJUK KE TABLE orders
            $table->unsignedBigInteger('product_id'); //FIELD INI AKAN MERUJUK KE TABLE products
            $table->integer('price'); //INI SAMA DENGAN CUSTOMER, INFORMASI HARGA SAAT BARANG INI DIPESAN JUGA DIBUAT SALINNANNYA
            $table->integer('qty');
            $table->integer('weight'); //JUGA BERLAKU DENGAN BERAT BARANG, UNTUK MENGHINDARI PERUBAHAN DATA PRODUK
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('order_details');
    }
}

Import Data Wilayah

Pendekatan yang akan digunakan untuk memasukkan data wilayah adalah dengan memanfaatkan fitur Laravel lainnya, yakni Seeder. Jadi Seeder ini bisa kita gunakan untuk menyimpan static data dimana data tersebut dapat dieksekusi untuk dimasukkan kedalam database. Biasanya Seeder digunakan dalam proses development adalah untuk menyimpan data dummy, sehingga developer bisa memasukkan data tersebut saat dibutuhkan secara berulang kali.

Pada command line, jalankan command berikut satu persatu secara bergantian untuk membuat Seeder.

php artisan make:seeder ProvinceTableSeeder
php artisan make:seeder CityTableSeeder
php artisan make:seeder DistrictTableSeeder

Adapun hasil generate dari ketiga command diatas akan disimpan ke dalam folder database/seeds. 3 buah file yang dihasilkan akan kita isi dengan query data wilayah. Pertama, buka file ProvinceTableSeeder.php dan modifikasi menjadi

<?php

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;

class ProvinceTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
      //JADI KITA MENGGUNAKAN QUERY BUILDER UNTUK MENJALANKAN QUERY YANG SUDAH ADA
      //DIMANA QUERY BUILDER ADALAH SALAH SATU FITUR YANG ADA DILARAVEL UNTUK BERINTERAKSI DENGAN DATABASE
      //ADAPUN QUERYNYA ADALAH SALINAN DARI PROJECT SAYA YANG LAINNYA
        DB::insert("INSERT INTO `provinces` (`id`, `name`, `created_at`, `updated_at`) VALUES
        (1, 'Bali', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (2, 'Bangka Belitung', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (3, 'Banten', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (4, 'Bengkulu', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (5, 'DI Yogyakarta', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (6, 'DKI Jakarta', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (7, 'Gorontalo', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (8, 'Jambi', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (9, 'Jawa Barat', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (10, 'Jawa Tengah', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (11, 'Jawa Timur', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (12, 'Kalimantan Barat', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (13, 'Kalimantan Selatan', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (14, 'Kalimantan Tengah', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (15, 'Kalimantan Timur', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (16, 'Kalimantan Utara', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (17, 'Kepulauan Riau', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (18, 'Lampung', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (19, 'Maluku', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (20, 'Maluku Utara', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (21, 'Nanggroe Aceh Darussalam (NAD)', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (22, 'Nusa Tenggara Barat (NTB)', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (23, 'Nusa Tenggara Timur (NTT)', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (24, 'Papua', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (25, 'Papua Barat', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (26, 'Riau', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (27, 'Sulawesi Barat', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (28, 'Sulawesi Selatan', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (29, 'Sulawesi Tengah', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (30, 'Sulawesi Tenggara', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (31, 'Sulawesi Utara', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (32, 'Sumatera Barat', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (33, 'Sumatera Selatan', '2019-08-29 12:55:52', '2019-08-29 12:55:52'),
        (34, 'Sumatera Utara', '2019-08-29 12:55:52', '2019-08-29 12:55:52');");
        
    }
}

Sedangkan dua file lainnya bisa kamu lihat Github: CityTableSeeder & DistrictTableSeeder (red: Karena kedua file ini code-nya sangat banyak).

Setelah ketiga bagian tersebut selesai, maka tugas selanjutnya adalah mendaftarkan ketiga class tersebut kedalam file DatabaseSeeder.php, buka file tersebut dan modifikasi menjadi.

<?php

use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call(ProvinceTableSeeder::class);
        $this->call(CityTableSeeder::class);
        $this->call(DistrictTableSeeder::class);
    }
}

Untuk menjalankan Seeder diatas bisa dengan command php artisan db:seed. Kemudian cek table provinces, cities dan table districts, pastikan datanya sudah ada didalam masing-masing table tersebut.

Baca Juga: Aplikasi Laudry Laravel 5.8 & Vue.js #14: Chart & Laporan

Kesimpulan

Belajar setiap seri Laravel tidak jauh berbeda jika seri tersebut tidak mengalami perubahan yang cukup derastis, utamanya dalam hal direktori. Seri Laravel 5 hingga ke-6 ini secara umum direktorinya sama, hanya bagian bagian kecil saja yang mengalami perubahan struktur sehingga tidak mengubah banyak terkait cara penggunaannya.

Sebisa mungkin dalam serial ini kita akan memasukkan apa saja yang baru dari Laravel tapi sambil menyelesaikan case yang sedang berjalan. So, bagi kamu yang ingin mengikuti serial ini, bisa memantau repositori di Github untuk setiap perubahan code yang terjadi.

Category:
Share:

Comments