Modul-Web Programming II New
Modul-Web Programming II New
MODUL
PROGRAMMING II
Segala puji dan syukur kami panjatkan ke hadirat Tuhan Yang Maha Esa, karena berkat rahmat-
Nya penulisan modul Mata Kuliah Web Programming II ini dapat terselesaikan dengan baik.
Modul ini disusun untuk memenuhi kebutuhan mahasiswa dalam mata kuliah Web
Programming II, yang disajikan dalam bentuk praktikum dan diharapkan dapat membekali
mahasiswa dalam memahami pembuatan web menggunakan Framework Laravel.
Modul Web Programming II ini membahas materi yang dibatasi hingga pembuatan halaman
Administrator (Back-End). Di akhir perkuliahan, mahasiswa diharapkan mampu
mengimplementasikan materi yang telah dipelajari dalam bentuk final project yang harus
dipresentasikan sebagai syarat kelulusan mata kuliah Web Programming II. Teknik penyajian
dalam modul ini dilakukan secara terpadu dan sistematis.
Kami menyadari bahwa modul ini masih memiliki banyak kekurangan. Oleh karena itu, kami
dengan lapang dada menerima segala masukan dan kritik yang konstruktif dari berbagai pihak
demi kesempurnaan modul ini di masa yang akan datang. Semoga modul ini dapat bermanfaat
bagi para pembaca.
Tim Penulis
DAFTAR ISI
COVER.................................................................................................................................................. i
KATA PENGANTAR .......................................................................................................................... ii
DAFTAR ISI ........................................................................................................................................iii
Minggu Ke-1 Instalasi & Konfigurasi Pada Laravel ............................................................................ 1
Minggu Ke-2 Mengenal Controller, Function, Route & View ............................................................ 18
Minggu Ke-3 Manajemen Basis Data: Konfigurasi Databases, Migration, dan Seeders ..................... 24
Minggu Ke-4 CRUD (Create, Read, Update, Delete) ......................................................................... 31
Minggu Ke-5 Authenticate (Logika Login) & Pengujian Unit ............................................................ 41
Minggu Ke-6 Template HTML, CSS, Bootstrap, dan JavaScript ....................................................... 55
Minggu Ke-7 Implementasi DataTable dan Form dengan Template................................................... 78
Minggu Ke-9 Manajemen Data Master ............................................................................................. 114
Minggu Ke-10 Data Join Tabel Part 1 .............................................................................................. 126
Minggu Ke-11 Data Join Tabel Part 2 .............................................................................................. 142
Minggu Ke-12 Laporan Data Master ................................................................................................ 168
Minggu Ke-13 Persentasi Tugas Kelompok...................................................................................... 193
Minggu Ke-14 Persentasi Tugas Kelompok...................................................................................... 194
Minggu Ke-15 Persentasi Tugas Kelompok...................................................................................... 195
Minggu Ke-1
Instalasi & Konfigurasi Pada Laravel
Laravel adalah salah satu framework PHP yang paling populer dan banyak digunakan untuk
pengembangan aplikasi web. Diciptakan oleh Taylor Otwell, Laravel dirancang untuk
membuat pengembangan web menjadi lebih mudah dan lebih cepat dengan menyediakan
berbagai alat dan fitur bawaan.
Fitur Utama Laravel:
1. Eloquent ORM: Laravel memiliki Object-Relational Mapping (ORM) yang sangat kuat
bernama Eloquent. Ini memungkinkan pengembang untuk berinteraksi dengan basis data
menggunakan model dan relasi, serta menyediakan metode yang mudah digunakan untuk
melakukan operasi CRUD.
2. Blade Templating Engine: Laravel memiliki sistem template yang disebut Blade. Blade
menggunakan kode PHP di dalam template dengan sintaks yang sederhana dan rapi, serta
mendukung pewarisan template dan komponen.
3. Routing: Laravel menyediakan sistem routing yang fleksibel dan mudah digunakan. Kita
dapat menentukan rute untuk aplikasi dengan cara yang sangat sederhana dan membaca
URL.
4. Middleware: Middleware di Laravel memungkinkan memfilter permintaan HTTP yang
masuk ke aplikasi. Ini sangat berguna untuk memeriksa autentikasi, logging, dan berbagai
kebutuhan lainnya.
5. Artisan CLI: Laravel menyediakan alat baris perintah yang kuat bernama Artisan. Artisan
membantu dengan berbagai tugas pengembangan seperti pembuatan model, migrasi, dan
kontroler, serta memungkinkan untuk membuat perintah kustom.
6. Migration dan Seeding: Laravel menyediakan sistem migrasi basis data yang dapat
melacak dan mengelola perubahan skema basis data dengan mudah. Seeding dapat mengisi
basis data dengan data dummy untuk pengujian.
7. Autentikasi dan Otentikasi: Laravel menyediakan sistem autentikasi dan otorisasi
bawaan yang memudahkan pengembang untuk menyiapkan login, registrasi, dan kontrol
akses pengguna.
8. Event Broadcasting: Laravel memungkinkan untuk menyiarkan event aplikasi ke klien
waktu nyata menggunakan WebSocket dengan driver seperti Pusher dan Redis.
9. Testing: Laravel dibangun dengan testing dalam pikiran dan mendukung PHPUnit secara
bawaan. Ini memungkinkan kita dapat menulis tes unit dan fitur untuk aplikasi.
Sertifikasi Kompetensi adalah proses pengakuan formal yang diberikan kepada individu yang
telah menunjukkan kemampuan, pengetahuan, dan keterampilan dalam bidang tertentu sesuai
dengan standar yang ditetapkan. Sertifikasi ini biasanya diberikan oleh lembaga atau badan
sertifikasi yang diakui secara nasional atau internasional. Salah satu manfaat sertifikasi
kompetensi bagi Developer memberikan pengakuan resmi terhadap keahlian dan pengetahuan
WEB PROGRAMMING II 1
teknis seorang developer, yang dapat meningkatkan kredibilitas mereka di mata perusahaan
atau klien.
Sertifikasi kompetensi diselenggarakan oleh Lembaga Sertifikasi (LSP) yang telah mendapat
lisensi dari Badan Nasional Sertifikasi Profesi (BNSP), seperti LSP Universitas Bina Sarana
Informatika. Berikut adalah salah satu skema yaitu skema programmer pada tabel 1.1 &
skema Analis Program pada tabel 1.2
Tabel I. 1
Skema Programmer
No Kode Unit Judul Unit Jenis Standar (Standar
Khusus/Standar
Internasional/SKKNI)
Tabel I. 2
Skema Analis Program
No Kode Unit Judul Unit Jenis Standar (Standar
Khusus/Standar
Internasional/SKKNI)
WEB PROGRAMMING II 2
8. J.620100.033.02 Melaksanakan pengujian unit program SKKNI
Keunggunalan lain dengan kita menggunakan Framework Laravel pada situs resmi Laravel
https://laravel.com/docs/10.x kita sudah dapat memenuhi salah satu unit pada Skema
Programmer (contoh lengkap pengerjaan Unit Kerja Programmer dapat dilihat di
https://bit.ly/LaravelWebPro2 yakni Menulis Kode Dengan Prinsip Sesuai Guidelines dan
Best Practice, sehingga kita dapat merujuk ke dokuemtasi
Gambar I. 1
Download Laragon
3. Setelah download selesai, buka folder di mana file Laragon disimpan. Double klik file
laragon-wamp.exe pada installer yang telah anda download, kemudian pilih bahasa jika
sudah klik OK seperti pada gambar I.2.
Gambar I. 2
Pilih Bahasa Pada saat Install
WEB PROGRAMMING II 3
3. Kemudian pilih direktori penyimpanan seperti pada gambar I.3
Gambar I. 3
Pilih Lokasi Direktori
4. Centang beberapa “option” sesuai kebutuhan seperti pada gambar I.4, lalu Klik Next.
Kemudian muncul konfirmasi untuk instal klik Install seperti gambar I.5 dan tunggu hingga
proses install selesai.
Gambar I. 4
Centang Option Sesuai Kebutuhan
WEB PROGRAMMING II 4
Gambar I. 5
Konfirmasi Insatall
5. Jika sudah berhasil berikut maka tampil seperti gambar I.6 pada Menu kita dapat memilih
versi laragon sesaui dengan kebutuhan((jika instalasi awal hanya memiliki satu versi PHP
bawaan dari Laragon) & untuk menambahkan versi PHP bisa klik How to add another PHP
version atau mengunjungi https://www.php.net/downloads.php atau bisa mengakses versi
sebelumnya https://windows.php.net/downloads/releases/archives/. Setelah berhasil download
versi PHP yang digunakan simpan pada direktori c:\laragon\bin\php seperti pada gambar I.7
jika hasil download dalam bentuk kompresi, pastikan telah mengekstraknya. Dan untuk
mengaktifkan menjalankan laragon klik Start All
Gambar I. 6
Version Laragon
WEB PROGRAMMING II 5
Gambar I. 7
Menambahan versi PHP Pada Laragon
Gambar I. 8
phpMyAdmin Belum Tersedia Pada Laragon
Gambar I. 9
Menambahkan phpMyAdmin Pada Laragon
WEB PROGRAMMING II 6
2
1
Gambar I. 10
Halaman Utama phpMyAdmin
1.2. Instalasi Composer Pada Laragon
1. Untuk mendapatkan composer-setup.exe dapat didownload pada situs resmi
https://getcomposer.org/download/ seperti pada gambar I.11 atau
https://bit.ly/LaravelWebPro2
Gambar I. 11
Download Composer
WEB PROGRAMMING II 7
2. Double klik file .exe kemudian pilih model instal apakah untuk semua user atau tidak seperti
pada gambar I.12, kemudian Next seperti pada gambar GI.13
Gambar I. 12
Pilih Mode Install
Gambar I. 13
Installation type
3. Pilih direktori penyimpanan laragon seperti pada gambar I.14 kemudian kemudian pilih
Next, berikutnya tampil pilihan untuk memilih php.exe seperti pada gambar I.15, misalnya
pada php-8.1.10-Win32-vs16-x64 maka direktori pada C:\laragon\bin\php\php-8.1.10-Win32-
vs16-x64 jika kita memiliki lebih dari satu PHP pada laragon maka lakukan langkah nomor 1
sampe nomor 3 ini untuk setiap versi PHP dengan php.exe berikutnya hingga instalasi selesai
WEB PROGRAMMING II 8
Gambar I. 14
Direktori Laragon
Gambar I. 15
Pilih PHP.exe
WEB PROGRAMMING II 9
4. Pada halaman ini proxy settings pilih Next seperti pada gambar I.16. Kemudian pada gambar
I.17 klik install untuk memulai proses install dan tunggu hingga proses install hingga selesai
Gambar I. 16
Proxy Settings
Gambar I. 17
Memulai Istall
WEB PROGRAMMING II 10
5. Untuk memastikan bahwa insatalasi berhasil dilakukkan maka, buka Command Prompt
atau tekan tombol Windows + R dan ketikkan cmd. Kita dapat melihat versi composer yang
kita gunakan dengan cara mengetikkan composer -V sedangkan versi php php -v seperti pada
gambar I.18
Gambar I. 18
Melihat Versi Composer atau PHP Pada Command Prompt
1.3. Konfigurasi environment
1. Langkah ini hanya dilakukakan jika versi PHP lebih dari satu pada Windows 11 seperti pada
Gambar I.6 dimana yang diaktifkan PHP 8.1 tetapi yang terbaca PHP 8.2 dan kita
menginginkan versi PHP 8.1. Untuk mengatur ini pada start lakukan pencarian kemudian cari
environment kemudian pilih Environment Variables
Gambar I. 19
Environment Pada Windows 11
2. Pada Environment Variables, pilih Path (langkah nomor 1). Maka akan muncul jendela Edit
Environment Variable. Klik tombol New (langkah nomor 2), kemudian ketikkan direktori
PHP yang akan digunakan. Klik tombol New lagi jika ingin menambahkan versi PHP lainnya.
Agar PHP yang terbaca sesuai dengan keinginan kita, pastikan posisi direktori PHP yang
WEB PROGRAMMING II 11
diinginkan berada di bagian teratas. Kita dapat menggeser posisi direktori ke atas atau ke bawah
(langkah nomor 3) untuk mengatur prioritas PHP yang dipilih.
Gambar I. 20
Edit Environment Variable
3. Setelah melakukan konfigurasi Environment Variable, pastikan untuk membuka jendela
Command Prompt yang baru. Jangan mengecek versi PHP menggunakan Command
Prompt yang sudah dibuka sebelum konfigurasi Environment Variable. Command Prompt
tidak memiliki sistem refresh, jadi pastikan Anda menggunakan jendela Command Prompt
yang terbaru. Kemudian, ketik kembali php -v untuk memeriksa versi PHP.
Gambar I. 21
Command Prompt setalah konfigurasi Environment Variable
4. Kemudian, versi PHP apa yang dibutuhkan oleh Laravel? Jika kita cek di dokumentasi
Laravel, versi 10 membutuhkan PHP versi >=8.1.
Gambar I. 22
Dokumentasi versi PHP Pada Laravel 10
WEB PROGRAMMING II 12
1.4. Konfigurasi Laravel
1. Pada gambar I.23 bagamana cara mendownload Project baru pada Laravel 10 dengan
composer dengan tautan https://laravel.com/docs/10.x
composer create-project laravel/laravel:^10.0 example-app
Gambar I. 23
Membuat Project Baru Pada Laravel 10
2. Untuk memulai download Project baru pada Laravel 10 menggunakan Composer kita bisa
membukan Command Prompt dengan kombinasi keyboard Windows+R kemudian ketikan
cmd atau bisa menggunakan Git Bash atau Terminal (Linux/Mac) atau Terminal yang disedian
oleh Laragon, dimana Project akan kita simpan pada direktori C:\Laravel10 sehingga pada
Terminal akan terlihat sebagai berikut:
a. Membuat folder Laravel10 pada localdisk C dan buka direktori C:\Laravel10 ikuti langkah
dibawah ini
Gambar I. 24
Membuat Folder Dan Masuk Folder Pada Command Prompt
2. Copy composer create-project laravel/laravel:^10.0 example-app kemudian paste pada
Command Prompt dan ganti example-app misalnya menjadi new-project-laravel10,
kemudian tekan enter pada keyboard untuk proses download Project Laravel dan pastikan PC
terkoneksi dengan internet seperti pada gambar I.25
WEB PROGRAMMING II 13
Gambar I. 25
Proses Download Project Baru
Jika proses download berhasil ada pesan successfully pada gambar I.26
Gambar I. 26
Project Baru Berhasil di Download
3. Ganti Project new-project-laravel10 menjadi PerdanaLaravel. Kali ini, kita akan buka
direktori C:\Laravel10\PerdanaLaravel, dengan cara di drag ke Command Prompt. Pada
Command Prompt atau Terminal ketikan cd kemudian drag folder PerdanaLaravel
(langkah nomor 1) ke terminal (langkah nomor 2), jika direktori sesuai akan tampil pada
Terminal cd /c/Laravel10/PerdanaLaravel, untuk melanjukan tekan Enter seperti pada
gambar I.27 & berikutnya ketikkan perintah untuk menjalankan Project pada terminal
php artisan serve
WEB PROGRAMMING II 14
2
d
/
c
/
L 1
a d
r
Gambar I. 27 /
a
Menjalankan Project Laravelc
v /
e
4. Pada browser dengan mengetikkan alamat http://localhost:8000
L seperti pada gambar I.28
http://localhost:8000 l a
1 r
0 a
/ v
P e
e l
r 1
d 0
a /
n P
a e
L r
a d
r a
a n
v a
e L
l a
Gambar I. 28 r
a
Melihat Hasil Project Pada browser
v
e
5. Sedangkan untuk menghentikan Project yang sedang berjalan dengan cara pada keyboard
kombinasi Ctrl+C l
Gambar I. 29
Service Dalam Keadaan Berhenti
WEB PROGRAMMING II 15
Gambar I. 30
Menjalankan program melalui Terminal VSC
Untuk menjalan perintah artisan kita bisa menggunakan terminal Visual Studio Code (VSC)
pertama buka project dengan cara File -> Open Folder yakni pada direktori C:/Laravel10/
PerdanaLaravel, kemudian buka Terminal dengan cara Terminal->New Terminal dan pada
terminal ketikan perinah Artisan seperti pada gambar I.30, atau menggunakan git best seperti
pada gambar I.31
Gambar I. 31
Menjalankan program melalui Terminal Git Bash
6. untuk mengetahui versi laravel yang kita gunakan dengan mengetikan perintah pada terminal
php artisan --version seperti pada gambar 1.6 dan pastikan pengecekan sudah sesuai dengan
direktori Project laravel yang akan kita lihat. Saat pembuatan modul ini versi yang digunakan
Laravel Framework 10.48.16
Gambar I. 32
Melihat Versi Project Laravel Yang Digunakan
WEB PROGRAMMING II 16
Latihan Mandiri 1:
Portofolio sertifikasi kompetensi, Impentasikan Unit Kompetensi Software Development pada
Mengimplementasikan Pemrograman Terstruktur. Studi kasus dapat diambil dari Project
kelompok semester sebelumnya dimana tugas yang memiliki laporan lengkap. Misalnya
Project kelompok, pada Web Programming I (WP1) Semester 2 atau Dasar Pemrograman
(Python) Semester 1. Dengan memenuhi kriteria sebagai berikut:
• Tampilkan input dan output pada Project.
• Ketentuan nama variabel, seperti pembuatan nama variabel dan ketentuan saat
pembuatan variabel.
• Operator yang digunakan.
• Percabangan.
• Perulangan.
• Penggunaan function.
• Array.
• Library.
• Membuat dokumentasi script.
WEB PROGRAMMING II 17
Minggu Ke-2
Mengenal Controller, Function, Route & View
Controller adalah kelas yang mengatur logika aplikasi yang bertanggung jawab untuk
menerima input dari pengguna, memprosesnya, dan mengembalikan respons yang sesuai.
Dengan fungsi utama dari pada controller untuk menghubungkan model (yang mewakili data)
dengan tampilan (views) yang menampilkan informasi kepada pengguna dan mengelola logika
atau untuk dikirimkan kembali ke pengguna atau tampilan yang sesuai. Sedangkan Route
adalah mekanisme yang menentukan bagaimana URL atau rute tertentu dalam aplikasi web
akan diproses. Route menghubungkan URL yang diminta oleh pengguna dengan function atau
Controller yang akan menanganinya.
Gambar II. 1
Membuka Project Pada Visual Studio Code
3. Namun pada modul ini penulis untuk menjalan perinta menggunakan terminal pada Git
Bash misal saya gunakan 2 terminal, dengan demikan tidak memberatkan Visual Studio Code
serta lembar kerja lebih luas. [1] Terminal untuk menjalankan program php artisan serve [2]
menjalankan perintah-perintah artisan terlihat pada gambar II.2
WEB PROGRAMMING II 18
1
d
2
d
Gambar II. 2
Membukan 2 Terminal
Gambar II. 3
Membuat Controller
Gambar II. 4
Direktori Controller
WEB PROGRAMMING II 19
use Illuminate\Http\Request;
Route::get('/', function () {
return view('welcome');
});
Gambar II. 5
Mengenal Route
2. Dengan demikan kita dapat melihat hasilnya pada browser dengan mengetikkan alamat
http://localhost:8000/helloworld seperti pada gambar II.6
Gambar II. 6
Melihat Hasil Helloword
WEB PROGRAMMING II 20
2.5. Membuat Views
1. Kali ini kita akan memanggil file pada direktori views, Pertama kita tambahkan function
ambilFile()
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
2. Maka pada direktori views kita tambahkan file dengan cara klik kanan pada resources/views
pilih New File kemudian beri nama file ambilfile.blade.php. Tambahkan script html yang
terlihat pada gambar II.7
Gambar II. 7
Menambahkan File pada Views
Route::get('/', function () {
return view('welcome');
});
WEB PROGRAMMING II 21
Route::get('helloworld', [HelloWorldController::class, 'index']);
Route::get('ambilfile', [HelloWorldController::class, 'ambilFile']);
4. Kali ini, kita akan membuat controller baru dengan nama HtmlController. Kita juga akan
membuat struktur folder yang lebih rapi, misalnya dengan menempatkan view dalam folder
v_html. Dengan demikian, semua file view yang berhubungan dengan HelloWorldController
akan berada dalam folder v_html. Script HelloWorldController sebagai berikut:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
Dengan baris script seperti ini return view('v_html.getlorem'); artinya kita diminta untuk
membuat folder v_html dengan file getlorem.blade.php pada resources/views seperti pada
gambar II.8
Gambar II. 8
Menambahkan Folder pada Views
5. Pada routes\web.php kita tambahkan script sebagai berikut:
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\HelloWorldController;
use App\Http\Controllers\HtmlController;
Route::get('/', function () {
return view('welcome');
});
6. Dengan demikan kita pada melihat hasilnya pada browser dengan mengetikkan alamat
http://localhost:8000/getlorem seperti pada gambar II.9
WEB PROGRAMMING II 22
Gambar II. 9
Mengenal View getlorem Pada browser
Studi Kasus:
Buat Contoller baru dengan nama LatihanController. Pada LatihanController terdapat 2
function :
1. Function getTabel, menampilkan disain tabel dengan tampilan sebagai berikut:
Latihan Mandiri 2:
Portofolio sertifikasi kompetensi, Impentasikan Unit Kompetensi Software Development pada
Menulis Kode Dengan Prinsip Sesuai Guidelines dan Best Practice. Dengan minimal
memenuhi kriteria berikut:
• Instalasi Project
• Menjalankan Program.
• Route.
• Contoller.
WEB PROGRAMMING II 23
Minggu Ke-3
Manajemen Basis Data: Konfigurasi Databases, Migration, dan Seeders
Salah satu Fitur Utama Laravel yakni Migration dan Seeding Laravel menyediakan sistem
migrasi basis data yang memungkinkan kita dapat melacak dan mengelola perubahan skema
basis data dengan mudah. Seeding dapat mengisi basis data dengan data dummy untuk
pengujian.
Gambar III. 1
Membuat Database
3.2. Konfigurasi Database
Selanjutnya, buka Project BelajarCRUD dan sesuaikan konfigurasi database pada file .env
dengan server yang kita gunakan seperti pada gambar III.2, Jika menggunakan Laragon,
konfigurasi sebagai berikut:
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=db_crud
DB_USERNAME=root
DB_PASSWORD= # isi jika password tersedia
Gambar III. 2
Konfigurasi Database
WEB PROGRAMMING II 24
3.3. Migration
1. Membuat migration, pada terminal ketikan perintah berikut, seperti pada gambar III.3
php artisan make:migration create_anggota_table
Gambar III. 3
Membuat Migration
2. Rancangan tabel yang digunakan dapat dilihat pada Tabel III.1. Selanjutnya, buka blueprint
tabel anggota seperti yang ditunjukkan pada Gambar III.4, yang terdapat pada direktori
database/migrations. Tambahkan script berikut:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
Tabel III. 1
Tabel Anggota
Fild Tipe Data Keterangan
id Bigint Primary Key
nama Varchar(255)
hp Varchar(13)
created_at Timestamp
updated_at Timestamp
WEB PROGRAMMING II 25
Gambar III. 4
Blueprint Table
3. Untuk menjalankan migrations pada terminal sebagai berikut, seperti pada gambar III.5
php artisan migrate
atau
php artisan migrate:fresh
Kapan Menggunakan:
• php artisan migrate digunakan saat hanya ingin menjalankan migration baru tanpa
mengganggu data yang sudah ada.
• php artisan migrate:fresh digunakan saat mengembangkan aplikasi dan perlu mengatur
ulang database untuk memastikan semua migration berfungsi dengan benar atau ketika
kita ingin memulai kembali dengan database kosong.
Gambar III. 5
Menjalankan Migrations
4. Maka pada saat kita cek di Apache terdapat beberapa tabel lainya yang dimana bawaan dari
laravel & terdapat tabel anggota sesuai dengan rancangan yang kita rancanng gambar III.4,
berikut tampilan Structure table anggota seperti terlihat pada gambar III.6
WEB PROGRAMMING II 26
Gambar III. 6
Structure Table
3.4. Seeders
Seeders dalam Laravel digunakan untuk mengisi database dengan data awal dengan tujuan
mempermudah pembuatan data ini secara otomatis. Pada saat ingin menjalankan seeders maka
kita harus menyiapkan Model terlebih dulu.
Gambar III. 7
Membuat Model
2. Model dapat kita buka pada direktori app/Models/anggota.php seperti pada gambar III.8 &
ubah script model Anggota sebagai berikut:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
• Gunakan $fillable jika kita ingin secara eksplisit mengizinkan atribut tertentu untuk
diisi. dengan fillable, semua atribut yang ingin diizinkan harus disebutkan satu per satu.
• Gunakan $guarded sebagai kebalikan dari fillable. Dalam guarded, hanya atribut yang
disebutkan yang tidak dapat diisi, sedangkan semua atribut lainnya dapat diisi.
WEB PROGRAMMING II 27
Gambar III. 8
Model Angggota
3. Buka file DatabaseSeeder.php pada direktori database/seeders seperti pada gambar III.9
& ubah script DatabaseSeeder.php sebagai berikut:
<?php
namespace Database\Seeders;
use Illuminate\Database\Seeder;
use App\Models\Anggota;
WEB PROGRAMMING II 28
Gambar III. 9
DatabaseSeeder
4. Untuk menjalankan seeders pada terminal seperti terlihat pada gambar III.10:
php artisan migrate:fresh --seed
Gambar III. 10
Menjalankan seeders
WEB PROGRAMMING II 29
5. Sehingga record terisi seperti terlihat pada gambar 3.11
Gambar III. 11
Record Terisi Melalui seeders
Latihan Mandiri 3:
Portofolio sertifikasi kompetensi, Impentasikan Unit Kompetensi Software Development pada
Menerapkan Akses Basis Data, dengan minimal memenuhi kriteria berikut. Tugas dikirim di
LSM MyBest:
• server yang digunakan
• Konfigurasi Database.
WEB PROGRAMMING II 30
Minggu Ke-4
CRUD (Create, Read, Update, Delete)
MVC (Model, View, Controller) adalah pendekatan perangkat lunak yang memisahkan logika
aplikasi dari presentasinya. Pendekatan ini membagi aplikasi menjadi beberapa komponen,
seperti manipulasi data, controller, dan antarmuka pengguna. MVC sangat berkaitan dengan
Object-Oriented Programming (OOP) karena setiap komponen dapat diimplementasikan
sebagai kelas dan objek, yang memanfaatkan prinsip-prinsip OOP seperti enkapsulasi,
pewarisan, dan polimorfisme. Dengan menggunakan prinsip-prinsip OOP, MVC membantu
dalam menciptakan aplikasi yang terstruktur, mudah dikelola, dan dapat diperluas.
• Model: Model mewakili struktur data dan biasanya berisi fungsi-fungsi yang
membantu pengelolaan basis data, seperti memasukkan data, memperbarui data, dan
sebagainya.
• View: View adalah bagian yang bertanggung jawab untuk menampilkan informasi
kepada pengguna, biasanya dalam bentuk halaman web.
• Controller: Controller adalah komponen yang menghubungkan model dan view,
bertindak sebagai perantara antara keduanya.
Gambar IV. 1
Controller --resource
Berikut adalah kegunaan masing-masing function pada Controller yang dihasilkan dengan
opsi --resource dalam Laravel:
• index(), digunakan menampilkan semua entri dari suatu model.
• create(), digunakan untuk menampilkan halaman input data baru.
• store(Request $request), digunakan untuk memproses dan menyimpan data yang
dikirim dari form create.
• show($id), digunakan untuk menampilkan informasi lengkap dari satu entri data.
• edit($id), Digunakan untuk menampilkan halaman pengeditan data.
• update(Request $request, $id), Digunakan untuk memproses dan menyimpan
perubahan data yang dikirim dari form edit.
• destroy($id), digunakan untuk menghapus satu entri data.
Setiap function ini sesuai dengan operasi CRUD dan mempermudah dalam pengelolaan data
di aplikasi Laravel.
WEB PROGRAMMING II 31
4.2. Menampilkan Data Pada Laravel
1. Pertama kita akan menampilkan data anggota secara keselurahan berdasarkan ID. Maka pada
AnggotaController function index() berikut perubahannya:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Anggota;
2. Maka pada resources/views kita tambahkan folder v_anggota & file dengan nama
index.blade.php seperti yang terlihat pada gambar Gambar IV.2
<h3> {{$judul}} </h3>
<a href="{{ route('anggota.create') }}">
<button type="button">Tambah</button>
</a>
<table border="1" width="60%">
<tr>
<th>No</th>
<th>Nama</th>
<th>HP</th>
<th>Aksi</th>
</tr>
@foreach ($index as $row)
<tr>
<td> {{ $loop->iteration }} </td>
<td> {{$row->nama}} </td>
<td> {{$row->hp}} </td>
<td>
<a href="{{ route('anggota.edit', $row->id) }}">
<button type="button">Ubah</button>
</a>
<form action="{{ route('anggota.destroy', $row->id) }}" method="POST">
@method('delete')
@csrf
<button type="submit">Hapus</button>
</form>
</td>
</tr>
@endforeach
</table>
Tambahkan style="display: inline-block;" pada aksi Ubah dan Hapus digunakan untuk
memastikan bahwa elemen <a> dan <form> ditampilkan sebagai elemen blok yang tetap
berada dalam satu baris dengan elemen lainnya, menjaga keselarasan dan tata letak yang rapi
pada halaman web. Berikut perubahan setelah ditambahan style="display: inline-block;"
<h3> {{$judul}} </h3>
<a href="{{ route('anggota.create') }}">
WEB PROGRAMMING II 32
<button type="button">Tambah</button>
</a>
<table border="1" width="60%">
<tr>
<th>No</th>
<th>Nama</th>
<th>HP</th>
<th>Aksi</th>
</tr>
@foreach ($index as $row)
<tr>
<td> {{ $loop->iteration }} </td>
<td> {{$row->nama}} </td>
<td> {{$row->hp}} </td>
<td>
<a href="{{ route('anggota.edit', $row->id) }}" style="display: inline-block;">
<button type="button">Ubah</button>
</a>
<form action="{{ route('anggota.destroy', $row->id) }}" method="POST"
style="display: inline-block;">
@method('delete')
@csrf
<button type="submit">Hapus</button>
</form>
</td>
</tr>
@endforeach
</table>
Gambar IV. 2
Index.blade.php()
3. Pada routes\web.php sebagai berikut:
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\AnggotaController;
Route::get('/', function () {
return view('welcome');
});
Route::resource('anggota', AnggotaController::class);
4. Dengan demikan kita pada melihat hasilnya pada browser dengan mengetikkan alamat
http://localhost:8000/anggota
WEB PROGRAMMING II 33
public function create()
{
return view('v_anggota.create', [
'judul' => 'Tambah Anggota'
]);
}
Gambar IV. 3
Create.blade.php
Pada Input Text tambahkan value="{{old('nama_text')}}"> sangat berguna untuk menjaga data
input pengguna tetap ada selama siklus validasi form, sehingga data yang telah di-input tidak
hilang. Berikut setelah form ditambahakan value="{{old('nama_text')}}">. Tambahan lainnya
yakni kita juga dapat menambahan placeholder yang berfungsi untuk memudahkan pengguna
dalam mengisi formulir, terutama ketika informasi yang diminta tidak langsung jelas dari
konteks form.
<h3> {{$judul}} </h3>
<form action="{{ route('anggota.store') }}" method="post">
@csrf
<label>Nama</label><br>
<input type="text" name="nama" id="" value="{{old('nama')}}" placeholder="Masukkan Nama
Lengkap">
WEB PROGRAMMING II 34
<p></p>
<label>HP</label><br>
<input type="text" name="hp" id="" value="{{old('hp')}}" placeholder="Masukkan Nomor
HP">
<p></p>
<button type="submit">Simpan</button>
<a href="{{ route('anggota.index') }}">
<button type="button">Batal</button>
</a>
</form>
3. Sebelum kita mengklik tombol Simpan, periksa data yang dikirim dengan cara pada
Controller di function store dengan menggunakan ddd($request) atau dd($request). Dengan
demikian, kita dapat memastikan bahwa form berfungsi dengan baik. Berikut adalah
perubahan AnggotaController pada function store:
public function store(Request $request)
{
// Debugging request data
dd($request);
// atau untuk lebih banyak informasi debugging
// ddd($request);
}
Gambar IV. 4
dd($request)
4. Jika request sudah sesuai dengan yang diharapkan, tambahkan script untuk menyimpan data
ke database pada function store(). Jika data berhasil tersimpan, kita akan kembali ke halaman
WEB PROGRAMMING II 35
yang menggunakan fungsi index(), sehingga record baru akan masuk dan seluruh data anggota
akan ditampilkan. Kita juga dapat memeriksa di database apakah record telah bertambah,
seperti yang terlihat pada gambar IV.5
public function store(Request $request)
{
// Debugging request data
// dd($request);
// atau untuk lebih banyak informasi debugging
// ddd($request);
$validatedData = $request->validate([
'nama' => 'required|max:255',
'hp' => 'required|min:10|max:13',
]);
Anggota::create($validatedData);
return redirect('/anggota');
}
Gambar IV. 5
Record Baru Berhasil Tersimpan
4.4. Hapus Data Pada Laravel
1. Berikutnya pada aksi Hapus, dimana saat aksi Hapus diklik data akan terhapus. Tambahkan
script pada function destroy pada AnggotaController sebagai berikut:
public function destroy(string $id)
{
$anggota = Anggota::findOrFail($id);
$anggota->delete();
return redirect('/anggota');
}
2. Pada index.blade.php yakni pada folder v_anggota, pastikan aksi hapus telah tersedia
<form action="{{ route('anggota.destroy', $row->id) }}" method="POST" style="display:
inline-block;">
@method('delete')
@csrf
<button type="submit">Hapus</button>
</form>
/**
WEB PROGRAMMING II 36
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
$rules = [
'nama' => 'required|max:100',
'hp' => 'required|min:10|max:13',
];
$validatedData = $request->validate($rules);
Anggota::where('id', $id)->update($validatedData);
return redirect('/anggota');
}
Gambar IV. 6
edit.blade.php
WEB PROGRAMMING II 37
a. Perubahaan create.blade.php setelah ditambahan invalid-feedback, sehingga saat form disini
kosong terdapat pesan bahwa data tidak boleh kosong seperti pada gambar IV.7
<h3> {{$judul}} </h3>
<form action="{{ route('anggota.store') }}" method="post">
@csrf
<label>Nama</label><br>
<input type="text" name="nama" id="" value="{{old('nama')}}" placeholder="Masukkan Nama
Lengkap" class="form-control @error('nama') is-invalid @enderror">
@error('nama')
<span class="invalid-feedback alert-danger" role="alert">
{{$message}}
</span>
@enderror
<p></p>
<label>HP</label><br>
<input type="text" name="hp" id="" value="{{old('hp')}}" placeholder="Masukkan Nomor
HP" class="form-control @error('hp') is-invalid @enderror">
@error('hp')
<span class="invalid-feedback alert-danger" role="alert">
{{$message}}
</span>
@enderror
<p></p>
<button type="submit">Simpan</button>
<a href="{{ route('anggota.index') }}">
<button type="button">Batal</button>
</a>
</form>
Gambar IV. 7
View Create Setelah di Tambahkan invalid-feedback
WEB PROGRAMMING II 38
@enderror
<p></p>
<label>HP</label><br>
<input type="text" name="hp" id="" value="{{old('hp',$edit->hp)}}"
placeholder="Masukkan Nomor HP" class="form-control @error('hp') is-invalid @enderror">
@error('hp')
<span class="invalid-feedback alert-danger" role="alert">
{{$message}}
</span>
@enderror
<p></p>
<button type="submit">Perbaharui</button>
<a href="{{ route('anggota.index') }}">
<button type="button">Batal</button>
</a>
</form>
Gambar IV. 8
View Create Setelah di Tambahkan invalid-feedback
Berikul tampilan lengkap script Controller dengan nama AnggotaController:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Anggota;
WEB PROGRAMMING II 39
// ddd($request);
$validatedData = $request->validate([
'nama' => 'required|max:255',
'hp' => 'required|min:10|max:13',
]);
Anggota::create($validatedData);
return redirect('/anggota');
}
Latihan Mandiri 4:
Portofolion sertifikasi kompetensi, Impentasikan Unit Kompetensi Software Development
pada Melakukan Debugging, Dengan minimal memenuhi kriteria berikut:
• penggunaan ddd($request) atau dd($request).
• invalid-feedback
• Penanganan pesan kesalahan pada browser dan cara penyelesaiannya
WEB PROGRAMMING II 40
Minggu Ke-5
Authenticate (Logika Login) & Pengujian Unit
Pada studi kasus kali ini adalah Project berkelompok, dimana pengerjaannya dapat dilakukan
bersama dengan berkelompok yang sudah ditentukan. Pada pembahasan modul ini studi kasus
yang akan dibangun yakni aplikasi toko online. Authenticate adalah proses verifikasi identitas
pengguna untuk mengakses aplikasi atau sistem. Untuk membuat Authenticate pada Laravel
10, kita dapat membuat Authenticate secara otomatis misalnya menggunakan Laravel Breeze,
Laravel Jetstream, Laravel Fortify dll, atau kita juga dapat membuat Authenticate secara
manual. Pada studi kasus aplikasi toko online yang akan dibahas dalam modul pembelajaran
ini, autentikasi akan dibuat secara manual.
3. Pastikan terminal sudah berada di direktori Project TokoOnline. Kemudian Jalankan migrasi
pada terminal, dan secara otomatis akan dibuatkan tabel yang disediakan oleh Laravel
php artisan migrate
Tabel V. 1
Tabel User
Fild Tipe Data Keterangan
id Bigint Primary Key
nama Varchar(255)
email Varchar(255)
role Enum
status Boolean
password Varchar(255)
hp Varchar(13)
foto Varchar(255) Nullable
WEB PROGRAMMING II 41
created_at Timestamp
updated_at Timestamp
Gambar V. 1
Blueprint Tabel User
Peran (role) di tabel user menggunakan tipe data enum dengan nilai:
• 0 untuk Admin: Pengguna dengan hak akses administratif yang dapat mengelola
sistem.
• 1 untuk SuperAdmin: Pengguna dengan hak akses tertinggi yang memiliki kontrol
penuh atas sistem.
• 2 untuk Customer: Peran ini dapat diubah sesuai dengan studi kasus yang diambil,
misalnya diganti dengan peran sebagai Member, Student, Teacher, dll.
Fungsi dari Status menggunakan tipe data boolean dengan nilai:
• 0 : Status user belum aktif atau dinonaktifkan sehingga user tidak diberikan akses untuk
login.
• 1 : User dapat mengakses dan login ke sistem
Sedangkan untuk foto, kita beri atribut nullable sehingga record dapat dikosongkan dan tidak
wajib diisi.
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
WEB PROGRAMMING II 42
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $table = "user";
protected $fillable = [
'nama',
'email',
'role',
'status',
'password',
'hp',
'foto',
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
}
2. Pada seeder kita tentukan nilai tabel dari user, sebagai berikut:
<?php
namespace Database\Seeders;
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use App\Models\User;
WEB PROGRAMMING II 43
'status' => 1,
'hp' => '0812345678901',
'password' => bcrypt('P@55word'),
]);
#untuk record berikutnya silahkan, beri nilai berbeda pada nilai: nama, email, hp dengan
nilai masing-masing anggota kelompok
User::create([
'nama' => 'Sopian Aji',
'email' => '[email protected]',
'role' => '0',
'status' => 1,
'hp' => '081234567892',
'password' => bcrypt('P@55word'),
]);
}
}
3. Kemudian jalankan seeder pada terminal sehingga tabel kini menjadi user dan record terisi
sesuai dengan seeder yang kita buat. Untuk field password akan terenkripsi (jika lupa password
maka bisa dicek kembali pada seeder) periksa di phpmyadmin seperti yang terlihat pada gambar
V.2
php artisan migrate:fresh --seed
Gambar V. 2
Tabel User Pada phpmyadmin
namespace App\Http\Controllers;
use Illuminate\Http\Request;
WEB PROGRAMMING II 44
]);
}
}
Route::get('/', function () {
return view('welcome');
});
Route::get('backend/beranda', [BerandaController::class, 'berandaBackend'])-
>name('backend.beranda');
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>tokoonline</title>
</head>
<body>
WEB PROGRAMMING II 45
<a href="{{ route('backend.beranda') }}">Beranda</a> |
<a href="#">User</a> |
<a href="#">Keluar</a>
<p></p>
Gambar V. 3
Penerapan Yield
WEB PROGRAMMING II 46
5.6. Membut Login Pada Laravel
1. Setelah kita konfigurasi database, menyiapkan data user & Halaman Utama, langkah
selanjutnya adalah membuat controller login dengan nama LoginController
php artisan make:controller LoginController
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
if (Auth::attempt($credentials)) {
if (Auth::user()->status == 0) {
Auth::logout();
return back()->with('error', 'User belum aktif');
}
$request->session()->regenerate();
return redirect()->intended(route('backend.beranda'));
}
return back()->with('error', 'Login Gagal');
}
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>tokoonline</title>
</head>
<body>
<h3> {{$judul}}</h3>
<!-- error -->
WEB PROGRAMMING II 47
@if(session()->has('error'))
<div class="alert alert-danger alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
aria-hidden="true">×</span></button>
<strong>{{ session('error')}} </strong>
</div>
@endif
<!-- errorEnd -->
<label>Password</label><br>
<input type="password" name="password" id="" value="{{old('password')}}"
class="form-control @error('password') is-invalid @enderror" placeholder="Masukkan
Password">
@error('password')
<span class="invalid-feedback alert-danger" role="alert">
{{$message}}
</span>
@enderror
<p></p>
<button type="submit">Login</button>
</form>
</body>
</html>
Gambar V. 4
Halaman Login
4. Kita lakukan perubahan pada routes\web.php sehingga ketika kita mengakses
http://localhost:8000/ di browser tidak lagi http://localhost:8000/backend/login. kita akan
diarahkan langsung ke halaman login gambar V.4. Selain itu, kita tambahkan middleware pada
WEB PROGRAMMING II 48
BerandaController sehingga controller hanya dapat diakses oleh pengguna yang sudah
berhasil login:
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\BerandaController;
use App\Http\Controllers\LoginController;
Route::get('/', function () {
// return view('welcome');
return redirect()->route('backend.login');
});
Route::get('backend/beranda', [BerandaController::class, 'berandaBackend'])-
>name('backend.beranda')->middleware('auth');
<body>
<a href="{{ route('backend.beranda') }}">Beranda</a> |
<a href="#">User</a> |
<a href="" onclick="event.preventDefault(); document.getElementById('keluar-
app').submit();">Keluar</a>
<p></p>
</html>
WEB PROGRAMMING II 49
Selamat Datang, <b>{{ Auth::user()->nama }}</b> pada aplikasi Toko Online dengan hak
akses yang anda miliki sebagai
<b>
@if (Auth::user()->role ==1)
Super Admin
@elseif(Auth::user()->role ==0)
Admin
@endif
</b>
ini adalah halaman utama dari aplikasi ini.
</p>
Gambar V. 5
Login sebagai Role Super Admin
Gambar V. 6
Login sebagai Role Admin
WEB PROGRAMMING II 50
7. Konfigurasi Http\Middleware\Authenticate.php seperti pada gambar V.6, dengan script
sebagai berikut:
<?php
namespace App\Http\Middleware;
Gambar V. 7
Authenticate.php
5.7. Pengujian Terhadap Form Login
Pengujian Black Box adalah metode pengujian perangkat lunak di mana penguji mengevaluasi
fungsionalitas suatu aplikasi tanpa melihat atau mempertimbangkan kode sumber internalnya.
Pengujian ini fokus pada input yang diberikan ke sistem dan output yang dihasilkan,
WEB PROGRAMMING II 51
memastikan bahwa sistem berfungsi sesuai dengan spesifikasi dan persyaratan yang
ditetapkan.
Pengujian Black Box pada Halaman Login melibatkan pengujian berbagai skenario
penggunaan yang mungkin dilakukan oleh pengguna. Contoh pengujian yang dapat dilakukan
pada Form Login:
Tabel V. 2
Hasil Pengujian Black Box Testing Halaman Login
No Skenario Test case Hasil yang Hasil Kesimpulan
pengujian diharapkan pengujian
1 Email User dan Email User:(kosong) Sistem akan Sesuai Valid
Password tidak Password:(kosong) menolak, pada Email harapan
diisi kemudian User dan
klik tombol login menampilkan
“Bidang isian email
wajib diisi”. Dan
pada Password dan
menampilkan
“Bidang isian
password wajib diisi”
2 Email User tidak Email User: admin Sistem akan Sesuai Valid
menggunakan Password:(kosong) menolak, pada Email harapan
format email User dan
dan Password menampilkan “Isian
tidak diisi email harus berupa
kemudian klik alamat surel yang
tombol login valid”. Dan pada
Password dan
menampilkan
“Bidang isian
password wajib diisi”
3 Mengetikkan Email User: Sistem akan Sesuai Valid
semua kondisi [email protected] menolak, pada Email harapan
salah, baik pada Password:S@n41 User dan Password
Email User atau kosong, dengan
Password menampilkan pesan
“Login Gagal”.
4 Mengetikkan Email User: Sistem akan Sesuai Valid
salah satu [email protected] menolak, pada Email harapan
kondisi, salah Password:S@n41 User dan Password
pada Email User kosong, dengan
atau Password menampilkan pesan
kemudian klik “Login Gagal”.
tombol login
5 Mengetikkan Email User: Sistem akan Sesuai Valid
Email User atau [email protected] menolak, pada Email harapan
Password Password:P@55word User dan Password
dengan data yang kosong, dengan
benar, tetapi menampilkan pesan
status kondisi 0 “Status User tidak
(status akun aktif”.
tidak aktif)
WEB PROGRAMMING II 52
6 Mengetikkan Email User: Sistem menerima Sesuai Valid
Email User atau [email protected] akses login dan harapan
Password Password:P@55word kemudian langsung
dengan data yang menampilkan menu
benar dan status utama.
kondisi 1 (status
akun aktif)
Gambar V. 8
Pengujian Pada Nomor 1
Gambar V. 9
Pengujian Pada Nomor 2
WEB PROGRAMMING II 53
Gambar V. 10
Pengujian Pada Nomor 3 & 4
Gambar V. 11
Pengujian Pada Nomor 5
Latihan Mandiri 5:
Portofolion sertifikasi kompetensi, Impentasikan Unit Kompetensi Software Development
pada Menggunakan Library atau Komponen Pre-Existing.
WEB PROGRAMMING II 54
Minggu Ke-6
Template HTML, CSS, Bootstrap, dan JavaScript
Untuk template pada studi kasus toko online menggunakan template dengan nama Matrix
Admin – dengan menggunakan Free HTML5 Bootstrap 4, untuk template dapat di download
pada https://bit.ly/LaravelWebPro2.
Gambar VI. 1
Template - Matrix Admin
2. Berikut demo Template - Matrix Admin dimana fitur utama yang digunakan sudah sesuai
dengan kebutuhan Project toko online:
WEB PROGRAMMING II 55
Drop-down menu Sidebar dimana menu didalam menu, seperti pada
gambar VI.5 (garis merah putus-putus)
FontAwesome atau Untuk memudahkan dalam menggati icon pada gambar
Material icon font icons VI.5
Buttons Untuk mengetahui jenis Buttons yang tersedia pada
gambar VI.6
Authentication pages Halaman login seperti pada gambar VI.7
Forms Halaman Form seperti pada gambar VI.8
elements Untuk mengetahui jenis Badges, Notificaion, Additional
Content dan lainnya pada gambar VI.9
Gambar VI. 2
Fully Responsive
Gambar VI. 3
Basic Data Tables
WEB PROGRAMMING II 56
Gambar VI. 4
Charts
Gambar VI. 5
Icons
WEB PROGRAMMING II 57
Gambar VI. 6
Buttons
Gambar VI. 7
Authentication Pages
WEB PROGRAMMING II 58
Gambar VI. 8
Forms
Gambar VI. 9
Elements
6.2. Implementasi Template Admin
1. copy folder dist dan isi folder assets maka terdapat 3 folder yakni extra-libs, images dan
libs pada direktori TokoOnline\public\backend sehingga terlihat pada gambar VI.10
WEB PROGRAMMING II 59
Gambar VI. 10
Komponen Template Backend - Matrix Admin
2. Menerapkan Template Login:
• Duplikat view login yang terletak pada direktori
resources\views\backend\v_login\login.blade.php. Beri nama hasil duplikat tersebut
login-old.blade.php seperti pada gambar VI.11.
• Kemudian, buka file seperti pada gambar VI.1 dengan nama file authentication-
login.html yang terletak pada direktori TokoOnline\public\backend\matrix-admin-
master menggunakan Visual Studio Code,
• Ganti seluruh script di login.blade.php dengan script dari authentication-login.html.
3. Ubah direktori komponen dengan menggunakan Asset <link href="gantidirektori"
rel="stylesheet"> menjadi {{ asset('asset') }} umumnya script pada blok kode <head></head>
seperti pada gambar VI.11, dan pada blok kode akhir sebelum </body> yakni <script
src=""> </script>, seperti pada gambar VI.12.
Gambar VI. 11
Asset Pada Blok Kode<head></head>
WEB PROGRAMMING II 60
Gambar VI. 12
Asset Pada Akhir Sebelum </body>
Berikut adalah script lengkap pada login.blade.php:
• Favicon icon, untuk mendapatkan icon_univ_bsi.png dapat didownload
https://bit.ly/LaravelWebPro2 dengan direktori TokoOnline\public\image kemudian
direktori menggunakan aset. dimana gambar yang digunakan icon_univ_bsi.png
• Title, diubah menjadi tokoonline
• Logo template, dimana gambar yang digunakan icon_univ_bsi.png telah
menggunakan asset
• Form, sudah disesuiakan dimana penggunaan text email & password dimana kode
referensi dari login-old.blade.php
<!DOCTYPE html>
<html dir="ltr">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Tell the browser to be responsive to screen width -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<!-- Favicon icon -->
<link rel="icon" type="image/png" sizes="16x16" href="{{
asset('image/icon_univ_bsi.png') }}">
<title>tokoonline</title>
<!-- Custom CSS -->
<link href="{{ asset('backend/dist/css/style.min.css') }}" rel="stylesheet">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="main-wrapper">
WEB PROGRAMMING II 61
<!-- ============================================================== -->
<!-- Preloader - style you can find in spinners.css -->
<!-- ============================================================== -->
<div class="preloader">
<div class="lds-ripple">
<div class="lds-pos"></div>
<div class="lds-pos"></div>
</div>
</div>
<!-- ============================================================== -->
<!-- Preloader - style you can find in spinners.css -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- Login box.scss -->
<!-- ============================================================== -->
<div class="auth-wrapper d-flex no-block justify-content-center align-items-center
bg-dark">
<div class="auth-box bg-dark border-top border-secondary">
<div id="loginform">
<div class="text-center p-t-20 p-b-20">
<span class="db"><img src="{{ asset('backend/images/logo.png') }}"
alt="logo" /></span>
</div>
<!-- Form -->
<!-- error -->
@if(session()->has('error'))
<div class="alert alert-danger alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-
label="Close"><span aria-hidden="true">×</span></button>
<strong>{{ session('error')}} </strong>
</div>
@endif
<!-- errorEnd -->
<form class="form-horizontal m-t-20" id="loginform" action="{{
route('backend.login') }}" method="post">
@csrf
<div class="row p-b-30">
<div class="col-12">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text bg-success text-
white" id="basic-addon1"><i class="ti-user"></i></span>
</div>
<input type="text" name="email"
value="{{old('email')}}" class="form-control form-control-lg @error('email') is-invalid
@enderror" placeholder="Masukkan Email" aria-label="Username" aria-describedby="basic-
addon1">
@error('email')
<span class="invalid-feedback alert-danger"
role="alert">
{{$message}}
</span>
@enderror
</div>
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text bg-warning text-
white" id="basic-addon2"><i class="ti-pencil"></i></span>
</div>
<input type="password" name="password" class="form-
control form-control-lg @error('password') is-invalid @enderror" placeholder="Masukkan
Password" aria-label="Password" aria-describedby="basic-addon1">
@error('password')
<span class="invalid-feedback alert-danger"
role="alert">
{{$message}}
WEB PROGRAMMING II 62
</span>
@enderror
</div>
</div>
</div>
<div class="row border-top border-secondary">
<div class="col-12">
<div class="form-group">
<div class="p-t-20">
<button class="btn btn-info" id="to-recover"
type="button"><i class="fa fa-lock m-r-5"></i> Lost password?</button>
<button class="btn btn-success float-right"
type="submit">Login</button>
</div>
</div>
</div>
</div>
</form>
</div>
<div id="recoverform">
<div class="text-center">
<span class="text-white">Enter your e-mail address below and we
will send you instructions how to recover a password.</span>
</div>
<div class="row m-t-20">
<!-- Form -->
<form class="col-12" action="index.html">
<!-- email -->
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text bg-danger text-white"
id="basic-addon1"><i class="ti-email"></i></span>
</div>
<input type="text" class="form-control form-control-lg"
placeholder="Email Address" aria-label="Username" aria-describedby="basic-addon1">
</div>
<!-- pwd -->
<div class="row m-t-20 p-t-20 border-top border-secondary">
<div class="col-12">
<a class="btn btn-success" href="#" id="to-login"
name="action">Back To Login</a>
<button class="btn btn-info float-right" type="button"
name="action">Recover</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- ============================================================== -->
<!-- Login box.scss -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- Page wrapper scss in scafholding.scss -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- Page wrapper scss in scafholding.scss -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- Right Sidebar -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- Right Sidebar -->
<!-- ============================================================== -->
</div>
WEB PROGRAMMING II 63
<!-- ============================================================== -->
<!-- All Required js -->
<!-- ============================================================== -->
<script src="{{ asset('backend/libs/jquery/dist/jquery.min.js') }}"></script>
<!-- Bootstrap tether Core JavaScript -->
<script src="{{ asset('backend/libs/popper.js/dist/umd/popper.min.js') }}"></script>
<script src="{{ asset('backend/libs/bootstrap/dist/js/bootstrap.min.js') }}"></script>
<!-- ============================================================== -->
<!-- This page plugin js -->
<!-- ============================================================== -->
<script>
$('[data-toggle="tooltip"]').tooltip();
$(".preloader").fadeOut();
// ==============================================================
// Login and Recover Password
// ==============================================================
$('#to-recover').on("click", function() {
$("#loginform").slideUp();
$("#recoverform").fadeIn();
});
$('#to-login').click(function() {
$("#recoverform").hide();
$("#loginform").fadeIn();
});
</script>
</body>
</html>
Gambar VI. 13
Login setelah Menggunakan Template
WEB PROGRAMMING II 64
4. Menerapkan Template Menu Utama, Langkah-langkahnya sama seperti menerapkan
template pada login:
• Duplikat view login yang terletak pada direktori
resources\views\backend\v_layouts\app.blade.php. Beri nama hasil duplikat tersebut
app-old.blade.php seperti pada gambar VI.11.
• Kemudian, buka file seperti pada gambar VI.1 dengan nama file tables.html yang
terletak pada direktori TokoOnline\public\backend\matrix-admin-master
menggunakan Visual Studio Code
• Ganti seluruh script di app.blade.php dengan script dari tables.html. Dengan
menggunakan master template dari tables.html dengan demikian kita akan lebih
mudah dalam menggunakan Datatable.
5. Ubah direktori komponen dengan menggunakan {{ asset('gantidengandirektori') }} baik
pada blok kode <head></head> maupun pada blok kode akhir sebelum </body>.
Gambar VI. 14
Asset Blok Kode <head></head> Pada Menu Utama
WEB PROGRAMMING II 65
Gambar VI. 15
Blok Kode Akhir Sebelum </body> Pada Menu Utama
Berikut adalah script lengkap pada app.blade.php dan beberapa perubahan script lainnya
sebagai berikut:
• Favicon icon, dimana gambar yang digunakan icon_univ_bsi.png telah menggunakan
asset
• Title, diubah menjadi tokoonline
• Logo template, dimana gambar yang digunakan icon_univ_bsi.png & logo_text.png
telah menggunakan asset hasil akan terlihat seperti pada gambar VI.16
Gambar VI. 16
Penyesuaian Pada Menu Utama
WEB PROGRAMMING II 66
Berikutnya kembali kita sesuaikan pada app.blade.php hasilnya seperti gambar VI.16 dan
beberapa perubahan script lainnya sebagai berikut:
• Hapus Topbar header seperti pada gambar gambar VI.6 (garis merah putus-putus)
• Sidebar, sudah disesuiakan dengan kebutuhan studi kasus toko online dengan refensi
dari app-old.blade.php yakni tombol Beranda {{ route('backend.beranda') }} dan
Tombol Keluar untuk mengakhiri session() dengan memanggil <form id="keluar-
app">. Serta ada penambahan icon (referensi dari Gambar VI.5 Icons) & dropdwon.
• Datatable, ambil tabel yang berformat Datatable kemudian contoh record hapus
sisahkan 1 record untuk master Datatable
• Avatar, menu yang digunakan My Profile dan Logout. & ubah footer sesuai dengan
kesepakatan kelompok masing-masing
Gambar VI. 17
Penyesuaian Pada Topbar header, Sidebar, Datatable, Avatar & footer
Kita tambahkan @yield('content') pada app.blade.php. Cari baris script dengan kata kunci
pada dokumentasi <!-- Start Page Content --> seperti pada gambar VI.18, sehingga saat tombol
Beranda diklik, halaman akan tampil seperti pada gambar VI.19
<!DOCTYPE html>
<html dir="ltr" lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Tell the browser to be responsive to screen width -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<!-- Favicon icon -->
<link rel="icon" type="image/png" sizes="16x16" href="{{
asset('image/icon_univ_bsi.png') }}">
<title>tokoonline</title>
<!-- Custom CSS -->
<link rel="stylesheet" type="text/css" href="{{ asset('backend/extra-
libs/multicheck/multicheck.css') }}">
WEB PROGRAMMING II 67
<link href="{{ asset('backend/libs/datatables.net-bs4/css/dataTables.bootstrap4.css')
}}" rel="stylesheet">
<link href="{{ asset('backend/dist/css/style.min.css') }}" rel="stylesheet">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<!-- ============================================================== -->
<!-- Preloader - style you can find in spinners.css -->
<!-- ============================================================== -->
<div class="preloader">
<div class="lds-ripple">
<div class="lds-pos"></div>
<div class="lds-pos"></div>
</div>
</div>
<!-- ============================================================== -->
<!-- Main wrapper - style you can find in pages.scss -->
<!-- ============================================================== -->
<div id="main-wrapper">
<!-- ============================================================== -->
<!-- Topbar header - style you can find in pages.scss -->
<!-- ============================================================== -->
<header class="topbar" data-navbarbg="skin5">
<nav class="navbar top-navbar navbar-expand-md navbar-dark">
<div class="navbar-header" data-logobg="skin5">
<!-- This is for the sidebar toggle which is visible on mobile only -->
<a class="nav-toggler waves-effect waves-light d-block d-md-none"
href="javascript:void(0)"><i class="ti-menu ti-close"></i></a>
<!-- ============================================================== -->
<!-- Logo -->
<!-- ============================================================== -->
<a class="navbar-brand" href="index.html">
<!-- Logo icon -->
<b class="logo-icon p-l-10">
<!--You can put here icon as well // <i class="wi wi-
sunset"></i> //-->
<!-- Dark Logo icon -->
<img src="{{ asset('image/icon_univ_bsi.png') }}"
alt="homepage" class="light-logo" />
</b>
<!--End Logo icon -->
<!-- Logo text -->
<span class="logo-text">
<!-- dark Logo text -->
<img src="{{ asset('image/logo_text.png') }}" alt="homepage"
class="light-logo" />
</span>
<!-- Logo icon -->
<!-- <b class="logo-icon"> -->
<!--You can put here icon as well // <i class="wi wi-sunset"></i>
//-->
<!-- Dark Logo icon -->
<!-- <img src="assets/images/logo-text.png" alt="homepage"
class="light-logo" /> -->
WEB PROGRAMMING II 68
<!-- ============================================================== -->
<!-- End Logo -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- Toggle which is visible on mobile only -->
<!-- ============================================================== -->
<a class="topbartoggler d-block d-md-none waves-effect waves-light"
href="javascript:void(0)" data-toggle="collapse" data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle
navigation"><i class="ti-more"></i></a>
</div>
<!-- ============================================================== -->
<!-- End Logo -->
<!-- ============================================================== -->
<div class="navbar-collapse collapse" id="navbarSupportedContent" data-
navbarbg="skin5">
<!-- ============================================================== -->
<!-- toggle and nav items -->
<!-- ============================================================== -->
<ul class="navbar-nav float-left mr-auto">
<li class="nav-item d-none d-md-block"><a class="nav-link
sidebartoggler waves-effect waves-light" href="javascript:void(0)" data-sidebartype="mini-
sidebar"><i class="mdi mdi-menu font-24"></i></a></li>
<!-- ==============================================================
-->
<!-- create new -->
<!-- ==============================================================
-->
<!-- ==============================================================
-->
<!-- Search -->
<!-- ==============================================================
-->
</ul>
<!-- ============================================================== -->
<!-- Right side toggle and nav items -->
<!-- ============================================================== -->
<ul class="navbar-nav float-right">
<!-- ==============================================================
-->
<!-- Comment -->
<!-- ==============================================================
-->
<!-- ==============================================================
-->
<!-- End Comment -->
<!-- ==============================================================
-->
<!-- ==============================================================
-->
<!-- Messages -->
<!-- ==============================================================
-->
<!-- ==============================================================
-->
<!-- End Messages -->
<!-- ==============================================================
-->
<!-- ==============================================================
-->
<!-- User profile and search -->
WEB PROGRAMMING II 69
<!-- ==============================================================
-->
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle text-muted waves-effect
waves-dark pro-pic" href="" data-toggle="dropdown" aria-haspopup="true" aria-
expanded="false"><img src="assets/images/users/1.jpg" alt="user" class="rounded-circle"
width="31"></a>
<div class="dropdown-menu dropdown-menu-right user-dd
animated">
<a class="dropdown-item" href="javascript:void(0)"><i
class="ti-user m-r-5 m-l-5"></i> Profil Saya</a>
<a class="dropdown-item" href=""
onclick="event.preventDefault(); document.getElementById('keluar-app').submit();"><i
class="fa fa-power-off m-r-5 m-l-5"></i> Keluar</a>
<div class="dropdown-divider"></div>
</div>
</li>
<!-- ==============================================================
-->
<!-- User profile and search -->
<!-- ==============================================================
-->
</ul>
</div>
</nav>
</header>
<!-- ============================================================== -->
<!-- End Topbar header -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- Left Sidebar - style you can find in sidebar.scss -->
<!-- ============================================================== -->
<aside class="left-sidebar" data-sidebarbg="skin5">
<!-- Sidebar scroll-->
<div class="scroll-sidebar">
<!-- Sidebar navigation-->
<nav class="sidebar-nav">
<ul id="sidebarnav" class="p-t-30">
<li class="sidebar-item"> <a class="sidebar-link waves-effect
waves-dark sidebar-link" href="{{ route('backend.beranda') }}" aria-expanded="false"><i
class="mdi mdi-view-dashboard"></i><span class="hide-menu">Beranda</span></a>
</li>
<li class="sidebar-item"> <a class="sidebar-link waves-effect
waves-dark sidebar-link" href="charts.html" aria-expanded="false"><i class="mdi mdi-
account"></i><span class="hide-menu">User</span></a>
</li>
<li class="sidebar-item"> <a class="sidebar-link has-arrow waves-
effect waves-dark" href="javascript:void(0)" aria-expanded="false"><i class="mdi mdi-
shopping"></i><span class="hide-menu">Data Produk </span></a>
<ul aria-expanded="false" class="collapse first-level">
<li class="sidebar-item"><a href="icon-material.html"
class="sidebar-link"><i class="mdi mdi-chevron-right"></i><span class="hide-menu"> Kategori
</span></a>
</li>
<li class="sidebar-item"><a href="icon-fontawesome.html"
class="sidebar-link"><i class="mdi mdi-chevron-right"></i><span class="hide-menu"> Produk
</span></a>
</li>
</ul>
</li>
</ul>
</nav>
<!-- End Sidebar navigation -->
</div>
<!-- End Sidebar scroll-->
WEB PROGRAMMING II 70
</aside>
<!-- ============================================================== -->
<!-- End Left Sidebar - style you can find in sidebar.scss -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- Page wrapper -->
<!-- ============================================================== -->
<div class="page-wrapper">
<!-- ============================================================== -->
<!-- Bread crumb and right sidebar toggle -->
<!-- ============================================================== -->
<div class="page-breadcrumb">
<div class="row">
<div class="col-12 d-flex no-block align-items-center">
<h4 class="page-title">Tables</h4>
<div class="ml-auto text-right">
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="#">Home</a></li>
<li class="breadcrumb-item active" aria-
current="page">Library</li>
</ol>
</nav>
</div>
</div>
</div>
</div>
<!-- ============================================================== -->
<!-- End Bread crumb and right sidebar toggle -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- Container fluid -->
<!-- ============================================================== -->
<div class="container-fluid">
<!-- ============================================================== -->
<!-- Start Page Content -->
<!-- ============================================================== -->
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-body">
<h5 class="card-title">Basic Datatable</h5>
<div class="table-responsive">
<table id="zero_config" class="table table-striped
table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Age</th>
<th>Start date</th>
<th>Salary</th>
</tr>
</thead>
<tbody>
<tr>
<td>Tiger Nixon</td>
<td>System Architect</td>
WEB PROGRAMMING II 71
<td>Edinburgh</td>
<td>61</td>
<td>2011/04/25</td>
<td>$320,800</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!-- ============================================================== -->
<!-- End PAge Content -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- Right sidebar -->
<!-- ============================================================== -->
<!-- .right-sidebar -->
<!-- ============================================================== -->
<!-- End Right sidebar -->
<!-- ============================================================== -->
</div>
<!-- ============================================================== -->
<!-- End Container fluid -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- footer -->
<!-- ============================================================== -->
<footer class="footer text-center">
Web Programming. Studi Kasus Toko Online <a
href="https://bsi.ac.id/">Kuliah..? BSI Aja !!!</a>
</footer>
<!-- ============================================================== -->
<!-- End footer -->
<!-- ============================================================== -->
</div>
<!-- ============================================================== -->
<!-- End Page wrapper -->
<!-- ============================================================== -->
</div>
<!-- ============================================================== -->
<!-- End Wrapper -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- All Jquery -->
<!-- ============================================================== -->
<script src="{{ asset('backend/libs/jquery/dist/jquery.min.js') }}"></script>
<!-- Bootstrap tether Core JavaScript -->
<script src="{{ asset('backend/libs/popper.js/dist/umd/popper.min.js') }}"></script>
<script src="{{ asset('backend/libs/bootstrap/dist/js/bootstrap.min.js') }}"></script>
<!-- slimscrollbar scrollbar JavaScript -->
<script src="{{ asset('backend/libs/perfect-scrollbar/dist/perfect-
scrollbar.jquery.min.js') }}"></script>
<script src="{{ asset('backend/extra-libs/sparkline/sparkline.js') }}"></script>
<!--Wave Effects -->
<script src="{{ asset('backend/dist/js/waves.js') }}"></script>
<!--Menu sidebar -->
<script src="{{ asset('backend/dist/js/sidebarmenu.js') }}"></script>
<!--Custom JavaScript -->
<script src="{{ asset('backend/dist/js/custom.min.js') }}"></script>
<!-- this page js -->
<script src="{{ asset('backend/extra-libs/multicheck/datatable-checkbox-init.js')
}}"></script>
WEB PROGRAMMING II 72
<script src="{{ asset('backend/extra-libs/multicheck/jquery.multicheck.js')
}}"></script>
<script src="{{ asset('backend/extra-libs/DataTables/datatables.min.js') }}"></script>
<script>
/****************************************
* Basic Table *
****************************************/
$('#zero_config').DataTable();
</script>
<!-- form keluar app -->
<form id="keluar-app" action="{{ route('backend.logout') }}" method="POST" class="d-
none">
@csrf
</form>
<!-- form keluar app end -->
</body>
</html>
Gambar VI. 18
Menambahakan @yield('content') pada App.blade.php
Gambar VI. 19
Konten Pada Halaman Beranda
WEB PROGRAMMING II 73
6.2. Membuat Master DataTable
Sehingga Beranda dan DataTable tampil, namun seharusnya DataTable ini tidak muncul di
halaman Beranda seperti pada Gambar VI.19. Selanjutnya, kita pindahkan DataTable sesuai
dengan view yang menggunakan DataTable. Maka kita siapkan terlebih dulu data yang akan
ditampilkan dengan menggunakan DataTable. Misalnya kita akan menampilkan data user,
maka kita buat Controller terlebih dulu dengan nama UserController.
</td>
</tr>
@endforeach
</table>
WEB PROGRAMMING II 74
@endsection
</table>
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\BerandaController;
use App\Http\Controllers\LoginController;
use App\Http\Controllers\UserController;
Route::get('/', function () {
// return view('welcome');
return redirect()->route('backend.login');
});
Route::get('backend/beranda', [BerandaController::class, 'berandaBackend'])-
>name('backend.beranda')->middleware('auth');
// Route::resource('backend/user', UserController::class)->middleware('auth');
Route::resource('backend/user', UserController::class, ['as' => 'backend'])-
>middleware('auth');
as sebagai Alias
as digunakan untuk memberikan alias atau prefix ke nama route yang dihasilkan oleh metode
routing seperti Route::resource. Ini digunakan untuk mengelompokkan nama-nama route atau
menambahkan namespace ke dalamnya.
Tanpa as:
Route::resource('user', UserController::class);
Route yang dihasilkan:
• user.index
• user.create
• user.store
• user.show
• user.edit
• user.update
• user.destroy
Dengan as:
Route::resource('user', UserController::class, ['as' => 'backend']);
Route yang dihasilkan:
• backend.user.index
• backend.user.create
• backend.user.store
• backend.user.show
• backend.user.edit
• backend.user.update
• backend.user.destroy
WEB PROGRAMMING II 75
5. Pada sidebar di resources\views\backend\v_layouts\app.blade.php, kita tambahkan
href="panggilRoute" pada menu User. Perubahan pada app.blade.php dilakukan pada bagian
sidebar dengan kata kunci pada dokumentasi <!-- Sidebar navigation--> sehingga saat tombol
User diklik, akan sesuai dengan href="panggilRoute" yang akan dipanggil, seperti pada gambar
VI.20.
<div class="scroll-sidebar">
<!-- Sidebar navigation-->
<nav class="sidebar-nav">
<ul id="sidebarnav" class="p-t-30">
<li class="sidebar-item"> <a class="sidebar-link waves-effect
waves-dark sidebar-link" href="{{ route('backend.beranda') }}" aria-expanded="false"><i
class="mdi mdi-view-dashboard"></i><span class="hide-menu">Beranda</span></a>
</li>
<li class="sidebar-item"> <a class="sidebar-link waves-effect
waves-dark sidebar-link" href="{{ route('backend.user.index') }}" aria-expanded="false"><i
class="mdi mdi-account"></i><span class="hide-menu">User</span></a>
</li>
<li class="sidebar-item"> <a class="sidebar-link has-arrow waves-
effect waves-dark" href="javascript:void(0)" aria-expanded="false"><i class="mdi mdi-
shopping"></i><span class="hide-menu">Data Produk </span></a>
<ul aria-expanded="false" class="collapse first-level">
<li class="sidebar-item"><a href="icon-material.html"
class="sidebar-link"><i class="mdi mdi-chevron-right"></i><span class="hide-menu"> Kategori
</span></a>
</li>
<li class="sidebar-item"><a href="icon-fontawesome.html"
class="sidebar-link"><i class="mdi mdi-chevron-right"></i><span class="hide-menu"> Produk
</span></a>
</li>
</ul>
</li>
</ul>
</nav>
<!-- End Sidebar navigation -->
</div>
Gambar VI. 20
Konten Pada Halaman User
WEB PROGRAMMING II 76
Latihan Mandiri 6:
Portofolion sertifikasi kompetensi, Impentasikan Unit Kompetensi Software Development
pada Membuat Dokumen Kode Program.
WEB PROGRAMMING II 77
Minggu Ke-7
Implementasi DataTable dan Form dengan Template
DataTable adalah plugin jQuery yang sangat berguna untuk memanipulasi dan menampilkan
data dalam bentuk tabel HTML. Plugin ini menyediakan berbagai fitur yang meningkatkan
kemampuan tabel HTML biasa menjadi lebih interaktif dan mudah digunakan.
Fitur Utama DataTable
• Pencarian: Memungkinkan pengguna untuk mencari data dalam tabel secara real-time.
• Pagination: Membagi data dalam tabel menjadi beberapa halaman, memudahkan
navigasi ketika data yang ditampilkan sangat banyak.
• Sortir Kolom: Memungkinkan pengguna untuk mengurutkan data berdasarkan kolom
tertentu secara ascending atau descending.
• Pengaturan Tampilan Kolom: Memungkinkan pengguna untuk memilih kolom mana
yang akan ditampilkan atau disembunyikan.
• AJAX: Mendukung pengambilan data secara dinamis melalui AJAX, sehingga data
dapat dimuat tanpa perlu memuat ulang halaman.
Gambar VII. 1
Implementasi @yield('content') pada app.blade.php
WEB PROGRAMMING II 78
2. Sehingga view pada resources\views\backend\v_user\ index.blade.php bertumpuk dengan
datatable, seperti pada gambar 7.2 sebagai berikut:
@extends('backend.v_layouts.app')
@section('content')
<!-- contentAwal -->
<h3> {{$judul}} </h3>
<a href="{{ route('backend.user.create') }}">
<button type="button">Tambah</button>
</a>
<table border="1" width="80%">
<tr>
<th>No</th>
<th>Email</th>
<th>Nama</th>
<th>Role</th>
<th>Status</th>
<th>Aksi</th>
</tr>
@foreach ($index as $row)
<tr>
<td> {{ $loop->iteration }} </td>
<td> {{$row->nama}} </td>
<td> {{$row->email}} </td>
<td> {{$row->role}} </td>
<td> {{$row->status}} </td>
<td>
<a href="{{ route('backend.user.edit', $row->id) }}">
<button type="button">Ubah</button>
</a>
<form action="{{ route('backend.user.destroy', $row->id) }}" method="POST">
@method('delete')
@csrf
<button type="submit">Hapus</button>
</form>
</td>
</tr>
@endforeach
</table>
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-body">
<h5 class="card-title">Basic Datatable</h5>
<div class="table-responsive">
<table id="zero_config" class="table table-striped table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Age</th>
<th>Start date</th>
<th>Salary</th>
</tr>
</thead>
<tbody>
<tr>
<td>Tiger Nixon</td>
<td>System Architect</td>
<td>Edinburgh</td>
<td>61</td>
<td>2011/04/25</td>
WEB PROGRAMMING II 79
<td>$320,800</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
Gambar VII. 2
Konten User & DataTabel
3. Sehingga, pada view di resources\views\backend\v_user\index.blade.php, tabel yang
digunakan hanya satu yaitu menggunakan DataTable. Berikut adalah script lengkap pada
index.blade.php, yang sudah ditambahkan aksi Tambah, Ubah, dan Hapus (referensi dari
Gambar VI.6 Buttons) pada DataTable. Kami ini index.blade.php seperti pada gambar VII.3
@extends('backend.v_layouts.app')
@section('content')
<!-- contentAwal -->
<div class="row">
<div class="col-12">
<a href="{{ route('backend.user.create') }}">
<button type="button" class="btn btn-primary"><i class="fas fa-plus"></i>
Tambah</button>
</a>
<div class="card">
<div class="card-body">
<h5 class="card-title"> {{$judul}} </h5>
<div class="table-responsive">
<table id="zero_config" class="table table-striped table-bordered">
<thead>
<tr>
<th>No</th>
WEB PROGRAMMING II 80
<th>Email</th>
<th>Nama</th>
<th>Role</th>
<th>Status</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
@foreach ($index as $row)
<tr>
<td> {{ $loop->iteration }} </td>
<td> {{$row->nama}} </td>
<td> {{$row->email}} </td>
<td>
@if ($row->role == 1)
<span class="badge badge-success"></i>
Super Admin</span>
@elseif($row->role == 0)
<span class="badge badge-primary"></i>
Admin</span>
@endif
</td>
<td>
@if ($row->status ==1)
<span class="badge badge-success"></i>
Aktif</span>
@elseif($row->status ==0)
<span class="badge badge-secondary"></i>
NonAktif</span>
@endif
</td>
<td>
<a href="{{ route('backend.user.edit', $row->id) }}"
title="Ubah Data">
<button type="button" class="btn btn-cyan btn-
sm"><i class="far fa-edit"></i> Ubah</button>
</a>
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
WEB PROGRAMMING II 81
Gambar VII. 3
Indeks User menggunakan DataTabel
7.2. Menerapkan Template pada Halaman Beranda
Demikian juga pada index() BerandaController kita gunakan Elements Additional Content-
alert-success seperti pada gambar Gambar VI.9 dengan direktori
resources\views\backend\v_beranda\index.blade.php berikut script lengkap & berikut
perubahan seperti pada gambar VII.4
@extends('backend.v_layouts.app')
@section('content')
<!-- contentAwal -->
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-body border-top">
<h5 class="card-title"> {{$judul}}</h5>
<div class="alert alert-success" role="alert">
<h4 class="alert-heading"> Selamat Datang, {{ Auth::user()->nama
}}</h4>
Aplikasi Toko Online dengan hak akses yang anda miliki sebagai
<b>
@if (Auth::user()->role ==1)
Super Admin
@elseif(Auth::user()->role ==0)
Admin
@endif
</b>
ini adalah halaman utama dari aplikasi Web Programming. Studi Kasus
Toko Online.
<hr>
<p class="mb-0">Kuliah..? BSI Aja !!!</p>
</div>
</div>
</div>
</div>
</div>
WEB PROGRAMMING II 82
Gambar VII. 4
Konten Beranda dengan Elements Additional Content- Alert-Success
7.3. Membuat Form Create Tanpa Template
1. Menerapkan Template Form, masih dengan UserController dengan function create()
public function create()
{
return view('backend.v_user.create', [
'judul' => 'Tambah User',
]);
}
<label>Foto</label>
<img class="foto-preview">
<input type="file" name="foto" class="form-control @error('foto') is-invalid @enderror"
onchange="previewFoto()">
@error('foto')
<div class="invalid-feedback alert-danger">{{ $message }}</div>
@enderror
<p></p>
<label>Hak Ases</label>
<select name="role" class="form-control @error('role') is-invalid @enderror">
<option value="" {{ old('role') == '' ? 'selected' : '' }}> - Pilih Hak Akses
-
</option>
<option value="1" {{ old('role') == '1' ? 'selected' : '' }}> Super Admin</option>
<option value="0" {{ old('role') == '0' ? 'selected' : '' }}> Admin
</option>
WEB PROGRAMMING II 83
</select>
@error('role')
<span class="invalid-feedback alert-danger" role="alert">
{{ $message }}
</span>
@enderror
<p></p>
<label>Nama</label>
<input type="text" name="nama" value="{{ old('nama') }}" class="form-control
@error('nama') is-invalid @enderror" placeholder="Masukkan Nama">
@error('nama')
<span class="invalid-feedback alert-danger" role="alert">
{{ $message }}
</span>
@enderror
<p></p>
<label>Email</label>
<input type="text" name="email" value="{{ old('email') }}" class="form-control
@error('email') is-invalid @enderror" placeholder="Masukkan Email">
@error('email')
<span class="invalid-feedback alert-danger" role="alert">
{{ $message }}
</span>
@enderror
<p></p>
<label>HP</label>
<input type="text" onkeypress="return hanyaAngka(event)" name="hp" value="{{ old('hp')
}}" class="form-control @error('hp') is-invalid @enderror" placeholder="Masukkan Nomor HP">
@error('hp')
<span class="invalid-feedback alert-danger" role="alert">
{{ $message }}
</span>
@enderror
<p></p>
<label>Password</label>
<input type="password" name="password" class="form-control @error('password') is-
invalid @enderror" placeholder="Masukkan Password">
@error('password')
<span class="invalid-feedback alert-danger" role="alert">
{{ $message }}
</span>
@enderror
<p></p>
<label>Konfirmasi Password</label>
<input type="password" name="password_confirmation" class="form-control"
placeholder="Konfirmasi Password">
</div>
<p></p>
<br>
<button type="submit" class="btn btn-primary">Simpan</button>
<a href="{{ route('backend.user.index') }}">
<button type="button" class="btn btn-secondary">Kembali</button>
</a>
</form>
WEB PROGRAMMING II 84
Gambar VII. 5
Form Create User
7.4. Menerapkan Form Create Dengan Template
Pada direktori resources\views\backend\v_user\create.blade.php kita ganti kali ini kita
gunakan Template Form dengan menggunakan form-basic.html seperti pada gambar VI.8,
berikut script lengkap create.blade.php setelah menggunakan Template Form
@Extends('Backend.V_Layouts.App')
@section('content')
<!-- contentAwal -->
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="card">
<form class="form-horizontal" action="{{ route('backend.user.store') }}"
method="post" enctype="multipart/form-data">
@csrf
<div class="card-body">
<h4 class="card-title"> {{$judul}} </h4>
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label>Foto</label>
<img class="foto-preview">
<input type="file" name="foto" class="form-control
@error('foto') is-invalid @enderror" onchange="previewFoto()">
@error('foto')
<div class="invalid-feedback alert-danger">{{ $message
}}</div>
@enderror
</div>
</div>
<div class="col-md-8">
<div class="form-group">
<label>Hak Ases</label>
<select name="role" class="form-control @error('role')
is-invalid @enderror">
WEB PROGRAMMING II 85
<option value="" {{ old('role') == '' ? 'selected'
: '' }}> - Pilih Hak Akses
-
</option>
<option value="1" {{ old('role') == '1' ?
'selected' : '' }}> Super Admin</option>
<option value="0" {{ old('role') == '0' ?
'selected' : '' }}> Admin
</option>
</select>
@error('role')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Nama</label>
<input type="text" name="nama" value="{{ old('nama')
}}" class="form-control @error('nama') is-invalid @enderror" placeholder="Masukkan Nama">
@error('nama')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Email</label>
<input type="text" name="email" value="{{ old('email')
}}" class="form-control @error('email') is-invalid @enderror" placeholder="Masukkan Email">
@error('email')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>HP</label>
<input type="text" onkeypress="return
hanyaAngka(event)" name="hp" value="{{ old('hp') }}" class="form-control @error('hp') is-
invalid @enderror" placeholder="Masukkan Nomor HP">
@error('hp')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Password</label>
<input type="password" name="password" class="form-
control @error('password') is-invalid @enderror" placeholder="Masukkan Password">
@error('password')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
WEB PROGRAMMING II 86
<label>Konfirmasi Password</label>
<input type="password" name="password_confirmation"
class="form-control" placeholder="Konfirmasi Password">
</div>
</div>
</div>
</div>
<div class="border-top">
<div class="card-body">
<button type="button" class="btn btn-primary">Simpan</button>
<a href="{{ route('backend.user.index') }}">
<button type="button" class="btn btn-
secondary">Kembali</button>
</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
Gambar VII. 6
Form Template
7.5. Membuat ImageHelper
1. Sebelum kita melanjutkan ke function store() pada UserController, form user mengirim
Image maka diperlukan ImageHelper. ImageHelper digunakan untuk memanipulasi gambar,
termasuk mengubah ukuran, memotong, memutar, dan mengubah format gambar
2. Membuat folder Helper dalam folder app, pada terminal
mkdir app/Helpers
3. Membuat file ImageHelper.php pada direktori app\Herpers, pada terminal
touch app/Helpers/ImageHelper.php
WEB PROGRAMMING II 87
4. Berikut script lengkap ImageHelper.php seperti pada gambar VII.7
<?php
namespace App\Helpers;
class ImageHelper
{
public static function uploadAndResize($file, $directory, $fileName, $width = null,
$height = null)
{
$destinationPath = public_path($directory);
$extension = strtolower($file->getClientOriginalExtension());
$image = null;
imagedestroy($image);
return $fileName;
}
}
WEB PROGRAMMING II 88
Gambar VII. 7
Script ImageHelper
5. Perintah php artisan storage:link adalah perintah dalam Laravel yang digunakan untuk
membuat symbolic link (symlink) dari direktori storage/app/public ke direktori public/storage.
Ini memungkinkan file yang disimpan di direktori storage dapat diakses secara publik melalui
URL. Jalankan perintah di terminal:
php artisan storage:link
Gambar VII. 8
Artisan Storage link
6. Jika berhasil maka pada folder public akan tertambah folder storage (folder berbentuk
shortcut)
Gambar VII. 9
Storage
WEB PROGRAMMING II 89
7. Setelah kita membuat ImageHelper maka kita panggil di UserController demikian kita
tambahkan juga Library Hash untuk password pada function store(). Library Hash di Laravel
digunakan untuk mengenkripsi (hashing) dan memverifikasi password dengan aman.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use App\Helpers\ImageHelper;
// menggunakan ImageHelper
if ($request->file('foto')) {
$file = $request->file('foto');
$extension = $file->getClientOriginalExtension();
$originalFileName = date('YmdHis') . '_' . uniqid() . '.' . $extension;
$directory = 'storage/img-user/';
// Simpan gambar dengan ukuran yang ditentukan
ImageHelper::uploadAndResize($file, $directory, $originalFileName, 385, 400);
// null (jika tinggi otomatis)
// Simpan nama file asli di database
$validatedData['foto'] = $originalFileName;
}
// password kombinasi
$password = $request->input('password');
$pattern = '/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_]).+$/';
// huruf kecil ([a-z]), huruf besar ([A-Z]), dan angka (\d) (?=.*[\W_]) simbol
karakter (non-alphanumeric)
if (preg_match($pattern, $password)) {
$validatedData['password'] = Hash::make($validatedData['password']);
User::create($validatedData, $messages);
return redirect()->route('user.index')->with('success', 'Data berhasil
tersimpan');
} else {
return redirect()->back()->withErrors(['password' => 'Password harus terdiri
dari kombinasi huruf besar, huruf kecil, angka, dan simbol karakter.']);
}
}
/**
* function lainnya
*/
}
WEB PROGRAMMING II 90
pada baris script ini kita dapat mengatur ukuran tinggi misalnya lebar 385px dengan tinggi
400px, namun kita juga dapat mengatur dengan lebar 385px dengan tinggi otomatis
// Simpan gambar dengan ukuran yang ditentukan
ImageHelper::uploadAndResize($file, $directory, $originalFileName, 385, 400);
// null (jika tinggi otomatis)
Sedangkan untuk // password kombinasi pada saat input data pada form password terdiri dari
kombinasi huruf kecil, huruf besar, angka dan simbol karakter misalnya P@55word
8. Kemudian jangan lupa untuk membuat folder img-user pada terminal, sehingga kita
memiliki folder img-user pada public/storage/ atau storage/app/public/
mkdir storage/app/public/img-user
Gambar VII. 10
Field Foto Null
7.6. SweetAlert
1. Silakan buat data user baru dengan mengklik tombol Tambah. Jika berhasil tersimpan, maka
akan redirect ke halaman utama data user, yakni route('backend.user.index'). Namun, saat
berhasil tersimpan, pesan with('success') tidak tampil (konfirmasi pesan data berhasil
tersimpan). Hal ini terjadi karena kita belum memanggil SweetAlert. Untuk memanggil
SweetAlert, terlebih dulu kita download dari https://bit.ly/LaravelWebPro2 dan ekstrak
SweetAlert pada folder public seperti pada gambar VII.8 Pada app.blade.php di direktori
resources\views\backend\v_layouts, tambahkan script untuk memanggil SweetAlert,
kemudian tambahkan konfirmasi success seperti pada gambar VII.10
<!-- sweetalert -->
<script src="{{ asset('sweetalert/sweetalert2.all.min.js') }}"></script>
<!-- sweetalert End -->
<!-- konfirmasi success-->
@if (session('success'))
<script>
Swal.fire({
icon: 'success',
title: 'Berhasil!',
text: "{{ session('success') }}"
});
</script>
@endif
<!-- konfirmasi success End-->
WEB PROGRAMMING II 91
Gambar VII. 11
Memanggil SweetAlert & Session('success')
2. Dengan demikian pada saat kita create data user maka konfirmasi success akan tampil seperti
pada gambar VII.11
Gambar VII. 12
Konfirmasi Success
3. Kemudian pada Aksi Hapus. Pada UserContoller dengan function destroy()
public function destroy(string $id)
{
$user = user::findOrFail($id);
if ($user->foto) {
$oldImagePath = public_path('storage/img-user/') . $user->foto;
if (file_exists($oldImagePath)) {
unlink($oldImagePath);
}
}
$user->delete();
return redirect()->route('user.index')->with('success', 'Data berhasil dihapus');
}
WEB PROGRAMMING II 92
Pada script destroy, selain menghapus data berdasarkan $id, script ini juga menghapus gambar
jika $user memiliki gambar. Dimana gambar yang akan dihapus pada direktori storage/img-
user/.
Perubahan pada Button Class yakni show_confirm & data-konf-delete, kemudian kita akan
deklarasikan pada javascript yakni pada konfirmasi delete.
<form method="POST" action="{{ route('backend.user.destroy', $row->id) }}" style="display:
inline-block;">
@method('delete')
@csrf
<button type="submit" class="btn btn-danger btn-sm show_confirm" data-konf-delete="{{
$row->nama }}" title='Hapus Data'>
<i class="fas fa-trash"></i> Hapus</button>
</form>
<div class="row">
<div class="col-12">
<a href="{{ route('backend.user.create') }}">
<button type="button" class="btn btn-primary"><i class="fas fa-plus"></i>
Tambah</button>
</a>
<div class="card">
<div class="card-body">
<h5 class="card-title"> {{$judul}} </h5>
<div class="table-responsive">
<table id="zero_config" class="table table-striped table-bordered">
<thead>
<tr>
<th>No</th>
<th>Email</th>
<th>Nama</th>
<th>Role</th>
<th>Status</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
@foreach ($index as $row)
<tr>
<td> {{ $loop->iteration }} </td>
<td> {{$row->nama}} </td>
<td> {{$row->email}} </td>
<td>
@if ($row->role == 1)
<span class="badge badge-success"></i>
WEB PROGRAMMING II 93
Super Admin</span>
@elseif($row->role == 0)
<span class="badge badge-primary"></i>
Admin</span>
@endif
</td>
<td>
@if ($row->status ==1)
<span class="badge badge-success"></i>
Aktif</span>
@elseif($row->status ==0)
<span class="badge badge-secondary"></i>
NonAktif</span>
@endif
</td>
<td>
<a href="{{ route('backend.user.edit', $row->id) }}"
title="Ubah Data">
<button type="button" class="btn btn-cyan btn-
sm"><i class="far fa-edit"></i> Ubah</button>
</a>
</div>
</div>
</div>
</div>
WEB PROGRAMMING II 94
}).then((result) => {
if (result.isConfirmed) {
Swal.fire('Terhapus!', 'Data berhasil dihapus.', 'success')
.then(() => {
form.submit();
});
}
});
});
</script>
Gambar VII. 13
javascrip Konfirmasi Delete
6. Kali ini, jika aksi Hapus diklik, akan tampil konfirmasi seperti pada gambar VII.13. Jika Ya
dipilih, maka data akan dihapus & muncul konfimasi berikutny seperti pada gambar VII.14,
namun jika Batal dipilih, maka akan kembali ke halaman index() User. Sehingga script
lengkap dari resources\views\backend\v_layouts\app.blade.php sebagai berikut:
<!DOCTYPE html>
<html dir="ltr" lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Tell the browser to be responsive to screen width -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<!-- Favicon icon -->
<link rel="icon" type="image/png" sizes="16x16" href="{{
asset('image/icon_univ_bsi.png') }}">
<title>tokoonline</title>
<!-- Custom CSS -->
<link rel="stylesheet" type="text/css" href="{{ asset('backend/extra-
libs/multicheck/multicheck.css') }}">
<link href="{{ asset('backend/libs/datatables.net-bs4/css/dataTables.bootstrap4.css')
}}" rel="stylesheet">
<link href="{{ asset('backend/dist/css/style.min.css') }}" rel="stylesheet">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
WEB PROGRAMMING II 95
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<!-- ============================================================== -->
<!-- Preloader - style you can find in spinners.css -->
<!-- ============================================================== -->
<div class="preloader">
<div class="lds-ripple">
<div class="lds-pos"></div>
<div class="lds-pos"></div>
</div>
</div>
<!-- ============================================================== -->
<!-- Main wrapper - style you can find in pages.scss -->
<!-- ============================================================== -->
<div id="main-wrapper">
<!-- ============================================================== -->
<!-- Topbar header - style you can find in pages.scss -->
<!-- ============================================================== -->
<header class="topbar" data-navbarbg="skin5">
<nav class="navbar top-navbar navbar-expand-md navbar-dark">
<div class="navbar-header" data-logobg="skin5">
<!-- This is for the sidebar toggle which is visible on mobile only -->
<a class="nav-toggler waves-effect waves-light d-block d-md-none"
href="javascript:void(0)"><i class="ti-menu ti-close"></i></a>
<!-- ============================================================== -->
<!-- Logo -->
<!-- ============================================================== -->
<a class="navbar-brand" href="index.html">
<!-- Logo icon -->
<b class="logo-icon p-l-10">
<!--You can put here icon as well // <i class="wi wi-
sunset"></i> //-->
<!-- Dark Logo icon -->
<img src="{{ asset('image/icon_univ_bsi.png') }}"
alt="homepage" class="light-logo" />
</b>
<!--End Logo icon -->
<!-- Logo text -->
<span class="logo-text">
<!-- dark Logo text -->
<img src="{{ asset('image/logo_text.png') }}" alt="homepage"
class="light-logo" />
</span>
<!-- Logo icon -->
<!-- <b class="logo-icon"> -->
<!--You can put here icon as well // <i class="wi wi-sunset"></i>
//-->
<!-- Dark Logo icon -->
<!-- <img src="assets/images/logo-text.png" alt="homepage"
class="light-logo" /> -->
WEB PROGRAMMING II 96
<!-- Toggle which is visible on mobile only -->
<!-- ============================================================== -->
<a class="topbartoggler d-block d-md-none waves-effect waves-light"
href="javascript:void(0)" data-toggle="collapse" data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle
navigation"><i class="ti-more"></i></a>
</div>
<!-- ============================================================== -->
<!-- End Logo -->
<!-- ============================================================== -->
<div class="navbar-collapse collapse" id="navbarSupportedContent" data-
navbarbg="skin5">
<!-- ============================================================== -->
<!-- toggle and nav items -->
<!-- ============================================================== -->
<ul class="navbar-nav float-left mr-auto">
<li class="nav-item d-none d-md-block"><a class="nav-link
sidebartoggler waves-effect waves-light" href="javascript:void(0)" data-sidebartype="mini-
sidebar"><i class="mdi mdi-menu font-24"></i></a></li>
<!-- ==============================================================
-->
<!-- create new -->
<!-- ==============================================================
-->
<!-- ==============================================================
-->
<!-- Search -->
<!-- ==============================================================
-->
</ul>
<!-- ============================================================== -->
<!-- Right side toggle and nav items -->
<!-- ============================================================== -->
<ul class="navbar-nav float-right">
<!-- ==============================================================
-->
<!-- Comment -->
<!-- ==============================================================
-->
<!-- ==============================================================
-->
<!-- End Comment -->
<!-- ==============================================================
-->
<!-- ==============================================================
-->
<!-- Messages -->
<!-- ==============================================================
-->
<!-- ==============================================================
-->
<!-- End Messages -->
<!-- ==============================================================
-->
<!-- ==============================================================
-->
<!-- User profile and search -->
<!-- ==============================================================
-->
<li class="nav-item dropdown">
WEB PROGRAMMING II 97
<a class="nav-link dropdown-toggle text-muted waves-effect
waves-dark pro-pic" href="" data-toggle="dropdown" aria-haspopup="true" aria-
expanded="false"><img src="assets/images/users/1.jpg" alt="user" class="rounded-circle"
width="31"></a>
<div class="dropdown-menu dropdown-menu-right user-dd
animated">
<a class="dropdown-item" href="javascript:void(0)"><i
class="ti-user m-r-5 m-l-5"></i> Profil Saya</a>
<a class="dropdown-item" href=""
onclick="event.preventDefault(); document.getElementById('keluar-app').submit();"><i
class="fa fa-power-off m-r-5 m-l-5"></i> Keluar</a>
<div class="dropdown-divider"></div>
</div>
</li>
<!-- ==============================================================
-->
<!-- User profile and search -->
<!-- ==============================================================
-->
</ul>
</div>
</nav>
</header>
<!-- ============================================================== -->
<!-- End Topbar header -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- Left Sidebar - style you can find in sidebar.scss -->
<!-- ============================================================== -->
<aside class="left-sidebar" data-sidebarbg="skin5">
<!-- Sidebar scroll-->
<div class="scroll-sidebar">
<!-- Sidebar navigation-->
<nav class="sidebar-nav">
<ul id="sidebarnav" class="p-t-30">
<li class="sidebar-item"> <a class="sidebar-link waves-effect
waves-dark sidebar-link" href="{{ route('backend.beranda') }}" aria-expanded="false"><i
class="mdi mdi-view-dashboard"></i><span class="hide-menu">Beranda</span></a>
</li>
<li class="sidebar-item"> <a class="sidebar-link waves-effect
waves-dark sidebar-link" href="{{ route('backend.user.index') }}" aria-expanded="false"><i
class="mdi mdi-account"></i><span class="hide-menu">User</span></a>
</li>
<li class="sidebar-item"> <a class="sidebar-link has-arrow waves-
effect waves-dark" href="javascript:void(0)" aria-expanded="false"><i class="mdi mdi-
shopping"></i><span class="hide-menu">Data Produk </span></a>
<ul aria-expanded="false" class="collapse first-level">
<li class="sidebar-item"><a href="icon-material.html"
class="sidebar-link"><i class="mdi mdi-chevron-right"></i><span class="hide-menu"> Kategori
</span></a>
</li>
<li class="sidebar-item"><a href="icon-fontawesome.html"
class="sidebar-link"><i class="mdi mdi-chevron-right"></i><span class="hide-menu"> Produk
</span></a>
</li>
</ul>
</li>
</ul>
</nav>
<!-- End Sidebar navigation -->
</div>
<!-- End Sidebar scroll-->
</aside>
<!-- ============================================================== -->
WEB PROGRAMMING II 98
<!-- End Left Sidebar - style you can find in sidebar.scss -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- Page wrapper -->
<!-- ============================================================== -->
<div class="page-wrapper">
<!-- ============================================================== -->
<!-- Bread crumb and right sidebar toggle -->
<!-- ============================================================== -->
WEB PROGRAMMING II 99
<script src="{{ asset('backend/libs/perfect-scrollbar/dist/perfect-
scrollbar.jquery.min.js') }}"></script>
<script src="{{ asset('backend/extra-libs/sparkline/sparkline.js') }}"></script>
<!--Wave Effects -->
<script src="{{ asset('backend/dist/js/waves.js') }}"></script>
<!--Menu sidebar -->
<script src="{{ asset('backend/dist/js/sidebarmenu.js') }}"></script>
<!--Custom JavaScript -->
<script src="{{ asset('backend/dist/js/custom.min.js') }}"></script>
<!-- this page js -->
<script src="{{ asset('backend/extra-libs/multicheck/datatable-checkbox-init.js')
}}"></script>
<script src="{{ asset('backend/extra-libs/multicheck/jquery.multicheck.js')
}}"></script>
<script src="{{ asset('backend/extra-libs/DataTables/datatables.min.js') }}"></script>
<script>
/****************************************
* Basic Table *
****************************************/
$('#zero_config').DataTable();
</script>
</html>
Gambar VII. 14
Konfirmasi Delete
Gambar VII. 15
Konfirmasi Data Berhasil di Hapus
7.7. Menerapkan Form Edit Dengan Template
1. Berikutnya adalah aksi pada Ubah, dimana ubah menggunakan function edit() pada
controller UserController
public function edit(string $id)
{
$user = User::findOrFail($id);
return view('backend.v_user.edit', [
if ($request->email != $user->email) {
$rules['email'] = 'required|max:255|email|unique:user';
}
$validatedData = $request->validate($rules, $messages);
// menggunakan ImageHelper
if ($request->file('foto')) {
//hapus gambar lama
if ($user->foto) {
$oldImagePath = public_path('storage/img-user/') . $user->foto;
if (file_exists($oldImagePath)) {
unlink($oldImagePath);
}
}
$file = $request->file('foto');
$extension = $file->getClientOriginalExtension();
$originalFileName = date('YmdHis') . '_' . uniqid() . '.' . $extension;
$directory = 'storage/img-user/';
// Simpan gambar dengan ukuran yang ditentukan
ImageHelper::uploadAndResize($file, $directory, $originalFileName, 385, 400);
// null (jika tinggi otomatis)
// Simpan nama file asli di database
$validatedData['foto'] = $originalFileName;
}
$user->update($validatedData);
return redirect()->route('backend.user.index')->with('success', 'Data berhasil
diperbaharui');
}
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="card">
<form action="{{ route('backend.user.update', $edit->id) }}" method="post"
enctype="multipart/form-data">
@method('put')
@csrf
<div class="card-body">
<h4 class="card-title"> {{$judul}} </h4>
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label>Foto</label>
{{-- view image --}}
@if ($edit->foto)
<img src="{{ asset('storage/img-user/' . $edit->foto)
}}" class="foto-preview" width="100%">
<p></p>
@else
<img src="{{ asset('storage/img-user/img-default.jpg')
}}" class="foto-preview" width="100%">
<p></p>
@endif
{{-- file foto --}}
<input type="file" name="foto" class="form-control
@error('foto') is-invalid @enderror" onchange="previewFoto()">
@error('foto')
<div class="invalid-feedback alert-danger">{{ $message
}}</div>
@enderror
</div>
</div>
<div class="col-md-8">
<div class="form-group">
<label>Hak Ases</label>
<select name="role" class="form-control @error('role')
is-invalid @enderror">
<option value="" {{ old('role', $edit->role) == ''
? 'selected' : '' }}> -
Pilih Hak Akses -</option>
<option value="1" {{ old('role', $edit->role) ==
'1' ? 'selected' : '' }}>
Super Admin</option>
<option value="0" {{ old('role', $edit->role) ==
'0' ? 'selected' : '' }}>
Admin</option>
</select>
@error('role')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Status</label>
<select name="status" class="form-control
@error('status') is-invalid @enderror">
<option value="" {{ old('status', $edit->status) ==
'' ? 'selected' : '' }}> -
Pilih Hak Akses -</option>
<div class="form-group">
<label>Nama</label>
<input type="text" name="nama" value="{{ old('nama',
$edit->nama) }}" class="form-control @error('nama') is-invalid @enderror"
placeholder="Masukkan Nama">
@error('nama')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Email</label>
<input type="text" name="email" value="{{ old('email',
$edit->email) }}" class="form-control @error('email') is-invalid @enderror"
placeholder="Masukkan Email">
@error('email')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>HP</label>
<input type="text" onkeypress="return
hanyaAngka(event)" name="hp" value="{{ old('hp', $edit->hp) }}" class="form-control
@error('hp') is-invalid @enderror" placeholder="Masukkan Nomor HP">
@error('hp')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
</div>
</div>
</div>
<div class="border-top">
<div class="card-body">
<button type="submit" class="btn btn-
primary">Perbaharui</button>
<a href="{{ route('backend.user.index') }}">
<button type="button" class="btn btn-
secondary">Kembali</button>
Gambar VII. 16
Foto User Administrator Dengan Avatar Default
Gambar VII. 17
Konfirmasi Data Berhasil Diperbaharui
</div>
</li>
<!-- ========================================================== -->
<!-- User profile and search -->
<!-- ========================================================== -->
Gambar VII. 18
Foto Avatar Tidak Tampil
Berikut perubahan script lengkapnya
<!-- ========================================================= -->
<!-- User profile and search -->
<!-- ========================================================== -->
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle text-muted waves-effect
waves-dark pro-pic" href="" data-toggle="dropdown" aria-haspopup="true" aria-
expanded="false">
@if (Auth::user()->foto)
<img src="{{ asset('storage/img-user/' . Auth::user()-
>foto) }}" alt="user" class="rounded-circle" width="31">
@else
</div>
</li>
<!-- ========================================================== -->
<!-- User profile and search -->
<!-- ========================================================== -->
Gambar VII. 19
Foto Avatar Tampil
Berikut script lengkap dari resources\views\backend\v_layouts\app.blade.php
<!DOCTYPE html>
<html dir="ltr" lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Tell the browser to be responsive to screen width -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<!-- Favicon icon -->
<link rel="icon" type="image/png" sizes="16x16" href="{{
asset('image/icon_univ_bsi.png') }}">
<title>tokoonline</title>
<body>
<!-- ============================================================== -->
<!-- Preloader - style you can find in spinners.css -->
<!-- ============================================================== -->
<div class="preloader">
<div class="lds-ripple">
<div class="lds-pos"></div>
<div class="lds-pos"></div>
</div>
</div>
<!-- ============================================================== -->
<!-- Main wrapper - style you can find in pages.scss -->
<!-- ============================================================== -->
<div id="main-wrapper">
<!-- ============================================================== -->
<!-- Topbar header - style you can find in pages.scss -->
<!-- ============================================================== -->
<header class="topbar" data-navbarbg="skin5">
<nav class="navbar top-navbar navbar-expand-md navbar-dark">
<div class="navbar-header" data-logobg="skin5">
<!-- This is for the sidebar toggle which is visible on mobile only -->
<a class="nav-toggler waves-effect waves-light d-block d-md-none"
href="javascript:void(0)"><i class="ti-menu ti-close"></i></a>
<!-- ============================================================== -->
<!-- Logo -->
<!-- ============================================================== -->
<a class="navbar-brand" href="index.html">
<!-- Logo icon -->
<b class="logo-icon p-l-10">
<!--You can put here icon as well // <i class="wi wi-
sunset"></i> //-->
<!-- Dark Logo icon -->
<img src="{{ asset('image/icon_univ_bsi.png') }}"
alt="homepage" class="light-logo" />
</b>
<!--End Logo icon -->
<!-- Logo text -->
<span class="logo-text">
<!-- dark Logo text -->
<img src="{{ asset('image/logo_text.png') }}" alt="homepage"
class="light-logo" />
</span>
<!-- Logo icon -->
<!-- <b class="logo-icon"> -->
<!--You can put here icon as well // <i class="wi wi-sunset"></i>
//-->
<!-- Dark Logo icon -->
<!-- <img src="assets/images/logo-text.png" alt="homepage"
class="light-logo" /> -->
<!-- ==============================================================
-->
<!-- Search -->
<!-- ==============================================================
-->
</ul>
<!-- ============================================================== -->
<!-- Right side toggle and nav items -->
<!-- ============================================================== -->
<ul class="navbar-nav float-right">
<!-- ==============================================================
-->
<!-- Comment -->
<!-- ==============================================================
-->
<!-- ==============================================================
-->
<!-- End Comment -->
<!-- ==============================================================
-->
<!-- ==============================================================
-->
<!-- Messages -->
<!-- ==============================================================
-->
<!-- ==============================================================
-->
<!-- End Messages -->
<!-- ==============================================================
-->
</div>
</li>
<!-- ==============================================================
-->
<!-- User profile and search -->
<!-- ==============================================================
-->
</ul>
</div>
</nav>
</header>
<!-- ============================================================== -->
<!-- End Topbar header -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- Left Sidebar - style you can find in sidebar.scss -->
<!-- ============================================================== -->
<aside class="left-sidebar" data-sidebarbg="skin5">
<!-- Sidebar scroll-->
<div class="scroll-sidebar">
<!-- Sidebar navigation-->
<nav class="sidebar-nav">
<ul id="sidebarnav" class="p-t-30">
<li class="sidebar-item"> <a class="sidebar-link waves-effect
waves-dark sidebar-link" href="{{ route('backend.beranda') }}" aria-expanded="false"><i
class="mdi mdi-view-dashboard"></i><span class="hide-menu">Beranda</span></a>
</li>
<li class="sidebar-item"> <a class="sidebar-link waves-effect
waves-dark sidebar-link" href="{{ route('backend.user.index') }}" aria-expanded="false"><i
class="mdi mdi-account"></i><span class="hide-menu">User</span></a>
</li>
<li class="sidebar-item"> <a class="sidebar-link has-arrow waves-
effect waves-dark" href="javascript:void(0)" aria-expanded="false"><i class="mdi mdi-
shopping"></i><span class="hide-menu">Data Produk </span></a>
<ul aria-expanded="false" class="collapse first-level">
<li class="sidebar-item"><a href="icon-material.html"
class="sidebar-link"><i class="mdi mdi-chevron-right"></i><span class="hide-menu"> Kategori
</span></a>
</li>
</ul>
</nav>
<!-- End Sidebar navigation -->
</div>
<!-- End Sidebar scroll-->
</aside>
<!-- ============================================================== -->
<!-- End Left Sidebar - style you can find in sidebar.scss -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- Page wrapper -->
<!-- ============================================================== -->
<div class="page-wrapper">
<!-- ============================================================== -->
<!-- Bread crumb and right sidebar toggle -->
<!-- ============================================================== -->
</html>
Latihan Mandiri 7:
Update Portofolion sertifikasi kompetensi, Impentasikan Unit Kompetensi Software
Development pada skema Menulis Kode Dengan Prinsip Sesuai Guidelines dan Best Practice,
Melakukan Debugging, Membuat Dokumen Kode Program, Menggunakan Library atau
Komponen Pre-Existing dan Menerapkan Akses Basis Data
Manajemen data master adalah proses pengelolaan data penting yang menjadi acuan utama
dalam sebuah sistem, data tersebut akurat, konsisten, dan dapat diandalkan. Dalam studi kasus
toko online, manajemen data master dapat mencakup pengelolaan berbagai jenis data seperti:
1. Kategori Produk: Informasi tentang berbagai kategori produk seperti elektronik, pakaian,
peralatan rumah tangga, dll.
2. Merek Produk: Informasi tentang merek-merek yang tersedia dalam toko online.
3. Menu: Struktur navigasi atau menu yang digunakan untuk mengelompokkan produk atau
layanan.
4. Tipe Produk: Spesifikasi atau jenis produk seperti ukuran, warna, bahan, dll.
Data-data ini digunakan sebagai acuan utama dan dihubungkan (join) dengan data produk
dalam sistem untuk memastikan bahwa setiap produk memiliki informasi yang lengkap dan
konsisten. Misalnya, setiap produk akan dihubungkan dengan kategori dan merek yang sesuai,
sehingga memudahkan dalam pengelolaan dan pencarian produk.
Dengan manajemen data master yang baik, sebuah toko online dapat memastikan bahwa
informasi produk yang ditampilkan kepada pelanggan selalu akurat dan up-to-date, serta
mendukung berbagai fungsi bisnis seperti pemasaran, penjualan, dan analisis data.
Gambar IX. 1
Migration Tabel Kategori
2. Kemudian, sesuaikan migration tabel kategori dengan Tabel IX.1. Berikut adalah Blueprint
dari tabel kategori. Jalankan migration seperti yang ditunjukkan pada Gambar IX.1.
Schema::create('kategori', function (Blueprint $table) {
$table->id();
$table->string('nama_kategori');
});
Tabel IX. 1
Tabel Kategori
Fild Tipe Data Keterangan
id Bigint Primary Key
Nama_kategori Varchar(255)
Gambar IX. 3
Model Pada Katagori
2. Script lengkap pada model Kategori sebagai berikut:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use App\Http\Controllers\KategoriController;
2. Pada sidebar, kita dapat menambahkan link pada tombol Kategori di direktori
resources/views/backend/v_layouts/app.blade.php. Jika berhasil, saat tombol Kategori
disentuh, link akan menuju http://localhost:8000/backend/kategori seperti pada Gambar IX.5.
Namun, jika tombol Kategori diklik, URL akan menuju http://localhost:8000/backend/kategori
tetapi halaman kategori akan tampil kosong (putih) seperti pada Gambar IX.6.
<li class="sidebar-item"><a href="{{ route('backend.kategori.index') }}"
class="sidebar-link"><i class="mdi mdi-chevron-right"></i><span class="hide-
menu"> Kategori </span></a>
</li>
Gambar IX. 5
Route Pada Kategori
<div class="row">
<div class="col-12">
<a href="{{ route('backend.kategori.create') }}">
<button type="button" class="btn btn-primary"><i class="fas fa-plus"></i>
Tambah</button>
</a>
<div class="card">
<div class="card-body">
<h5 class="card-title"> {{$judul}} </h5>
<div class="table-responsive">
<table id="zero_config" class="table table-striped table-bordered">
<thead>
<tr>
<th>No</th>
<th>Nama Kategori</th>
<th>Aksi</th>
</tr>
</thead>
</div>
</div>
</div>
</div>
Gambar IX. 7
Halaman Index Pada Kategori
unique:kategori berfungsi untuk menyatakan bahwa nilai nama_kategori harus unik dalam
tabel kategori. Artinya, tidak boleh ada dua atau lebih baris dalam tabel kategori yang
memiliki nilai yang sama untuk kolom nama_kategori
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="card">
<form class="form-horizontal" action="{{ route('backend.kategori.store')
}}" method="post">
@csrf
<div class="card-body">
<h4 class="card-title"> {{$judul}} </h4>
<div class="form-group">
<label>Nama Kategori</label>
<input type="text" name="nama_kategori" value="{{
old('nama_kategori') }}" class="form-control @error('nama_kategori') is-invalid @enderror"
placeholder="Masukkan Nama Kategori">
@error('nama_kategori')
<span class="invalid-feedback alert-danger" role="alert">
{{ $message }}
</div>
<div class="border-top">
<div class="card-body">
<button type="submit" class="btn btn-primary">Simpan</button>
<a href="{{ route('backend.kategori.index') }}">
<button type="button" class="btn btn-
secondary">Kembali</button>
</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
Gambar IX. 8
Form Create Kategori
Gambar IX. 9
Halaman Index Dengan Menampilkan Data Kategori
Gambar IX. 10
Konfimasi Hapus Data Pada Kategori
9.6. Halaman Edit Kategori
1. Berikutnya, kita akan melakukan perubahan data. Untuk mengubah data, kita tambahkan
script pada function edit() dan update() di KategoriController.
use App\Models\Kategori;
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
$rules = [
'nama_kategori' => 'required|max:255|unique:kategori,nama_kategori,' . $id,
];
$validatedData = $request->validate($rules);
Kategori::where('id', $id)->update($validatedData);
return redirect()->route('backend.kategori.index')->with('success', 'Data berhasil
diperbaharui');
}
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="card">
<form action="{{ route('backend.kategori.update', $edit->id) }}"
method="post">
@method('put')
@csrf
<div class="card-body">
<h4 class="card-title"> {{$judul}} </h4>
<div class="form-group">
<label>Nama Kategori</label>
<input type="text" name="nama_kategori" value="{{
old('nama_kategori', $edit->nama_kategori) }}" class="form-control @error('nama_kategori')
is-invalid @enderror" placeholder="Masukkan Nama Kategori">
@error('nama_kategori')
<span class="invalid-feedback alert-danger" role="alert">
{{ $message }}
</span>
@enderror
</div>
</div>
<div class="border-top">
<div class="card-body">
<button type="submit" class="btn btn-
primary">Perbaharui</button>
<a href="{{ route('backend.kategori.index') }}">
<button type="button" class="btn btn-
secondary">Kembali</button>
</a>
</div>
Gambar IX. 11
Form Edit Kategori
Berikut script lengkap pada controller di KategoriController sebagai berikut:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Kategori;
/**
* Show the form for creating a new resource.
*/
public function create()
{
return view('backend.v_kategori.create', [
'judul' => 'Kategori',
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
// dd($request);
$validatedData = $request->validate([
'nama_kategori' => 'required|max:255|unique:kategori',
]);
Kategori::create($validatedData);
return redirect()->route('backend.kategori.index')->with('success', 'Data berhasil
tersimpan');
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
$kategori = Kategori::find($id);
return view('backend.v_kategori.edit', [
'judul' => 'Kategori',
'edit' => $kategori
]);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
$rules = [
'nama_kategori' => 'required|max:255|unique:kategori,nama_kategori,' . $id,
];
$validatedData = $request->validate($rules);
Kategori::where('id', $id)->update($validatedData);
return redirect()->route('backend.kategori.index')->with('success', 'Data berhasil
diperbaharui');
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
$user = kategori::findOrFail($id);
$user->delete();
return redirect()->route('backend.kategori.index')->with('success', 'Data berhasil
dihapus');
}
}
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\BerandaController;
use App\Http\Controllers\LoginController;
use App\Http\Controllers\UserController;
use App\Http\Controllers\KategoriController;
Route::get('/', function () {
// return view('welcome');
return redirect()->route('backend.login');
});
Route::get('backend/beranda', [BerandaController::class, 'berandaBackend'])-
>name('backend.beranda')->middleware('auth');
// Route::resource('backend/user', UserController::class)->middleware('auth');
Route::resource('backend/user', UserController::class, ['as' => 'backend'])-
>middleware('auth');
Route::resource('backend/kategori', KategoriController::class, ['as' => 'backend'])-
>middleware('auth');
Latihan Mandiri 9:
Portofolion sertifikasi kompetensi, Impentasikan Unit Kompetensi Software Development
pada Mengimplementasikan pemrograman berorientasi objek.
Data Join Tabel di Laravel 10 adalah teknik yang digunakan untuk menggabungkan data dari
dua atau lebih tabel dalam basis data berdasarkan kolom yang terkait antara tabel-tabel tersebut.
Berikut adalah rancangan LRS (Logical Record Structure) untuk studi kasus toko online pada
Modul Web Programming II. Dalam rancangan ini, terjadi join antara tabel produk dengan
tabel kategori untuk menentukan kategori dari produk, dan tabel produk juga join dengan
tabel user untuk mengetahui siapa yang membuat produk tersebut, seperti pada gambar X.1
Gambar X. 1
LRS Toko Online Pada Web Programming II
10.1. Validasi Menggunakan Bahasa Indonesia
1. Sebelum kita masuk kepembahasan manajeman data master produk, kita konfigurasi
validasi dengan menggunakan bahasa Indonesia, pada terminal kita ketikkan
php artisan lang:publish
Gambar X. 2
Artisan Lang
2. Pada file config/app.php, ubah baris script 'locale' => 'en' menjadi 'locale' => 'id'. Kemudian,
ubah waktu menjadi waktu Asia dengan mengubah baris script 'timezone' => 'UTC' menjadi
'timezone' => 'Asia/Jakarta', seperti yang ditunjukkan pada gambar X.3
Gambar X. 4
Folder Bahasa id (Indonesia)
Gambar X. 5
Validasi Menggunakan Bahasa Indonesia
10.2. Seeder Kategori
Untuk membantu dalam mengisi record data master, seperti kategori, yang merupakan data
tetap, kita bisa menggunakan seeder. Dengan demikian, saat kita mengubah relasi tabel, record
tidak akan hilang dan tidak perlu diinput ulang melalui form. Buka file DatabaseSeeder.php
pada direktori database/seeders seperti pada gambar IX.12 & berikut script lengkap
DatabaseSeeder.php
<?php
namespace Database\Seeders;
// use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use App\Models\User;
use App\Models\Kategori;
Gambar X. 6
Seeder Kategori
Kemudian jalankan seeder dan cek data Kategori untuk memastikan data yang kita input pada
DatabaseSeeder telah sesuai.
php artisan migrate:fresh --seed
Gambar X. 7
Migration Pada Produk
2. Kemudian, sesuaikan migration tabel kategori dengan Tabel X.1. Berikut adalah Blueprint
dari tabel produk. Jalankan migration seperti yang ditunjukkan pada Gambar X.6.
Schema::create('produk', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('kategori_id');
$table->unsignedBigInteger('user_id');
$table->boolean('status');
$table->string('nama_produk');
$table->text('detail');
$table->double('harga');
$table->integer('stok');
$table->float('berat');
$table->string('foto'); // Thumbnail image
$table->timestamps();
$table->foreign('kategori_id')->references('id')->on('kategori');
$table->foreign('user_id')->references('id')->on('user');
});
Tabel X. 1
Tabel Produk
Fild Tipe Data Keterangan
id Bigint Primary Key
kategori_id Bigint
user_id Bigint
status Tinyint(1)
Nama_produk Varchar(255)
detail text
harga double
stok int
berat double
foto Varchar(255)
created_at Timestamp
updated_at Timestamp
Gambar X. 9
Model Pada Produk
2. Script lengkap pada model Produk sebagai berikut:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
Pada script produk di Laravel, belongsTo adalah metode Eloquent yang digunakan untuk
mendefinisikan relasi satu-ke-banyak terbalik (inverse one-to-many) antara model. Ini
digunakan ketika model saat ini berhubungan dengan satu entitas dari model lain. Dalam hal
ini, model Produk memiliki relasi dengan model Kategori dan User, dimana setiap produk
hanya memiliki satu kategori dan satu user yang membuatnya.
Gambar X. 10
Controller Pada ProdukController
10.6. Konfigurasi Route Pada Produk
1. Kemudian pada routes\web.php kita tambahkan script sebagai berikut
<?php
use App\Http\Controllers\ProdukController;
2. Pada sidebar, kita dapat menambahkan link pada tombol Produk di direktori
resources/views/backend/v_layouts/app.blade.php. Jika berhasil, saat tombol Kategori
disentuh, link akan menuju http://localhost:8000/backend/produk seperti pada Gambar IX.5.
<li class="sidebar-item"><a href="{{ route('backend.produk.index') }}" class="sidebar-
link"><i class="mdi mdi-chevron-right"></i><span class="hide-menu"> Produk </span></a>
</li>
use App\Models\Produk;
<div class="row">
<div class="col-12">
<a href="{{ route('backend.produk.create') }}">
<button type="button" class="btn btn-primary"><i class="fas fa-plus"></i>
Tambah</button>
</a>
<div class="card">
<div class="card-body">
<h5 class="card-title"> {{$judul}} </h5>
<div class="table-responsive">
<table id="zero_config" class="table table-striped table-bordered">
<thead>
<tbody>
@foreach ($index as $row)
<tr>
<td> {{ $loop->iteration }}</td>
<td> {{ $row->kategori->nama_kategori }} </td>
<td>
@if ($row->status ==1)
<span class="badge badge-success"></i>
Publis</span>
@elseif($row->status ==0)
<span class="badge badge-secondary"></i>
Blok</span>
@endif
</td>
<td> {{ $row->nama_produk }} </td>
<td> Rp. {{ number_format($row->harga, 0, ',', '.') }}
</td>
<td> {{ $row->stok }} </td>
<td>
<a href="{{ route('backend.produk.edit', $row->id) }}"
title="Ubah Data">
<button type="button" class="btn btn-cyan btn-
sm"><i class="far fa-edit"></i> Ubah</button>
</a>
</div>
</div>
</div>
</div>
Pemanggilan Kategori dilakukan dalam metode create karena pada halaman halaman create
produk, kita perlu menampilkan daftar kategori yang sudah ada untuk penggunan dimana
memilih kategori yang sesuai untuk produk yang akan ditambahkan. Sehingga jika perhasil
halaman create produk seperti pada gambar X.13
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="card">
<form class="form-horizontal" action="{{ route('backend.produk.store') }}"
method="post" enctype="multipart/form-data">
@csrf
<div class="card-body">
<h4 class="card-title"> {{$judul}} </h4>
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label>Foto</label>
<input type="file" name="foto" class="form-control
@error('foto') is-invalid @enderror">
@error('foto')
</div>
<div class="col-md-8">
<div class="form-group">
<label>Kategori</label>
<select class="form-control @error('kategori') is-
invalid @enderror" name="kategori_id">
<option value="" selected>--Pilih Kategori--
</option>
@foreach ($kategori as $k)
<option value="{{ $k->id }}"> {{ $k->nama_kategori
}} </option>
@endforeach
</select>
@error('kategori_id')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Nama Produk</label>
<input type="text" name="nama_produk" value="{{
old('nama_produk') }}" class="form-control @error('nama_produk') is-invalid @enderror"
placeholder="Masukkan Nama Prod">
@error('nama_produk')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Detail</label><br>
<textarea name="detail" class="form-control
@error('detail') is-invalid @enderror">{{ old('detail') }}</textarea>
@error('detail')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Harga</label>
<input type="text" onkeypress="return
hanyaAngka(event)" name="harga" value="{{ old('harga') }}" class="form-control
@error('harga') is-invalid @enderror" placeholder="Masukkan Harga Produk">
@error('harga')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Stok</label>
<input type="text" onkeypress="return
hanyaAngka(event)" name="stok" value="{{ old('stok') }}" class="form-control @error('stok')
is-invalid @enderror" placeholder="Masukkan Stok Produk">
@error('stok')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
</div>
</div>
</div>
<div class="border-top">
<div class="card-body">
<button type="submit" class="btn btn-primary">Simpan</button>
<a href="{{ route('backend.produk.index') }}">
<button type="button" class="btn btn-
secondary">Kembali</button>
</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
if ($request->file('foto')) {
$file = $request->file('foto');
$extension = $file->getClientOriginalExtension();
$originalFileName = date('YmdHis') . '_' . uniqid() . '.' . $extension;
$directory = 'storage/img-produk/';
Produk::create($validatedData, $messages);
return redirect()->route('backend.produk.index')->with('success', 'Data berhasil
tersimpan');
}
4. Tambah folder img-produk pada terminal, sehingga kita memiliki tambahan folder img-
produk dan img-user pada public/storage/ atau storage/app/public/, kemudian baru lakukkan
tambah data pada form create produk, misalnya seperti pada gambar X.14
mkdir storage/app/public/img-produk
Gambar X. 14
Tambah Data Produk
5. Jika data berhasil tersimpan pada halaman index produk tampil seperti pada gambar X.15.
Kemudian kita cek pada phpmyadmin record sudah masuk, terutama pada foto seperti pada
gambar X.16 & kita pastikan foto berhasil dibuatkan thumbnail dengan ukuran yang sudah
ditentukan pada controller, cek foto/gambar pada direktori public/storage/img-produk atau
Gambar X. 15
Halaman Index dengan Data Produk
Gambar X. 16
Foto Berhasil Tersimpan
Gambar XI. 1
JavaScript Preview Gambar
2. Sehingga pada create.blade.php di dalam ProdukController, terdapat perubahan di mana
input type="file" diarahkan ke JavaScript untuk preview gambar.
Sebelumnya
<div class="form-group">
<label>Foto</label>
<input type="file" name="foto" class="form-control @error('foto') is-invalid
@enderror">
@error('foto')
<div class="invalid-feedback alert-danger">{{ $message }}</div>
@enderror
</div>
Menjadi
<div class="form-group">
<label>Foto</label>
<img class="foto-preview">
<input type="file" name="foto" class="form-control @error('foto') is-invalid @enderror"
onchange="previewFoto()">
@error('foto')
<div class="invalid-feedback alert-danger">{{ $message }}</div>
@enderror
</div>
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="card">
<form class="form-horizontal" action="{{ route('backend.produk.store') }}"
method="post" enctype="multipart/form-data">
@csrf
<div class="card-body">
<h4 class="card-title"> {{$judul}} </h4>
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label>Foto</label>
<img class="foto-preview">
<input type="file" name="foto" class="form-control
@error('foto') is-invalid @enderror" onchange="previewFoto()">
@error('foto')
<div class="invalid-feedback alert-danger">{{ $message
}}</div>
@enderror
</div>
</div>
<div class="col-md-8">
<div class="form-group">
<label>Kategori</label>
<select class="form-control @error('kategori') is-
invalid @enderror" name="kategori_id">
<option value="" selected>--Pilih Kategori--
</option>
@foreach ($kategori as $k)
<option value="{{ $k->id }}"> {{ $k->nama_kategori
}} </option>
@endforeach
</select>
@error('kategori_id')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Nama Produk</label>
<input type="text" name="nama_produk" value="{{
old('nama_produk') }}" class="form-control @error('nama_produk') is-invalid @enderror"
placeholder="Masukkan Nama Prod">
@error('nama_produk')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Harga</label>
<input type="text" onkeypress="return
hanyaAngka(event)" name="harga" value="{{ old('harga') }}" class="form-control
@error('harga') is-invalid @enderror" placeholder="Masukkan Harga Produk">
@error('harga')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Berat</label>
<input type="text" onkeypress="return
hanyaAngka(event)" name="berat" value="{{ old('berat') }}" class="form-control
@error('berat') is-invalid @enderror" placeholder="Masukkan Berat Produk">
@error('berat')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Stok</label>
<input type="text" onkeypress="return
hanyaAngka(event)" name="stok" value="{{ old('stok') }}" class="form-control @error('stok')
is-invalid @enderror" placeholder="Masukkan Stok Produk">
@error('stok')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
</div>
</div>
</div>
<div class="border-top">
<div class="card-body">
<button type="submit" class="btn btn-primary">Simpan</button>
<a href="{{ route('backend.produk.index') }}">
<button type="button" class="btn btn-
secondary">Kembali</button>
</a>
</div>
</div>
</form>
</div>
</div>
</div>
Gambar XI. 2
Preview Gambar Pada Create Produk
11.2. Menggunakan CKEditor
CKEditor adalah salah satu WYSIWYG (What You See Is What You Get) editor terpopuler
yang digunakan untuk mengedit teks dalam aplikasi web. Dalam materi ini, akan dibahas
mengenai pengenalan CKEditor, cara instalasi, dan implementasi dasar pada sebuah form di
aplikasi web. CKEditor alat yang memungkinkan pengguna untuk menulis dan mengedit teks
dalam konten rich text (teks dengan format HTML) dengan mudah melalui antarmuka grafis,
tanpa perlu pengetahuan HTML yang mendalam. Ini banyak digunakan di berbagai aplikasi
web untuk keperluan blogging, pembuatan konten, dan pengelolaan dokumen. CKEditor
mendukung berbagai fitur seperti penambahan gambar, tabel, tautan, dan format teks,
menjadikannya pilihan yang kuat untuk aplikasi web yang membutuhkan editor teks yang
lengkap
1. siapkan CKeditor bisa langsung memanggil ckeditor.js yakni pada situs resmi
https://cdn.ckeditor.com/ckeditor5/30.0.0/classic/ckeditor.js atau dengan cara download yang
telah tersedia https://bit.ly/LaravelWebPro2 dengan nama file ckeditor.zip kemudian extrak
ckeditor pada direktori TokoOnline\public seperti pada gambar XI.3
2. Kemudian panggil komponen ckeditor pada app.blade.php di direktori
resources\views\backend\v_layouts\ seperti pada gambar XI.4
<script src="{{ asset('ckeditor/ckeditor.js') }}"></script>
<!-- <script
src="https://cdn.ckeditor.com/ckeditor5/30.0.0/classic/ckeditor.js"></script> -->
<script>
ClassicEditor
.create(document.querySelector('#ckeditor'))
.catch(error => {
console.error(error);
});
</script>
Gambar XI. 4
Memanggil ckeditor.js
3. Sekarang kita dapat memastikan apakah ckeditor sudah dapat berhasil kita gunakan, pada
form yakni pada text, misalnya seperti pada text dengan label Detail, kita tambahkan ID=
“ckeditor”
<textarea name="detail" class="form-control @error('detail') is-invalid @enderror">{{
old('detail') }}</textarea>
Menjadi
Berikut script lengkap pada create.blade.php pada ProdukController, dan jika berhasil
akan tampil seperti pada gambar XI.5
@extends('backend.v_layouts.app')
@section('content')
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="card">
<form class="form-horizontal" action="{{ route('backend.produk.store') }}"
method="post" enctype="multipart/form-data">
@csrf
<div class="card-body">
<h4 class="card-title"> {{$judul}} </h4>
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label>Foto</label>
<img class="foto-preview">
<input type="file" name="foto" class="form-control
@error('foto') is-invalid @enderror" onchange="previewFoto()">
@error('foto')
<div class="invalid-feedback alert-danger">{{ $message
}}</div>
@enderror
</div>
</div>
<div class="col-md-8">
<div class="form-group">
<label>Kategori</label>
<select class="form-control @error('kategori') is-
invalid @enderror" name="kategori_id">
<option value="" selected>--Pilih Kategori--
</option>
@foreach ($kategori as $k)
<option value="{{ $k->id }}"> {{ $k->nama_kategori
}} </option>
@endforeach
</select>
@error('kategori_id')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Nama Produk</label>
<input type="text" name="nama_produk" value="{{
old('nama_produk') }}" class="form-control @error('nama_produk') is-invalid @enderror"
placeholder="Masukkan Nama Prod">
@error('nama_produk')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Detail</label><br>
<textarea name="detail" class="form-control
@error('detail') is-invalid @enderror" id="ckeditor">{{ old('detail') }}</textarea>
@error('detail')
<span class="invalid-feedback alert-danger"
role="alert">
<div class="form-group">
<label>Harga</label>
<input type="text" onkeypress="return
hanyaAngka(event)" name="harga" value="{{ old('harga') }}" class="form-control
@error('harga') is-invalid @enderror" placeholder="Masukkan Harga Produk">
@error('harga')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Berat</label>
<input type="text" onkeypress="return
hanyaAngka(event)" name="berat" value="{{ old('berat') }}" class="form-control
@error('berat') is-invalid @enderror" placeholder="Masukkan Berat Produk">
@error('berat')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Stok</label>
<input type="text" onkeypress="return
hanyaAngka(event)" name="stok" value="{{ old('stok') }}" class="form-control @error('stok')
is-invalid @enderror" placeholder="Masukkan Stok Produk">
@error('stok')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
</div>
</div>
</div>
<div class="border-top">
<div class="card-body">
<button type="submit" class="btn btn-primary">Simpan</button>
<a href="{{ route('backend.produk.index') }}">
<button type="button" class="btn btn-
secondary">Kembali</button>
</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
Gambar XI. 6
Migration Foto Produk
2. Dengan Blueprint tabel sebagai berikut:
Schema::create('foto_produk', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('produk_id');
$table->string('foto');
$table->timestamps();
$table->foreign('produk_id')->references('id')->on('produk')-
>onDelete('cascade');
});
Tabel XI. 1
Tabel Foto_Produk
Fild Tipe Data Keterangan
id Bigint Primary Key
produk_id Bigint
foto Varchar(255)
created_at Timestamp
updated_at Timestamp
Gambar XI. 7
Migrations Pada FotoProduk
11.3. Model Pada Foto Produk
1. Pada terminal buat model dengan nama FotoProduk sebagai berikut:
php artisan make:model FotoProduk
Gambar XI. 8
Model Pada FotoProduk
2. Berikut script model pada FotoProduk
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
3. Sehingga pada model Produk kita tambahkan untuk memanggil FotoProduk, berikut script
lengkap pada Produk
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-body">
<h4 class="card-title">{{ $judul }}</h4>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label>Kategori</label>
<select name="kategori_id" class="form-control
@error('kategori_id') is-invalid @enderror" disabled>
<option value="" selected> - Pilih Kategori - </option>
@foreach ($kategori as $row)
<option value="{{ $row->id }}" {{ old('kategori_id',
$show->kategori_id) == $row->id ? 'selected' : '' }}>
{{ $row->nama_kategori }}
</option>
@endforeach
</select>
@error('kategori_id')
<span class="invalid-feedback alert-danger" role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Nama Produk</label>
<input type="text" name="nama_produk" value="{{
old('nama_produk', $show->nama_produk) }}" class="form-control @error('nama_produk') is-
invalid @enderror" placeholder="Masukkan Nama Produk" disabled>
@error('nama_produk')
<span class="invalid-feedback alert-danger" role="alert">
{{ $message }}
<div class="form-group">
<label>Detail</label>
<textarea name="detail" class="form-control
@error('detail') is-invalid @enderror" id="ckeditor" disabled>{{ old('detail', $show-
>detail) }}</textarea>
@error('detail')
<span class="invalid-feedback alert-danger" role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Foto Utama</label> <br>
<img src="{{ asset('storage/img-produk/' . $show->foto) }}"
class="foto-preview" width="100%">
</div>
</div>
<div class="col-md-6">
<label>Foto Tambahan</label>
<div id="foto-container">
<div class="row">
@foreach($show->gambar as $gambar)
<div class="col-md-8">
<img src="{{ asset('storage/img-produk/' . $gambar-
>foto) }}" width="100%">
</div>
<div class="col-md-4">
<form action="{{
route('backend.foto_produk.destroy', $gambar->id) }}" method="post">
@csrf
@method('delete')
<button type="submit" class="btn btn-
danger">Hapus</button>
</form>
</div>
@endforeach
</div>
<br>
</div>
<button type="button" class="btn btn-primary add-foto mt-
2">Tambah Foto</button>
</div>
</div>
</div>
<div class="border-top">
<div class="card-body">
<a href="{{ route('backend.produk.index') }}">
<button type="button" class="btn btn-
secondary">Kembali</button>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const fotoContainer = document.getElementById('foto-container');
const addFotoButton = document.querySelector('.add-foto');
addFotoButton.addEventListener('click', function() {
const fotoRow = document.createElement('div');
fotoRow.classList.add('form-group', 'row');
fotoRow.innerHTML = `
<form action="{{ route('backend.foto_produk.store') }}" method="post"
enctype="multipart/form-data">
@csrf
<div class="col-md-12">
<input type="hidden" name="produk_id" value="{{ $show->id }}">
<input type="file" name="foto_produk[]" class="form-control
@error('foto_produk') is-invalid @enderror">
<button type="submit" class="btn btn-success">Simpan</button>
</div>
</form>
`;
fotoContainer.appendChild(fotoRow);
});
});
</script>
3. Agar kita dapat memanggil view show() aksi ini kita tambahkan pada view index() pada
direktori resources/views/v_produk, dimana aksi +Gambar seperti pada gambar XI.9 & jika
di klik aksi +Gambar maka seperti pada gambar XI.10
<a href="{{ route('backend.produk.show', $row->id) }}" title="Ubah Data">
<button type="button" class="btn btn-
warning btn-sm"><i class="fas fa-plus"></i> Gambar</button>
</a>
<div class="row">
<div class="col-12">
<a href="{{ route('backend.produk.create') }}">
<button type="button" class="btn btn-primary"><i class="fas fa-plus"></i>
Tambah</button>
</a>
<div class="card">
<div class="card-body">
<h5 class="card-title"> {{$judul}} </h5>
<div class="table-responsive">
<table id="zero_config" class="table table-striped table-bordered">
<thead>
<tr>
<th>No</th>
<th>Kategori</th>
<th>Status</th>
<th>Nama Produk</th>
<th>Harga</th>
<th>Stok</th>
<th>Aksi</th>
</tr>
<tbody>
@foreach ($index as $row)
<tr>
<td> {{ $loop->iteration }}</td>
<td> {{ $row->kategori->nama_kategori }} </td>
<td>
@if ($row->status ==1)
<span class="badge badge-success"></i>
Publis</span>
@elseif($row->status ==0)
<span class="badge badge-secondary"></i>
Blok</span>
@endif
</td>
<td> {{ $row->nama_produk }} </td>
<td> Rp. {{ number_format($row->harga, 0, ',', '.') }}
</td>
<td> {{ $row->stok }} </td>
<td>
<a href="{{ route('backend.produk.edit', $row->id) }}"
title="Ubah Data">
<button type="button" class="btn btn-cyan btn-
sm"><i class="far fa-edit"></i> Ubah</button>
</a>
<a href="{{ route('backend.produk.show', $row->id) }}"
title="Ubah Data">
<button type="button" class="btn btn-warning btn-
sm"><i class="fas fa-plus"></i> Gambar</button>
</a>
</div>
</div>
</div>
</div>
Gambar XI. 10
Halaman Detail Produk
4. Sebelum kita menambahkan Foto Tambahan, tambahkan script pada fungsi storeFoto dan
destroyFoto di ProdukController. Dengan demikian, saat kita mengklik Tambah Foto ->
Pilih gambar -> klik tombol Simpan, data akan tersimpan. Selain itu, terdapat aksi Hapus
untuk menghapus data foto yang tidak diperlukan. Terlihat seperti pada gambar XI.11
// Method untuk menyimpan foto tambahan
public function storeFoto(Request $request)
{
// Validasi input
$request->validate([
'produk_id' => 'required|exists:produk,id',
'foto_produk.*' => 'image|mimes:jpeg,jpg,png,gif|file|max:1024',
]);
5. Pada untuk menambahkan routes\web.php dengan script lengkap sebagai berikut sehingga:
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\BerandaController;
use App\Http\Controllers\LoginController;
use App\Http\Controllers\UserController;
use App\Http\Controllers\KategoriController;
use App\Http\Controllers\ProdukController;
Route::get('/', function () {
// return view('welcome');
return redirect()->route('backend.login');
});
Route::get('backend/beranda', [BerandaController::class, 'berandaBackend'])-
>name('backend.beranda')->middleware('auth');
// Route::resource('backend/user', UserController::class)->middleware('auth');
Gambar XI. 11
Foto Tambahan Pada Produk
11.5. Ubah Data Pada Produk
1. Tambahkan function edit dan function update pada ProdukController, berikut script
lengkapnya
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
$produk = Produk::findOrFail($id);
$kategori = Kategori::orderBy('nama_kategori', 'asc')->get();
return view('backend.v_produk.edit', [
'judul' => 'Ubah Produk',
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//ddd($request);
$produk = Produk::findOrFail($id);
$rules = [
'nama_produk' => 'required|max:255|unique:produk,nama_produk,' . $id,
'kategori_id' => 'required',
'status' => 'required',
'detail' => 'required',
'harga' => 'required',
'berat' => 'required',
'stok' => 'required',
'foto' => 'image|mimes:jpeg,jpg,png,gif|file|max:1024',
];
$messages = [
'foto.image' => 'Format gambar gunakan file dengan ekstensi jpeg, jpg, png,
atau gif.',
'foto.max' => 'Ukuran file gambar Maksimal adalah 1024 KB.'
];
$validatedData['user_id'] = auth()->id();
$validatedData = $request->validate($rules, $messages);
if ($request->file('foto')) {
//hapus gambar lama
if ($produk->foto) {
$oldImagePath = public_path('storage/img-produk/') . $produk->foto;
if (file_exists($oldImagePath)) {
unlink($oldImagePath);
}
$oldThumbnailLg = public_path('storage/img-produk/') . 'thumb_lg_' .
$produk->foto;
if (file_exists($oldThumbnailLg)) {
unlink($oldThumbnailLg);
}
$oldThumbnailMd = public_path('storage/img-produk/') . 'thumb_md_' .
$produk->foto;
if (file_exists($oldThumbnailMd)) {
unlink($oldThumbnailMd);
}
$oldThumbnailSm = public_path('storage/img-produk/') . 'thumb_sm_' .
$produk->foto;
if (file_exists($oldThumbnailSm)) {
unlink($oldThumbnailSm);
}
}
$file = $request->file('foto');
$extension = $file->getClientOriginalExtension();
$originalFileName = date('YmdHis') . '_' . uniqid() . '.' . $extension;
$directory = 'storage/img-produk/';
$produk->update($validatedData);
return redirect()->route('backend.produk.index')->with('success', 'Data berhasil
diperbaharui');
}
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="card">
<form action="{{ route('backend.produk.update', $edit->id) }}"
method="post" enctype="multipart/form-data">
@method('put')
@csrf
<div class="card-body">
<h4 class="card-title"> {{$judul}} </h4>
<div class="row">
<div class="col-md-4">
<div class="form-group">
<label>Foto</label>
{{-- view image --}}
@if ($edit->foto)
<img src="{{ asset('storage/img-produk/' . $edit->foto)
}}" class="foto-preview" width="100%">
<p></p>
@else
<img src="{{ asset('storage/img-produk/img-
default.jpg') }}" class="foto-preview" width="100%">
<p></p>
@endif
{{-- file foto --}}
<input type="file" name="foto" class="form-control
@error('foto') is-invalid @enderror" onchange="previewFoto()">
@error('foto')
<div class="invalid-feedback alert-danger">{{ $message
}}</div>
@enderror
</div>
</div>
<div class="col-md-8">
<div class="form-group">
<label>Status</label>
<div class="form-group">
<label>Kategori</label>
<select name="kategori_id" class="form-control
@error('kategori_id') is-invalid @enderror">
<option value="" selected> - Pilih Katagori -
</option>
@foreach ($kategori as $row)
@if (old('kategori_id', $edit->kategori_id) ==
$row->id)
<option value="{{ $row->id }}" selected> {{ $row-
>nama_kategori }} </option>
@else
<option value="{{ $row->id }}"> {{ $row->nama_type
}} </option>
@endif
@endforeach
</select>
@error('kategori_id')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Nama Produk</label>
<input type="text" name="nama_produk" value="{{
old('nama_produk',$edit->nama_produk) }}" class="form-control @error('nama_produk') is-
invalid @enderror" placeholder="Masukkan Nama Prod">
@error('nama_produk')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Detail</label><br>
<textarea name="detail" class="form-control
@error('detail') is-invalid @enderror" id="ckeditor">{{ old('detail',$edit->detail)
}}</textarea>
@error('detail')
<span class="invalid-feedback alert-danger"
role="alert">
<div class="form-group">
<label>Harga</label>
<input type="text" onkeypress="return
hanyaAngka(event)" name="harga" value="{{ old('harga',$edit->harga) }}" class="form-control
@error('harga') is-invalid @enderror" placeholder="Masukkan Harga Produk">
@error('harga')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Berat</label>
<input type="text" onkeypress="return
hanyaAngka(event)" name="berat" value="{{ old('berat', $edit->berat) }}" class="form-
control @error('berat') is-invalid @enderror" placeholder="Masukkan Berat Produk">
@error('berat')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Stok</label>
<input type="text" onkeypress="return
hanyaAngka(event)" name="stok" value="{{ old('stok',$edit->stok) }}" class="form-control
@error('stok') is-invalid @enderror" placeholder="Masukkan Stok Produk">
@error('stok')
<span class="invalid-feedback alert-danger"
role="alert">
{{ $message }}
</span>
@enderror
</div>
</div>
</div>
</div>
<div class="border-top">
<div class="card-body">
<button type="submit" class="btn btn-
primary">Perbaharui</button>
<a href="{{ route('backend.produk.index') }}">
<button type="button" class="btn btn-
secondary">Kembali</button>
</a>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
if ($produk->foto) {
// Hapus gambar asli
$oldImagePath = $directory . $produk->foto;
if (file_exists($oldImagePath)) {
unlink($oldImagePath);
}
// Hapus thumbnail lg
$thumbnailLg = $directory . 'thumb_lg_' . $produk->foto;
if (file_exists($thumbnailLg)) {
unlink($thumbnailLg);
}
// Hapus thumbnail md
$thumbnailMd = $directory . 'thumb_md_' . $produk->foto;
if (file_exists($thumbnailMd)) {
unlink($thumbnailMd);
}
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Produk;
use App\Models\Kategori;
use App\Models\FotoProduk;
use App\Helpers\ImageHelper;
/**
* Show the form for creating a new resource.
*/
public function create()
{
$kategori = Kategori::orderBy('nama_kategori', 'asc')->get();
return view('backend.v_produk.create', [
'judul' => 'Tambah Produk',
'kategori' => $kategori
]);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$validatedData = $request->validate([
'kategori_id' => 'required',
'nama_produk' => 'required|max:255|unique:produk',
'detail' => 'required',
'harga' => 'required',
'berat' => 'required',
'stok' => 'required',
'foto' => 'required|image|mimes:jpeg,jpg,png,gif|file|max:1024',
], $messages = [
'foto.image' => 'Format gambar gunakan file dengan ekstensi jpeg, jpg, png,
atau gif.',
'foto.max' => 'Ukuran file gambar Maksimal adalah 1024 KB.'
]);
$validatedData['user_id'] = auth()->id();
$validatedData['status'] = 0;
Produk::create($validatedData, $messages);
return redirect()->route('backend.produk.index')->with('success', 'Data berhasil
tersimpan');
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
$produk = Produk::with('fotoProduk')->findOrFail($id);
$kategori = Kategori::orderBy('nama_kategori', 'asc')->get();
return view('backend.v_produk.show', [
'judul' => 'Detail Produk',
'show' => $produk,
'kategori' => $kategori
]);
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
$produk = Produk::findOrFail($id);
$kategori = Kategori::orderBy('nama_kategori', 'asc')->get();
return view('backend.v_produk.edit', [
'judul' => 'Ubah Produk',
'edit' => $produk,
'kategori' => $kategori
]);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//ddd($request);
$produk = Produk::findOrFail($id);
if ($request->file('foto')) {
//hapus gambar lama
if ($produk->foto) {
$oldImagePath = public_path('storage/img-produk/') . $produk->foto;
if (file_exists($oldImagePath)) {
unlink($oldImagePath);
}
$oldThumbnailLg = public_path('storage/img-produk/') . 'thumb_lg_' .
$produk->foto;
if (file_exists($oldThumbnailLg)) {
unlink($oldThumbnailLg);
}
$oldThumbnailMd = public_path('storage/img-produk/') . 'thumb_md_' .
$produk->foto;
if (file_exists($oldThumbnailMd)) {
unlink($oldThumbnailMd);
}
$oldThumbnailSm = public_path('storage/img-produk/') . 'thumb_sm_' .
$produk->foto;
if (file_exists($oldThumbnailSm)) {
unlink($oldThumbnailSm);
}
}
$file = $request->file('foto');
$extension = $file->getClientOriginalExtension();
$originalFileName = date('YmdHis') . '_' . uniqid() . '.' . $extension;
$directory = 'storage/img-produk/';
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
$produk = Produk::findOrFail($id);
$directory = public_path('storage/img-produk/');
if ($produk->foto) {
// Hapus gambar asli
$oldImagePath = $directory . $produk->foto;
if (file_exists($oldImagePath)) {
unlink($oldImagePath);
}
// Hapus thumbnail lg
$thumbnailLg = $directory . 'thumb_lg_' . $produk->foto;
if (file_exists($thumbnailLg)) {
unlink($thumbnailLg);
}
// Hapus thumbnail md
$thumbnailMd = $directory . 'thumb_md_' . $produk->foto;
if (file_exists($thumbnailMd)) {
unlink($thumbnailMd);
}
// Hapus thumbnail sm
$thumbnailSm = $directory . 'thumb_sm_' . $produk->foto;
if (file_exists($thumbnailSm)) {
unlink($thumbnailSm);
}
}
$produk->delete();
Pada pembuatan manajemen laporan data master, kita tidak membuat controller baru,
melainkan hanya menambahkan fungsi seperti formProduk dan cetakProduk. Fungsi
formProduk digunakan untuk menampilkan tampilan form filter laporan berdasarkan tanggal
awal dan tanggal akhir. Sedangkan cetakProduk digunakan untuk menampilkan hasil filter dari
form laporan tersebut.
$tanggalAwal = $request->input('tanggal_awal');
$tanggalAkhir = $request->input('tanggal_akhir');
$user = $query->get();
return view('backend.v_user.cetak', [
'judul' => 'Laporan User',
'tanggalAwal' => $tanggalAwal,
'tanggalAkhir' => $tanggalAkhir,
'cetak' => $user
]);
}
<div class="row">
<div class="col-12">
<div class="card">
<form class="form-horizontal" action="{{ route('backend.laporan.cetakuser') }}"
method="post" target="_blank">
@csrf
<div class="form-group">
<label>Tanggal Awal</label>
<input type="date" name="tanggal_awal" onkeypress="return
hanyaAngka(event)" value="{{ old('tanggal_awal') }}" class="form-control
@error('tanggal_awal') is-invalid @enderror" placeholder="Masukkan Jumlah Pinjam">
@error('tanggal_awal')
<span class="invalid-feedback alert-danger" role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Tanggal Akhir</label>
<input type="date" name="tanggal_akhir" onkeypress="return
hanyaAngka(event)" value="{{ old('tanggal_akhir') }}" class="form-control
@error('tanggal_akhir') is-invalid @enderror" placeholder="Masukkan Jumlah Pinjam">
@error('tanggal_akhir')
<span class="invalid-feedback alert-danger" role="alert">
{{ $message }}
</span>
@enderror
</div>
<br>
<button type="submit" class="btn btn-primary">Cetak</button>
</form>
</div>
</div>
</div>
Gambar XII. 1
Form Pada Manajemen Laporan Data User
table tr td {
padding: 6px;
font-weight: normal;
border: 1px solid #ccc;
}
table th {
border: 1px solid #ccc;
}
</style>
<table>
<!-- <tr>
<td align="center">
<img src="{{ asset('images/header.png') }}" width="50%">
</td>
</tr> -->
<tr>
<td align="left">
Perihal : {{ $judul }} <br>
Tanggal Awal: {{ $tanggalAwal }} s/d Tanggal Akhir: {{ $tanggalAkhir }}
</td>
</tr>
</table>
<p></p>
<table>
<thead>
<tr>
<th>No</th>
<th>Email</th>
<th>Nama</th>
<th>Role</th>
<th>Status</th>
</tr>
</thead>
<tbody>
@foreach ($cetak as $row)
<tr>
<td> {{ $loop->iteration }} </td>
<td> {{$row->nama}} </td>
<td> {{$row->email}} </td>
<td>
@if ($row->role == 1)
Super Admin
@elseif($row->role == 0)
Admin
@endif
</td>
<td>
@if ($row->status ==1)
Aktif
@elseif($row->status ==0)
NonAktif
@endif
</td>
</tr>
@endforeach
<script>
window.onload = function() {
printStruk();
}
function printStruk() {
window.print();
}
</script>
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\BerandaController;
use App\Http\Controllers\LoginController;
use App\Http\Controllers\UserController;
use App\Http\Controllers\KategoriController;
use App\Http\Controllers\ProdukController;
Route::get('/', function () {
// return view('welcome');
return redirect()->route('backend.login');
});
Route::get('backend/beranda', [BerandaController::class, 'berandaBackend'])-
>name('backend.beranda')->middleware('auth');
5. Tambahkan pada sidebar manajemen laporan data User yakni app.blade.php pada direktori
resources\views\backend\ v_layouts\backend\. Jika berhasil, tampilan akan seperti pada
Gambar XII.2 untuk melihat filter form laporan. Jika tombol cetak diklik, halaman browser
baru akan terbuka dan menampilkan cetakan data yang diinginkan, seperti pada gambar XII.3
<li class="sidebar-item"> <a class="sidebar-link has-arrow waves-effect waves-dark"
href="javascript:void(0)" aria-expanded="false"><i class="mdi mdi-receipt"></i><span
class="hide-menu">Laporan </span></a>
<ul aria-expanded="false" class="collapse first-level">
<li class="sidebar-item"><a href="{{
route('backend.laporan.formuser') }}" class="sidebar-link"><i class="mdi mdi-chevron-
right"></i><span class="hide-menu"> User </span></a></li>
<li class="sidebar-item"><a href="error-404.html"
class="sidebar-link"><i class="mdi mdi-chevron-right"></i><span class="hide-menu"> Produk
</span></a></li>
</ul>
</li>
Gambar XII. 2
Halaman Laporan Data User
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use App\Helpers\ImageHelper;
/**
* Show the form for creating a new resource.
*/
public function create()
{
return view('backend.v_user.create', [
'judul' => 'Tambah User',
]);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
// menggunakan ImageHelper
if ($request->file('foto')) {
$file = $request->file('foto');
$extension = $file->getClientOriginalExtension();
$originalFileName = date('YmdHis') . '_' . uniqid() . '.' . $extension;
$directory = 'storage/img-user/';
// Simpan gambar dengan ukuran yang ditentukan
ImageHelper::uploadAndResize($file, $directory, $originalFileName, 385, 400);
// null (jika tinggi otomatis)
// Simpan nama file asli di database
$validatedData['foto'] = $originalFileName;
}
// password
$password = $request->input('password');
$pattern = '/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[\W_]).+$/';
// huruf kecil ([a-z]), huruf besar ([A-Z]), dan angka (\d) (?=.*[\W_]) simbol
karakter (non-alphanumeric)
if (preg_match($pattern, $password)) {
$validatedData['password'] = Hash::make($validatedData['password']);
User::create($validatedData, $messages);
return redirect()->route('backend.user.index')->with('success', 'Data berhasil
tersimpan');
} else {
return redirect()->back()->withErrors(['password' => 'Password harus terdiri
dari kombinasi huruf besar, huruf kecil, angka, dan simbol karakter.']);
}
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
$user = User::findOrFail($id);
return view('backend.v_user.edit', [
'judul' => 'Ubah User',
'edit' => $user
]);
}
/**
* Update the specified resource in storage.
if ($request->email != $user->email) {
$rules['email'] = 'required|max:255|email|unique:user';
}
$validatedData = $request->validate($rules, $messages);
// menggunakan ImageHelper
if ($request->file('foto')) {
//hapus gambar lama
if ($user->foto) {
$oldImagePath = public_path('storage/img-user/') . $user->foto;
if (file_exists($oldImagePath)) {
unlink($oldImagePath);
}
}
$file = $request->file('foto');
$extension = $file->getClientOriginalExtension();
$originalFileName = date('YmdHis') . '_' . uniqid() . '.' . $extension;
$directory = 'storage/img-user/';
// Simpan gambar dengan ukuran yang ditentukan
ImageHelper::uploadAndResize($file, $directory, $originalFileName, 385, 400);
// null (jika tinggi otomatis)
// Simpan nama file asli di database
$validatedData['foto'] = $originalFileName;
}
$user->update($validatedData);
return redirect()->route('backend.user.index')->with('success', 'Data berhasil
diperbaharui');
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
$user = user::findOrFail($id);
if ($user->foto) {
$oldImagePath = public_path('storage/img-user/') . $user->foto;
if (file_exists($oldImagePath)) {
unlink($oldImagePath);
}
}
$user->delete();
return redirect()->route('backend.user.index')->with('success', 'Data berhasil
dihapus');
}
$tanggalAwal = $request->input('tanggal_awal');
$tanggalAkhir = $request->input('tanggal_akhir');
$user = $query->get();
return view('backend.v_user.cetak', [
'judul' => 'Laporan User',
'tanggalAwal' => $tanggalAwal,
'tanggalAkhir' => $tanggalAkhir,
'cetak' => $user
]);
}
}
$tanggalAwal = $request->input('tanggal_awal');
$tanggalAkhir = $request->input('tanggal_akhir');
$produk = $query->get();
return view('backend.v_produk.cetak', [
'judul' => 'Laporan Produk',
'tanggalAwal' => $tanggalAwal,
'tanggalAkhir' => $tanggalAkhir,
'cetak' => $produk
]);
}
2. Sehingga pada view kita tambahkan file form.blade.php pada direktori resources/
views/v_produk
@extends('backend.v_layouts.app')
@section('content')
<!-- template -->
<div class="row">
<div class="col-12">
<div class="card">
<form class="form-horizontal" action="{{ route('backend.laporan.cetakproduk')
}}" method="post" target="_blank">
@csrf
<div class="card-body">
<h4 class="card-title"> {{$judul}} </h4>
<div class="form-group">
<label>Tanggal Awal</label>
<input type="date" name="tanggal_awal" onkeypress="return
hanyaAngka(event)" value="{{ old('tanggal_awal') }}" class="form-control
@error('tanggal_awal') is-invalid @enderror" placeholder="Masukkan Jumlah Pinjam">
@error('tanggal_awal')
<span class="invalid-feedback alert-danger" role="alert">
{{ $message }}
</span>
@enderror
</div>
<div class="form-group">
<label>Tanggal Akhir</label>
<input type="date" name="tanggal_akhir" onkeypress="return
hanyaAngka(event)" value="{{ old('tanggal_akhir') }}" class="form-control
@error('tanggal_akhir') is-invalid @enderror" placeholder="Masukkan Jumlah Pinjam">
@error('tanggal_akhir')
<span class="invalid-feedback alert-danger" role="alert">
{{ $message }}
</span>
@enderror
</div>
<br>
<button type="submit" class="btn btn-primary">Cetak</button>
</form>
</div>
</div>
</div>
table tr td {
padding: 6px;
font-weight: normal;
border: 1px solid #ccc;
}
table th {
border: 1px solid #ccc;
}
</style>
<table>
<!-- <tr>
<td align="center">
<img src="{{ asset('images/header.png') }}" width="50%">
</td>
</tr> -->
<tr>
<td align="left">
Perihal : {{ $judul }} <br>
Tanggal Awal: {{ $tanggalAwal }} s/d Tanggal Akhir: {{ $tanggalAkhir }}
</td>
</tr>
</table>
<p></p>
<table>
<thead>
<tr>
<th>No</th>
<th>Kategori</th>
<th>Status</th>
<th>Nama Produk</th>
<th>Harga</th>
<th>Stok</th>
</tr>
</thead>
<tbody>
@foreach ($cetak as $row)
<tr>
<td> {{ $loop->iteration }}</td>
<td> {{ $row->kategori->nama_kategori }} </td>
<td>
@if ($row->status ==1)
Publis
@elseif($row->status ==0)
Blok
@endif
</td>
<td> {{ $row->nama_produk }} </td>
<td> Rp. {{ number_format($row->harga, 0, ',', '.') }} </td>
<td> {{ $row->stok }} </td>
</tr>
@endforeach
</tbody>
</table>
function printStruk() {
window.print();
}
</script>
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\BerandaController;
use App\Http\Controllers\LoginController;
use App\Http\Controllers\UserController;
use App\Http\Controllers\KategoriController;
use App\Http\Controllers\ProdukController;
Route::get('/', function () {
// return view('welcome');
return redirect()->route('backend.login');
});
Route::get('backend/beranda', [BerandaController::class, 'berandaBackend'])-
>name('backend.beranda')->middleware('auth');
5. Tambahkan pada sidebar manajemen laporan Produk yakni app.blade.php pada direktori
resources\views\backend\ v_layouts\backend\. Jika berhasil, tampilan akan seperti pada
Gambar XII.4 untuk melihat filter form laporan. Jika tombol cetak diklik, halaman browser
baru akan terbuka dan menampilkan cetakan data yang diinginkan, seperti pada gambar XII.5
<li class="sidebar-item"> <a class="sidebar-link has-arrow waves-effect waves-dark"
href="javascript:void(0)" aria-expanded="false"><i class="mdi mdi-receipt"></i><span
class="hide-menu">Laporan </span></a>
<ul aria-expanded="false" class="collapse first-level">
<li class="sidebar-item"><a href="{{
route('backend.laporan.formuser') }}" class="sidebar-link"><i class="mdi mdi-chevron-
right"></i><span class="hide-menu"> User </span></a></li>
<li class="sidebar-item"><a href="{{
route('backend.laporan.formproduk') }}" class="sidebar-link"><i class="mdi mdi-chevron-
right"></i><span class="hide-menu"> Produk </span></a></li>
</ul>
</li>
Gambar XII. 4
Manajemen Laporan Data Produk
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Tell the browser to be responsive to screen width -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<!-- Favicon icon -->
<link rel="icon" type="image/png" sizes="16x16" href="{{
asset('image/icon_univ_bsi.png') }}">
<title>tokoonline</title>
<!-- Custom CSS -->
<link rel="stylesheet" type="text/css" href="{{ asset('backend/extra-
libs/multicheck/multicheck.css') }}">
<link href="{{ asset('backend/libs/datatables.net-bs4/css/dataTables.bootstrap4.css')
}}" rel="stylesheet">
<link href="{{ asset('backend/dist/css/style.min.css') }}" rel="stylesheet">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<!-- ============================================================== -->
<!-- Preloader - style you can find in spinners.css -->
<!-- ============================================================== -->
<div class="preloader">
<div class="lds-ripple">
<div class="lds-pos"></div>
<div class="lds-pos"></div>
</div>
</b>
<!--End Logo icon -->
<!-- Logo text -->
<span class="logo-text">
<!-- dark Logo text -->
<img src="{{ asset('image/logo_text.png') }}" alt="homepage"
class="light-logo" />
</span>
<!-- Logo icon -->
<!-- <b class="logo-icon"> -->
<!--You can put here icon as well // <i class="wi wi-sunset"></i>
//-->
<!-- Dark Logo icon -->
<!-- <img src="assets/images/logo-text.png" alt="homepage"
class="light-logo" /> -->
<!-- ==============================================================
-->
<!-- Search -->
<!-- ==============================================================
-->
</ul>
<!-- ============================================================== -->
<!-- Right side toggle and nav items -->
<!-- ============================================================== -->
<ul class="navbar-nav float-right">
<!-- ==============================================================
-->
<!-- Comment -->
<!-- ==============================================================
-->
<!-- ==============================================================
-->
<!-- End Comment -->
<!-- ==============================================================
-->
<!-- ==============================================================
-->
<!-- Messages -->
<!-- ==============================================================
-->
<!-- ==============================================================
-->
<!-- End Messages -->
<!-- ==============================================================
-->
<!-- ==============================================================
-->
<!-- User profile and search -->
<!-- ==============================================================
-->
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle text-muted waves-effect
waves-dark pro-pic" href="" data-toggle="dropdown" aria-haspopup="true" aria-
expanded="false">
@if (Auth::user()->foto)
<img src="{{ asset('storage/img-user/' . Auth::user()-
>foto) }}" alt="user" class="rounded-circle" width="31">
@else
<img src="{{ asset('storage/img-user/img-default.jpg') }}"
alt="user" class="rounded-circle" width="31">
@endif
</a>
<div class="dropdown-menu dropdown-menu-right user-dd
animated">
<a class="dropdown-item" href="{{
route('backend.user.edit', Auth::user()->id) }}"><i class="ti-user m-r-5 m-l-5"></i> Profil
Saya</a>
</div>
</li>
<!-- ==============================================================
-->
<!-- User profile and search -->
<!-- ==============================================================
-->
</ul>
</div>
</nav>
</header>
<!-- ============================================================== -->
<!-- End Topbar header -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- Left Sidebar - style you can find in sidebar.scss -->
<!-- ============================================================== -->
<aside class="left-sidebar" data-sidebarbg="skin5">
<!-- Sidebar scroll-->
<div class="scroll-sidebar">
<!-- Sidebar navigation-->
<nav class="sidebar-nav">
<ul id="sidebarnav" class="p-t-30">
<li class="sidebar-item"> <a class="sidebar-link waves-effect
waves-dark sidebar-link" href="{{ route('backend.beranda') }}" aria-expanded="false"><i
class="mdi mdi-view-dashboard"></i><span class="hide-menu">Beranda</span></a>
</li>
<li class="sidebar-item"> <a class="sidebar-link waves-effect
waves-dark sidebar-link" href="{{ route('backend.user.index') }}" aria-expanded="false"><i
class="mdi mdi-account"></i><span class="hide-menu">User</span></a>
</li>
<li class="sidebar-item"> <a class="sidebar-link has-arrow waves-
effect waves-dark" href="javascript:void(0)" aria-expanded="false"><i class="mdi mdi-
shopping"></i><span class="hide-menu">Data Produk </span></a>
<ul aria-expanded="false" class="collapse first-level">
<li class="sidebar-item"><a href="{{
route('backend.kategori.index') }}" class="sidebar-link"><i class="mdi mdi-chevron-
right"></i><span class="hide-menu"> Kategori </span></a>
</li>
<li class="sidebar-item"><a href="{{
route('backend.produk.index') }}" class="sidebar-link"><i class="mdi mdi-chevron-
right"></i><span class="hide-menu"> Produk </span></a>
</li>
</ul>
</li>
<li class="sidebar-item"> <a class="sidebar-link has-arrow waves-
effect waves-dark" href="javascript:void(0)" aria-expanded="false"><i class="mdi mdi-
receipt"></i><span class="hide-menu">Laporan </span></a>
<ul aria-expanded="false" class="collapse first-level">
<li class="sidebar-item"><a href="{{
route('backend.laporan.formuser') }}" class="sidebar-link"><i class="mdi mdi-chevron-
right"></i><span class="hide-menu"> User </span></a></li>
<li class="sidebar-item"><a href="{{
route('backend.laporan.formproduk') }}" class="sidebar-link"><i class="mdi mdi-chevron-
right"></i><span class="hide-menu"> Produk </span></a></li>
</ul>
</li>
</ul>
</nav>
</html>
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Produk;
use App\Models\Kategori;
use App\Models\FotoProduk;
use App\Helpers\ImageHelper;
/**
* Show the form for creating a new resource.
*/
public function create()
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$validatedData = $request->validate([
'kategori_id' => 'required',
'nama_produk' => 'required|max:255|unique:produk',
'detail' => 'required',
'harga' => 'required',
'berat' => 'required',
'stok' => 'required',
'foto' => 'required|image|mimes:jpeg,jpg,png,gif|file|max:1024',
], $messages = [
'foto.image' => 'Format gambar gunakan file dengan ekstensi jpeg, jpg, png,
atau gif.',
'foto.max' => 'Ukuran file gambar Maksimal adalah 1024 KB.'
]);
$validatedData['user_id'] = auth()->id();
$validatedData['status'] = 0;
if ($request->file('foto')) {
$file = $request->file('foto');
$extension = $file->getClientOriginalExtension();
$originalFileName = date('YmdHis') . '_' . uniqid() . '.' . $extension;
$directory = 'storage/img-produk/';
Produk::create($validatedData, $messages);
return redirect()->route('backend.produk.index')->with('success', 'Data berhasil
tersimpan');
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
$produk = Produk::with('fotoProduk')->findOrFail($id);
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
$produk = Produk::findOrFail($id);
$kategori = Kategori::orderBy('nama_kategori', 'asc')->get();
return view('backend.v_produk.edit', [
'judul' => 'Ubah Produk',
'edit' => $produk,
'kategori' => $kategori
]);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//ddd($request);
$produk = Produk::findOrFail($id);
$rules = [
'nama_produk' => 'required|max:255|unique:produk,nama_produk,' . $id,
'kategori_id' => 'required',
'status' => 'required',
'detail' => 'required',
'harga' => 'required',
'berat' => 'required',
'stok' => 'required',
'foto' => 'image|mimes:jpeg,jpg,png,gif|file|max:1024',
];
$messages = [
'foto.image' => 'Format gambar gunakan file dengan ekstensi jpeg, jpg, png,
atau gif.',
'foto.max' => 'Ukuran file gambar Maksimal adalah 1024 KB.'
];
$validatedData['user_id'] = auth()->id();
$validatedData = $request->validate($rules, $messages);
if ($request->file('foto')) {
//hapus gambar lama
if ($produk->foto) {
$oldImagePath = public_path('storage/img-produk/') . $produk->foto;
if (file_exists($oldImagePath)) {
unlink($oldImagePath);
}
$oldThumbnailLg = public_path('storage/img-produk/') . 'thumb_lg_' .
$produk->foto;
if (file_exists($oldThumbnailLg)) {
unlink($oldThumbnailLg);
}
$oldThumbnailMd = public_path('storage/img-produk/') . 'thumb_md_' .
$produk->foto;
if (file_exists($oldThumbnailMd)) {
unlink($oldThumbnailMd);
}
$oldThumbnailSm = public_path('storage/img-produk/') . 'thumb_sm_' .
$produk->foto;
$produk->update($validatedData);
return redirect()->route('backend.produk.index')->with('success', 'Data berhasil
diperbaharui');
}
/**
* Remove the specified resource from storage.
*/
public function destroy($id)
{
$produk = Produk::findOrFail($id);
$directory = public_path('storage/img-produk/');
if ($produk->foto) {
// Hapus gambar asli
$oldImagePath = $directory . $produk->foto;
if (file_exists($oldImagePath)) {
unlink($oldImagePath);
}
// Hapus thumbnail lg
$thumbnailLg = $directory . 'thumb_lg_' . $produk->foto;
if (file_exists($thumbnailLg)) {
unlink($thumbnailLg);
}
// Hapus thumbnail md
$thumbnailMd = $directory . 'thumb_md_' . $produk->foto;
if (file_exists($thumbnailMd)) {
unlink($thumbnailMd);
}
// Hapus thumbnail sm
$thumbnailSm = $directory . 'thumb_sm_' . $produk->foto;
if (file_exists($thumbnailSm)) {
unlink($thumbnailSm);
}
$produk->delete();
if ($request->hasFile('foto_produk')) {
foreach ($request->file('foto_produk') as $file) {
// Buat nama file yang unik
$extension = $file->getClientOriginalExtension();
$filename = date('YmdHis') . '_' . uniqid() . '.' . $extension;
$directory = 'storage/img-produk/';
$tanggalAwal = $request->input('tanggal_awal');
$tanggalAkhir = $request->input('tanggal_akhir');
$produk = $query->get();
return view('backend.v_produk.cetak', [
'judul' => 'Laporan Produk',
'tanggalAwal' => $tanggalAwal,
'tanggalAkhir' => $tanggalAkhir,
'cetak' => $produk
]);
}
}
Presentasi Tugas Kelompok yakni mempresentasikan hasil dari project akhir yang
dikerjakan secara berkelompok dengan Indikator Penilaian:
1. Ketepatan waktu pengumpulan tugas
2. Kelengkapan makalah project
3. Dapat menjelaskan, menampilkan dan membuktikan hasil project akhir secara
berkelompok
Presentasi Tugas Kelompok yakni mempresentasikan hasil dari project akhir yang
dikerjakan secara berkelompok dengan Indikator Penilaian:
1. Ketepatan waktu pengumpulan tugas
2. Kelengkapan makalah project
3. Dapat menjelaskan, menampilkan dan membuktikan hasil project akhir secara
berkelompok
Presentasi Tugas Kelompok yakni mempresentasikan hasil dari project akhir yang
dikerjakan secara berkelompok dengan Indikator Penilaian:
1. Ketepatan waktu pengumpulan tugas
2. Kelengkapan makalah project
3. Dapat menjelaskan, menampilkan dan membuktikan hasil project akhir secara
berkelompok