Anda di halaman 1dari 9

>> Kita akan menambahkan fitur untuk upload gambar.

Kita sudah punya fitur gambar,


tapi gambarnya
ngambil dari unsplash, ngambil gambar yang sesuai dengan kategori. Kalau kita
lihat isi
dari tabel posts, gk ada field untuk menyimpan gambar

>> Nantinya kita akan lihat kalau postingan gk ada gambarnya, kita akan pakai API
unsplash,
tapi kalau ada gambarnya, kita pakai gambar itu. Jadi yang akan kita ubah
adalah di bagian
create new postnya dlu, selanjutnya update, dan terakhir delete

>> Jika kita buka halaman create new post. Sebelum body, kita akan bikin satu
inputan untuk
menyimpan atau mengupload file, nanti filenya akan kita validasi yang boleh
upload hanya
gambar saja

>> Jadi untuk ngambil file inputnya, kita akan pakai file input bootstrap, kita
buka dokumentasi
bootstrap, kita cari di form, lalu ada form control, kita cari file input, di
dalamnya
kita ambil syntax yang pertama

>> Namanya Default file input example, kita cukup copas div pertama, lalu kita
pindahkan
ke file index untuk create postingan di dashboard. Kita scroll sampai ketemu
tag untuk
input category
Misal :
<div class="mb-3">
<label for="formFile" class="form-label">Default file input
example</label>
<input class="form-control" type="file" id="formFile">
</div>

>> Jika kita cek di web browser, maka tampilannya akan ada untuk upload file.
Paling tinggal
kita ganti isi dari labelnya jadi Post Image. Selanjutnya kita ganti label
fornya jadi
image, id di tag inputnya kita kasih image, lalu kita kasih atribut name di tag
inputnya
Misal :
<label for="image" class="form-label">Post Image</label>
<input class="form-control" type="file" id="image" name="image">

>> Ketika klik tombolnya kita bisa langsung pilih filenya, tapi fiturnya belum
jalan. Ketika
kita mau bekerja dengan file di dalam form kita, kita harus ubah dlu formnya,
kita harus
tambahkan sebuah atribut yang namanya enctype dengan isinya adalah
multipart/form-data
Misal :
<form method = "post" class="mb-5" action = "/dashboard/posts"
enctype="multipart/form-data">

>> Form ini bisa menangani dua hal, yaitu semua inputan dalam bentuk text akan
diambil dengan
request biasa, kalau ada file akan diambil menggunakan request file. Klo gk ada
ini, file
yang kita kirimkan gk akan bisa di upload

>> Sebelum jalankan fungsi upload, kita coba liat laravel menangani file seperti
apa. Kita
buka controller dashboard, lalu ke function store, Kalau kita lihat method
request menangani
semua data yang dikirimin form

>> Kita cek dengan menggunakan method ddd(), artinya dump die and debug. Kalau
kita tulis
di dalamnya variable request, artinya yang di bawah untuk validasi tidak
dijalankan
sambil ngedebug

>> Jika kita cek dengan cara isi sembarang data, maka nanti kita akan diarahkan ke
Dump,Die,
and Debug, di dalamnya bisa kita lihat, banyak banget yang dikirimin. Yang kita
butuhin
hanya yang ada di method request

>> Jika kita buka method requestnya, ada 5 data yang dikirimin, kecuali image.
File imagenya
ada di method files, itulah kenapa kita butuh multipart, sehingga yang string
masuknya ke
request, yang file masuknya ke files

>> Jika kita lihat isinya ada sebuah file yang namanya image yang berisi banyak
data seperti
original name, mime type (bentuk filenya), ada path (penyimpanan sementara),
ada filename
(nama sementara), size (ukuran file) dan seterusnya

>> Gimana cara kita menyimpan datanya, caranya kita cukup tulis, misalnya kita
return kita
mau upload filenya dlu, dengan cara return variable request pakai method file
isi dari
method file() dengan nama dari tag inputan filenya

