nschelper / larahelper
Helper package
Requires
- php: >=8.0
- laravel/framework: >=9.0
This package is not auto-updated.
Last update: 2025-07-16 16:05:17 UTC
README
[instalasi]
composer require nschelper/larahelper
composer update nschelper/larahelper
perhatian: tidak perlu lagi menambahkan apapun di config/app.php
, baik di providers
maupun di aliases
.
lalu publish file-file lang
, css
dan js
dengan cara:
php artisan vendor:publish --tag=niascoder-helper
php artisan vendor:publish --tag=niascoder-helper --force
perhatian: sebaiknya hindari penggunaan --force
. sebelum publish, pilih dulu satu atau beberapa file di bawah ini yang akan di baca ulang dari repo package. baru publish dengan tanpa --force
. publish tidak akan menimpa file-file yang sudah ada.
file-file yang dihasilkan:
config/niascoderhelper.php
lang/id/db.php
lang/id/error.php
lang/id/log.php
lang/id/tooltip.php
lang/id/validation.php
public/js/global.js
[component]
untuk blade:
// -----
// form control
// -----
<x-form-input
name="nama_lengkap"
lang-context="db.pegawai.edit">
</x-form-input>
<x-form-textarea
name="nama_lengkap"
lang-context="db.pegawai.edit">
</x-form-textarea>
<x-form-select
name="jenis_kelamin"
lang-context="db.pegawai.edit"
:options="['L' => 'Laki-laki', 'P' => 'Perempuan']">
</x-form-select>
<x-form-file
name="file_upload"
lang-context="db.pegawai.edit"
accept=".docx,.pdf"
multiple="true">
</x-form-file>
<x-form-recaptcha2
name="pegawai_captcha"
site-key="{{ config('recaptcha.api_site_key') }}"
:modal-form="true">
</x-form-recaptcha2>
// -----
// collection control
// -----
// menampilkan filter button dan data count
// kalau filter-control-nya hanya 1, gunakan syntax: "(bool) request()->filter1" pada :is-tersaring
<x-collection-filtering
:collection="$objectList"
:is-tersaring="request()->filter1 || request()->filter2 || [...]"
:post-url="route('route_name')">
<x-form-input
name="nama_lengkap"
old-value="{{ request()->filter1 }}"
lang-context="db.pegawai.index">
</x-form-input>
<x-form-input
name="alamat"
old-value="{{ request()->filter2 }}"
lang-context="db.pegawai.index">
</x-form-input>
</x-collection-filtering>
// menampilkan hanya data count (misalnya kalau tidak butuh fitur filter)
<x-collection-info
:collection="$objectList">
</x-collection-info>
// menampilkan dropdown untuk memilih jumlah baris data per halaman (row per page)
// tidak membutuhkan parameter
<x-collection-rowperpage />
// supaya row per page persist, di controller function
$rowsPerPage = intval(request()->query('rowsperpage', request()->cookie('rowsperpage', config('niascoderhelper.rows_per_page'))));
Cookie::queue('rowsperpage', $rowsPerPage, 360);
// ...
$objectList = ObjectModel::paginate($rowsPerPage)->withQueryString();
// -----
// partial view
// -----
// gunakan partial view ini untuk me-render pagination (bootstrap 5)
// $objectList harus hasil pagination.
// kalau tidak ada page (!$objectList->hasPages()), tidak ada yang di render.
{{ $objectList->links('niascoder-helper::partials.pagination-numbers') }}
untuk lang/id/db.php
:
return [
'pegawai.edit.nama_lengkap' => 'Nama lengkap',
'pegawai.edit.jenis_kelamin' => 'Jenis kelamin',
'pegawai.index.filter1' => 'Filter A',
'pegawai.index.filter2' => 'Filter B',
];
[validator]
di controller function yang menjalankan validasi:
$validator = Validator::make($request->all(), [
// ...
'tanggal' => 'required|tglblnthn',
'nik' => 'required|nik',
'nomorkk' => 'required|nomorkk',
// ...
'g-recaptcha-response' => 'recaptcha',
// atau bisa juga
recaptchaFieldName() => recaptchaRuleName(),
// ...
]);
[menyimpan data ke database]
di controller function yang outputnya full view:
// ganti $object dengan model eloquent
// ganti table.operation dengan nama tabel dan nama operasi, cth: pegawai.create, atau pegawai.update
try {
$object->save();
} catch (\Throwable $th) {
Log::error(__('log.db.error.table.operation'), ['th' => $th, 'db' => AppHelper::attrToArray($object)]);
return redirect()->back()->withErrors(AppHelper::validatorErrorTh($th, __('log.db.error.table.operation')))->withInput();
}
di controller function yang outputnya json:
// ganti $object dengan model eloquent
// ganti table.operation dengan nama tabel dan nama operasi, cth: pegawai.create, atau pegawai.update
try {
$object->save();
} catch (\Throwable $th) {
Log::error(__('log.db.error.table.operation'), ['th' => $th, 'db' => AppHelper::attrToArray($object)]);
return response()->json(AppHelper::jsonResponseErrorTh($th, __('log.db.error.table.operation')));
}
untuk lang/id/log.php
:
return [
// ...
'db.error.table.operation' => 'Gagal melakukan [operasi] pada [table].',
// ...
];
[redirect back, untuk non-ajax]
di controller function yang outputnya full view:
// redirect back dengan Throwable
return redirect()->back()->withErrors(AppHelper::validatorErrorTh($th))->withInput();
// redirect back, ada form input salah
// contoh: menampilkan validasi error di form control #nama_lengkap
return redirect()->back()->withErrors(AppHelper::validatorErrorForm('nama_lengkap', 'Nama ini tidak boleh digunakan.'))->withInput();
// redirect back, menampilkan sweetalert
// contoh: menampilkan pesan khusus lewat sweetalert
return redirect()->back()->withErrors(AppHelper::validatorErrorMessage('Maaf, pendaftaran sudah tutup.'))->withInput();
[json response, untuk ajax]
di controller function yang outputnya json:
// success
// ganti $redirect_url dengan alamat tujuan redirect. kalau kosong, refresh.
return response()->json(AppHelper::jsonResponseSuccess($redirect_url));
// error dengan Throwable
// ganti $redirect_url dengan alamat tujuan redirect. kalau kosong, refresh.
return response()->json(AppHelper::jsonResponseErrorTh($th, $message, $redirect_url));
// error dengan menampilkan pesan
// ganti $redirect_url dengan alamat tujuan redirect. kalau kosong, refresh.
return response()->json(AppHelper::jsonResponseErrorMessage($message, $redirect_url));
[DateTime di model]
class PegawaiModel
{
protected function tanggalLahir(): Attribute
{
return Attribute::make(
get: fn ($value) => AppHelper::showTanggal($value, "d-m-Y"),
set: fn ($value) => AppHelper::parseTanggal($value, "d-m-Y"),
);
}
}
[layout]
untuk blade template:
<script src="//cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script src="{{ asset('js/global.js') }}"></script>
@stack('scripts')
@error('error_alert')
<script>
$(function() {
Swal.fire('', '{{ $message }}', 'error');
});
</script>
@enderror
untuk blade content:
// -----
// buttons, dengan text
// -----
<a href="{{ route('route_create') }}" class="btn btn-success">Tambah</a>
<a href="{{ route('route_edit', ['id' => $id]) }}" class="btn btn-primary">Edit</a>
<a href="javascript:void(0);" class="btn btn-danger" data-deleteurl="{{ route('route_delete',['id'=> $id]) }}" onclick="sweetDeleteData(this)">Hapus</a>
<button type="submit" class="btn btn-success">Tambah</button>
<button type="submit" class="btn btn-primary">Simpan</button>
<a href="{{ route('route.index') }}" class="btn btn-outline btn-outline-secondary">Batal</a>
// -----
// buttons, dengan icon
// -----
<a href="{{ route('route_detail', ['id' => $id]) }}" title="{{ __('tooltip.btn_detail') }}"><i class='fa-solid fa-magnifying-glass'></i></a>
<a href="{{ route('route_edit', ['id' => $id]) }}" title="{{ __('tooltip.btn_edit') }}"><i class='fa-solid fa-pen-to-square'></i></a>
<a href="javascript:void(0);" data-deleteurl="{{ route('route_delete',['id'=> $id]) }}" onclick="sweetDeleteData(this)" title="{{ __('tooltip.btn_hapus') }}"><i class='fa-solid fa-trash'></i></a>
// -----
// table-index
// -----
<div class="table-responsive">
<table class="table table-index">
<thead>
<tr>
<th>Kolom 1</th>
<th>Kolom 2</th>
<th>Kolom 3</th>
<th class="col-btn1 || col-btn2 || col-btn3"></th>
</tr>
</thead>
<tbody>
<tr>
<td>Data 1</td>
<td>Data 2</td>
<td>Data 3</td>
<td class="col-action">
<a href="{{ route('route.detail', ['id' => $id]) }}" title="{{ __('tooltip.detail_button') }}"><i class='fa-solid fa-magnifying-glass'></i></a>
<a href="{{ route('route.edit', ['id' => $id]) }}" title="{{ __('tooltip.edit_button') }}"><i class="fa-solid fa-pen-to-square"></i></a>
<a href="javascript:void(0);" data-deleteurl="{{ route('route.deletepost', ['id' => $id]) }}" onclick="sweetDeleteData(this)" title="{{ __('tooltip.hapus_button') }}"><i class="fa-solid fa-xmark"></i></a>
</td>
</tr>
</tbody>
</table>
</div>
<div class="mt-3">
{{ $objectList->links('niascoder-helper::partials.pagination-numbers') }}
</div>
// -----
// table-detail
// -----
<table class="table table-detail">
<tbody>
<tr>
<th width="80px">Label</th>
<td>Data</td>
</tr>
<tr>
<th>Label</th>
<td>Data</td>
</tr>
</tbody>
</table>
[modal form]
frontend blade yang akan menampilkan form:
<a href="javascript:void(0);" class="btn btn-primary" data-mf-id="modalCreate" data-mf-url="{{ route('data.create') }}" onclick="modalFormShow(this)">Tambah</a>
<div class="modal fade" id="modalCreate" tabindex="-1" data-bs-backdrop="static" data-bs-keyboard="true" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-dialog-scrollable modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title fs-5">Tambah Data</h5>
</div>
<div class="modal-body">
</div>
</div>
</div>
</div>
backend blade yang akan me-render form:
<form action="{{ route('data.create_post') }}" method="POST" enctype="multipart/form-data">
@csrf
<x-form-input name="id" lang-context="db.data.create"></x-form-input>
<x-form-input name="nama" lang-context="db.data.create"></x-form-input>
<x-form-input name="kategori" lang-context="db.data.create"></x-form-input>
<div class="form-buttons">
<a href="javascript:void(0);" class="btn btn-outline-primary" id="closeButton">Batal</a>
<a href="javascript:void(0);" class="btn btn-primary" id="submitButton">Tambah</a>
</div>
</form>
backend controller yang akan menerima post data:
public function createPost(Request $request)
{
$validator = Validator::make($request->all(), [
'id' => 'required',
'nama' => 'required',
'kategori' => 'required',
]);
if ($validator->fails()) {
return AppHelper::jsonResponseErrorValidator($validator);
}
// ...
// proses form disini
// kalau masih ada error, lempar dengan:
AppHelper::jsonResponseErrorMessage(__('error.operation'));
// atau...
return AppHelper::jsonResponseErrorValidator(AppHelper::validatorErrorForm('nama','Nama ini tidak boleh digunakan.'));
// ...
return AppHelper::jsonResponseSuccess();
} // function createPost
[pemanggilan ajax]
ajaxShowLoading();
$.ajax({
type: "GET",
url: url,
success: function (resultData) {
if (resultData.status) {
// ...
// proses data disini
// ...
ajaxReturnJsonTrue(resultData.redirect);
} else {
ajaxReturnJsonFalse(resultData.desc);
}
},
error: function () {
ajaxReturnError();
},
});
[recaptcha v2]
install dan publish package biscolab/laravel-recaptcha
composer require biscolab/laravel-recaptcha
php artisan vendor:publish --provider="Biscolab\ReCaptcha\ReCaptchaServiceProvider"
update version
di file config/recaptcha.php
:
return [
// ...
'version' => 'v2',
'default_language' => 'id',
// ...
];
tambahkan di file .env
:
RECAPTCHA_SITE_KEY=<YOUR_API_SITE_KEY>
RECAPTCHA_SECRET_KEY=<YOUR_API_SECRET_KEY>
RECAPTCHA_SKIP_IP=<YOUR_IP_LIST>
RECAPTCHA_SKIP_IP
boleh kosong.
di file blade yang akan menampilkan recaptcha, masukkan script ini di html HEAD
:
<html>
<head>
// ...
{!! htmlScriptTagJsApi($configuration) !!}
// ...
</head>
lalu tampilkan recaptcha melalui component:
<x-form-recaptcha2 name="pegawai_captcha" site-key="{{ config('recaptcha.api_site_key') }}" :modal-form="true"> </x-form-recaptcha2>
atribut modal-form
digunakan hanya bila recaptcha di-render di modal form.
kemudian di controller yang akan menerima form post, recaptcha divalidasi dengan cara:
$validator = Validator::make($request->all(), [
// ...
'g-recaptcha-response' => 'recaptcha',
// atau bisa juga
recaptchaFieldName() => recaptchaRuleName(),
// ...
]);
Terima Kasih
Ini adalah repository yang berisi helper atau alat bantu yang dibuat sebagai bahan pembelajaran. Helper ini dapat digunakan untuk memahami berbagai konsep dan teknologi terkait pengembangan dalam framework Laravel
Sebuah terima kasih yang tak terhingga kepada Bang Indra yang merupakan seorang DevOps hebat. Kontribusinya dalam pengembangan dan operasional sistem telah memberikan inspirasi dan pemahaman yang mendalam bagi banyak orang.