>> Lalu kita panggil method namanya store(), kita arahkan mau nyimpennya ke
direktori mana.
Nanti kita mau bikin folder namanya post-images, jadi ceritanya file apapun
akan disimpan
ke folder tersebut
Misal :
return $request->file('image')->store('post-images');

>> Jika kita cek di browser, kita isi semua judul, slug, kategori, post image, dan
body. Maka
setelah kita klik create post, akan otomatis fungsi store tadi mengembalikan
pathnya
selain memasukkan atau mengupload filenya

>> Jadi sebetulnya sudah ke upload, kita mengetahui sudah ke upload jika kita buka
folder
storage, lalu kita buka folder app, di dalamnya ada folder post-images yang
kalau kita
klik ada sebuah file yang namanya random dan jika diklik, ini adalah file kita
yang kita
upload

>> Yang harus kita perbaiki, kita atur dlu tempat penyimpanannya bukan di tempat
tadi.
Coba kita buka dokumentasi laravel, kita cari yang namanya file storage. Kalau
kita baca
di introductionnya

>> Laravel sudah menyediakan filesystem yang powerfull gara2 ada library atau
package yang
namanya Flysystem. Jadi nanti kedepannya kalau kita mau integrasikan aplikasi
kit agar
bisa upload ke beberapa tempat, misalnya di local

>> Local tu di komputer kita mau lewat FTP di server kita, atau bahkan lewat
Amazon S3. Di
tempat penyimpanan terpisah, atau sekaligus ke tiga2nya bisa. Nanti yang akan
kita lakukan
adalah ke local dlu

>> Cara ngaturnya ada di bagian konfigurasi file system, kita bisa buka
config/filesystems.php
Jika kita buka di vscode, maka di dalamnya kita punya default filesystem Disk,
secara
default, itu adalah local
Misal :
'default' => env('FILESYSTEM_DRIVER', 'local'),

>> Jadi di cek dlu di environment variablenya ada atau tidak, kalau ada pilih
local. Local itu
ada di dalam folder storage, di dalam folder app
Misal :
'disks' => [

'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],

>> Kedepannya kita gk akan nyimpen di direktori tersebut karena kita ingin agar
file yang
di upload itu diakses secara public. Karena kita pengen nampilin di halaman
blog kita
jadi kita harus pindahin ke folder public

>> Makanya default filesystemnya jangan local, kita bisa pindahin ke public.
Caranya kita
bisa ganti defaultnya ke public, tapi kita lebih baik mindahin ke environment
variable
jadi kita bisa copas FILESYSTEM di dalam env(), kita buka file .env

>> Karena gk ada, kita tulis di paling bawah : FILESYSTEM_DRIVER, lalu kita tulis
=public
Misal:
FILESYSTEM_DRIVER=public

>> Maka yang akan di pakai sekarang ini. Kita balik ke browser, kita coba upload
sekali lagi
Jika sudah kita balik ke kodingan kita, sekarang di folder app tidak ada folder
yang
kita buat dengan nama post-images, adanya di dalam folder public

>> Tapi masih ada problem, kalau kita coba akses langsung lewat browser, caranya
kita
klik kanan file gambar, lalu kita klik copy relative path, kita paste di tab
baru di
browser. Syntax di urlnya adalah tempat penyimpanan gambar kita.

>> Kalau depannya kita coba tambahkan link website kita, jika kita enter, maka
tidak ada
tampilannya. Maka kalau kita upload, tidak akan tampil ke website kita, karena
gk bisa
di akses

>> Ini karena folder public yang ada di dalam folder storage, harus kita hubungkan
dlu dengan
folder public yang ada di dalam aplikasi kita. Kalau kita cari, kita juga punya
folder
public

>> Folder ini adalah folder yang bener2 bisa diakses oleh user. Contohnya kalau
kita punya
image, lalu kita klik kanan, copy relative path, depannya kita kasih link kita,
kalau
tekan enter, maka akan tampil

>> Cara menghubungkan antara folder public yang ada di storage dengan folder
public yang ada
di aplikasi kita, kita harus gunakan yang namanya symbolic link. caranya kita
tulis
di terminal kita php artisan storage:link, supaya menghubungkan public aplikasi
kita
dengan public storage

>> Jika sudah dilakukan, maka kita bisa langsung akses, seolah2 dia ada di folder
public
nanti kalau kita mau akses filenya kita bisa pakai method yang namanya asset.
Sekarang
kita lakukan link dahulu di terminal
Misal :
php artisan storage:link

>> Kalau kita tekan enter, nanti ada tulisan The links have been created. Sekarang
kalau kita buka explorer, di folder public tiba2 ada storage yang ada panahnya,
berarti
dia symbolic link

>> Tempat aslinya berada di storage, jadi apapun yang ada di dalam storage akan
muncul
di public aplikasi kita.

>> Sekarang kita sudah siap jalankan upload filenya. Sebelum kita lakukan, di
dalam database
kita, kita tidak punya field image, sekarang kita bikin di migrasi kita. Jadi
kita bersih
kan database kita. Tapi kita gk akan ada maslah

>> Karena kita sudah menerapkan fitur migration dan factory, kita buka file
migrasi posts,
kita tambahkan satu field setelah slug. Kita bikin table dengan tipe data
string, alasannya
kita akan simpan nama dan tempat penyimpanan filenya aja

>> Yang tadi kita lihat ketika selesai upload ada tulisan storage/namaRandom, itu
yang akan
kita simpan di dalam database, sedangkan filenya akan diupload di direktori.
Namanya
image, lalu bisa kosong dengan menggunakan method nullable()
Misal :
$table->string('image')->nullable();

>> Karena kalau kosong, kita akan tetap pakai gambar dari unsplash, kalau sudah,
sebelum
kita jalankan migrasinya, kita buka seeder. Di dalamnya kita sudah bikin user
baru 3,
category baru 3, dan postingan 20, tapi kita ingin nama kita juga sebagai
usernya, kita
buka komentar untuk membuat user dengan nama kita
Misal :
User::create([
'name' => 'Ryan Dhika Permana',
'username' => 'ryandhikapermana',
'email' => 'ryandhikapermana@gmail.com',
'password' => bcrypt('12345')
]);

>> Jadi nanti ada 4 user, kita save dan buka terminal, kita lakukan migrate
Misal:
php artisan migrate:fresh --seed

>> Jika sudah, maka kita close terminalnya, close seedernya, kita cek di database,
kalau postnya kita refresh, maka sudah ada posts baru, kalau kita cek users
maka
ada user baru dengan nama kita.

>> Ada satu hal yang harus kita perbaiki, kalau username kita, ketika login dengan
menggunakan nama kita yang sudah dibuat sebelumnya, maka sudah bisa masuk ke
dashboard. Kalau kita login pakai user lain dengan .org di emailnya

>> Maka gk bisa login, karena email gk valid, ini salah di validasi kita, karena
validasi kita terlalu ketat. Jadi kita atur dlu kita buka file logincontroller
cari bagian authenticate, ada validasi :dns

>> Kalau kita mau seketat ini boleh, karena yang di generate oleh faker kita email
random, maka login kita gk bisa masuk. Jadi :dns nya bisa kita hapus saja.
Kalau sudah
kita lakukan login dengan user .org

>> Maka akan masuk ke dashboard, ini untuk ngejalanin faker kita saja. Sekarang
kita
jalankan validasi untuk gambar, kita buka dashboardpostcontroller. Kita ke
method
store. Hapus return di baris awal di dalam method store

>> Kita lakukan validasi, kita tambahin validasi untuk image, kita tambahkan
namanya
image, validasi pertama harus image, kalau kita ingin tambahkan validasi
ukuran, kita
tulis file lalu kasih pipe "|" lalu ukurannya berapa

>> Kalau kita kasih max, berarti maksimal ukurannya, kalau min, ini minimal
ukurannya,
kalau kita kasih size, ini harus persis ukurannya berapa. berarti yang kita
butuhin
adalah max: ukurannya mau berapa, ini satuannya kilobyte

>> Kalau kita ingin maksimal 1 mega, kita bisa tulis 1024, jadi maksimal 1 mega,
karena
kalau gk pakai file, dianggapnya karakter, atau integer, kalau kita kasih file
sebelum
max, berarti kilobyte. Kalau kita mau lihat lebih banya validasi apa yang bisa
digunakan
kita bisa cek dokumentasi laravelnya
Misal :
'image' => 'image|file|max:1024',

>> Sekarang kita cek validasi, kita balik ke create, kita akan kasih ketika gagal
tampilannya
akan gimana, kita bisa kasih @error, dan kita kasih class is-invalid
Misal :
@error ('image') is-invalid @enderror

>> Ini cuman buat kasih border warna merah kalau invalid, kita copas invalid-
feedbacknya
Misal :
@error('image')
<div class="invalid-feedback">
{{ $message }}
</div>
@enderror

>> Salah satu kendala dari image adalah, kita gk bisa ngasih method old() ketika
terjadi
kesalahan. Jadi kalau kita upload gambar, itu tidak ada masalah. Tapi kita lupa
isi body
begitu klik create, nanti di imagenya balik lagi kosong

>> Ini gk bisa dikasih old, karena itu pertimbangan security, jadi jangan sampe
nanti orang
bisa tahu struktur direktori kita. Makanya old gk bisa dipakai di upload file.

>> Kita coba di browser, kita upload image dengan ukuran lebih besar dari
validasi, maka ada
pesan error : image must bot be greater than 1024 kilobytes. Sekarang kalau
yang
di upload bukan gambar

>> Kita upload pdf, maka akan ada pesan error : image must be an image. Harus
gambar. Jadi
kita cuman ngejagain ukuran filenya, kalau ukuran gambarnya kita terima apa
adanya, gk
akan kita lakukan resize. Selama gambarnya di bawah 1mb, lolos

>> Sekarang kita balik ke controllernya, kita akan ngecek gimana kalau user gk
ngisiin
gambarnya, kan gk apa2 juga, gambar gk wajib karena kalau gambarnya kosong, dia
akan
ngambil dari unsplash

>> Kita cek dengan membuat seleksi kondisi di controller jika kalau request dari
file()
yang namanya image itu ada isinya, karena kalau gk ada berarti null, kalau null
berarti false, kalau true. Kita akan tambahkan satu validatedData di array
image diisi
dengan upload gambarnya

>> Sekaligus ambil nama gambarnya, caranya kita request lalu kita ambil filenya
dengan nama
image, lalu kita store, kita simpen di post-images, jadi kalau kosong, tidak
dijalanin,
kalau ada isinya dan udah valid, masuk ke seleksi kondisi, lalu insert ke dalam
database

>> Kita coba upload gambarnya. Ketika kita klik create post, maka sudah aman. Jika
kita balik
ke direktori di projek kita di dalam public/storage/post-images, gambar yang
kita kirimkan
sudah disimpan di direktori kita
Misal :
if ($request->file('image')) {
$validatedData['image'] = $request->file('image')->store('post-
images');
}

>> Kita cek di database, maka datanya sudah masuk. Tinggal kita bikin supaya
menampilkan
datanya caranya, kalau kita klik show, datanya masih ngambil dari unsplash.
Sekarang
kita bikin dia melakukan pengecekan

>> Kita buka halaman view yang show, kita cari kodingan kita untuk menampilkan
gambar. Maka
kita butuh melakukan pengecekan, kodingan kita yang sebelumnya adalah ketika
else. Jadi
kalau ada field image di dalam tabel, tampilin itu

>> Jadi if post ada image, baru kodingan kita di copy, tapi srcnya kita punya
method asset()
ngambil dari folder storage. Kan mulainya dari public, klo kita lihat di
sidebar projek kita
itu publicnya tidak perlu, langsung storage baru nama filenya.

>> post-images tidak usah ditulis karena itu sudah dibawa ke dalam tabel kita.
Jadi tinggal
kita gabung di luarnya kasih . lalu ambil di model post dengan tabel image
Misal :
@if ($post->image)
<img src="{{ asset('storage/' . $post->image) }}}}"
alt="{{ $post->category->name }}" class="img-fluid mt-3">
@else
<img src="https://source.unsplash.com/random/1200x400?{{ $post-
>category->name }}" alt="{{ $post->category->name }}" class="img-fluid mt-3">
@endif

>> Kita cek di browser, maka gambar kita sudah tampil. Tapi ukuran tingginya gk
sama. Kalau
kita mau samakan seperti di unsplash, kita bisa paksakan kita masukin ke dalam
div di
dalamnya kita kasih style

>> Kita atur tingginya dengan max-height dengan nilai 350px, kalau bablas kita
gunakan
overflow hidden. Kita cek di web browser, maka gambarnya akan terpotong
sebagian.
Ini untuk yang ada di halaman dashboard
Misal :
@if ($post->image)
<div style="max-height: 350px; overflow: hidden">
<img src="{{ asset('storage/' . $post->image) }}"
alt="{{ $post->category->name }}" class="img-fluid mt-3">
</div>

>> Kita harus benerin yang ada di halaman front-endnya. Kita harus benerin yang
besarnya dan
yang kecilnya. Kalau dia postnya udah turun, harus dibenerin juga. Sekarang
kita buka
view posts. Kita cari kodingan kita. Kita copas if else yang ada di show

>> Taro di atasnya syntax image posts, setiap post kita ubah jadi posts dengan
index ke 0
Misal :
@if ($posts[0]->image)
<div style="max-height: 350px; overflow: hidden">
<img src="{{ asset('storage/' . $posts[0]->image) }}"
alt="{{ $posts[0]->category->name }}" class="img-fluid mt-3">
</div>
@else
<img src="https://source.unsplash.com/random/1200x400?{{ $posts[0]-
>category->name }}" class="card-img-top" alt="{{ $posts[0]->category->name }}">
@endif

>> Jadi kalau ada isinya pakai yang di bawah if, tapi kalau gk ada isinya pakai
yang di bawah
else. Jika sudah kita save dlu, cek di browser, maka sudah tampil. Kalau
terlalu pendek,
kita ganti ukurannya jadi 400px

>> Kalau kita bikin postingan baru dan ada upload gambarnya. Karena kalau kita
lakukan fitur
edit, tidak bisa. Kalau kita buat postingan baru maka di halaman blognya akan
tampil,
postingan kedua, tapi yang postingan sebelumnya kita buat, balik lagi, dia
ambil dari
unsplash

>> Karena di kodingan kita untuk card imagenya kita masih ngambil dari unsplash,
kita harus
ganti lagi, kita copas dari show blade. Kita simpan di atasnya, kita hapus tag
div nya
untuk if, kita cut image source yang ada di bawah endif, pindahkan di bawah
else
Misal:
@if ($post->image)
<img src="{{ asset('storage/' . $post->image) }}"
alt="{{ $post->category->name }}" class="img-fluid mt-3">
@else
<img
src="https://source.unsplash.com/random/500x400?{{ $post->category->name }}"
class="card-img-top" alt="{{ $post->category->name }}">
@endif

>> Jadi sudah benar semua, kita hapus class mt di tag img yang ada di bawah if dan
class mt
yang ada di atas. Tinggal satu lagi, ketika kita klik read more. Maka tampilan
masih
ngambil gambar di unsplash

>> Ini ada di view post, kita buka kita copas syntax if yang di show, pindahkan ke
post
Misal :
@if ($post->image)
<div style="max-height: 350px; overflow: hidden">
<img src="{{ asset('storage/' . $post->image) }}"
alt="{{ $post->category->name }}" class="img-fluid">
</div>
@else
<img src="https://source.unsplash.com/random/1200x400?{{ $post-
>category->name }}" alt="{{ $post->category->name }}" class="img-fluid">
@endif

Anda mungkin juga menyukai