Fitur pencarian (search) adalah komponen krusial dalam hampir setiap aplikasi web modern. Pengguna mengharapkan cara yang mudah dan cepat untuk menemukan informasi yang mereka butuhkan. Laravel, dengan kekuatan Eloquent ORM-nya, menyediakan cara yang elegan dan efisien untuk mengimplementasikan fitur ini. Artikel ini akan menjadi panduan lengkap, langkah demi langkah, tentang cara membuat fitur search dengan Laravel Eloquent, mulai dari dasar hingga teknik optimasi yang lebih lanjut. Siap meningkatkan kemampuan aplikasi Laravel Anda? Mari kita mulai!
1. Mengapa Fitur Pencarian Penting untuk Aplikasi Anda? (Pentingnya Search Functionality)
Sebelum kita masuk ke teknis, mari kita bahas mengapa fitur pencarian begitu vital. Bayangkan sebuah toko online tanpa kolom pencarian. Pengguna harus menelusuri ratusan halaman produk untuk menemukan apa yang mereka cari. Frustrasi, bukan?
Fitur pencarian yang baik memberikan beberapa keuntungan signifikan:
- Meningkatkan Pengalaman Pengguna (UX): Pengguna dapat dengan cepat menemukan apa yang mereka cari, meningkatkan kepuasan dan kemungkinan mereka untuk kembali.
- Meningkatkan Tingkat Konversi: Jika pengguna mudah menemukan produk atau informasi yang mereka inginkan, kemungkinan mereka untuk melakukan pembelian atau tindakan lain yang diinginkan akan meningkat.
- Mengurangi Beban Server: Dengan pencarian yang dioptimalkan, Anda dapat mengurangi kebutuhan pengguna untuk memuat banyak halaman yang tidak relevan, sehingga mengurangi beban server.
- Analisis Data: Data pencarian dapat memberikan wawasan berharga tentang apa yang dicari pengguna Anda, membantu Anda memahami kebutuhan mereka dan mengoptimalkan konten Anda.
Singkatnya, fitur pencarian bukan hanya tentang kenyamanan; ini adalah investasi dalam pengalaman pengguna, kinerja aplikasi, dan potensi bisnis Anda.
2. Persiapan: Membuat Model dan Migrasi (Setting Up Model and Migration)
Langkah pertama dalam membuat fitur search dengan Laravel Eloquent adalah mempersiapkan model dan migrasi untuk data yang akan kita cari. Misalnya, kita akan membuat fitur pencarian untuk posting blog.
Membuat Model Post:
Gunakan perintah Artisan untuk membuat model Post:
php artisan make:model Post -m
Perintah ini akan membuat dua file:
app/Models/Post.php: File modelPost.database/migrations/[timestamp]_create_posts_table.php: File migrasi untuk membuat tabelposts.
Membuat Migrasi posts:
Buka file migrasi dan tambahkan kolom yang diperlukan, seperti title, content, dan author:
<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->string('author');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('posts');
}
};
Jalankan migrasi untuk membuat tabel di database:
php artisan migrate
Mengisi Data Dummy:
Untuk menguji fitur pencarian, kita perlu beberapa data. Anda bisa menggunakan seeder atau Tinker untuk memasukkan data dummy ke tabel posts. Berikut contoh menggunakan Tinker:
php artisan tinker
factory(AppModelsPost::class, 50)->create(); // Membuat 50 data postingan
Pastikan Anda sudah mendefinisikan factory untuk model Post jika menggunakan cara ini. Jika belum, buat factory menggunakan php artisan make:factory PostFactory --model=Post dan definisikan atributnya.
3. Implementasi Dasar: Pencarian Sederhana dengan where (Basic Search Implementation)
Sekarang kita memiliki model dan data, mari kita mulai implementasi pencarian paling dasar. Kita akan menggunakan method where dari Eloquent untuk mencari data yang sesuai dengan kriteria pencarian.
Membuat Controller:
Buat controller untuk menangani permintaan pencarian:
php artisan make:controller SearchController
Menambahkan Route:
Tambahkan route di routes/web.php:
Route::get('/search', [AppHttpControllersSearchController::class, 'index'])->name('search');
Menulis Logic Pencarian di Controller:
Buka app/Http/Controllers/SearchController.php dan tambahkan method index:
<?php
namespace AppHttpControllers;
use AppModelsPost;
use IlluminateHttpRequest;
class SearchController extends Controller
{
public function index(Request $request)
{
$keyword = $request->input('keyword');
$posts = Post::where('title', 'LIKE', "%$keyword%")
->orWhere('content', 'LIKE', "%$keyword%")
->get();
return view('search.results', compact('posts', 'keyword'));
}
}
Penjelasan:
$keyword = $request->input('keyword');: Mengambil kata kunci pencarian dari permintaan (request).Post::where('title', 'LIKE', "%$keyword%"): Mencari postingan yang judulnya mengandung kata kunci. OperatorLIKEdigunakan untuk pencarian parsial, dan%adalah wildcard yang mewakili nol atau lebih karakter.->orWhere('content', 'LIKE', "%$keyword%"): Mencari postingan yang kontennya mengandung kata kunci.orWheremenambahkan kondisi “ATAU” ke query.->get();: Menjalankan query dan mengambil hasilnya.return view('search.results', compact('posts', 'keyword'));: Me-render viewsearch.resultsdengan data postingan dan kata kunci pencarian.
Membuat View search.results:
Buat file resources/views/search/results.blade.php untuk menampilkan hasil pencarian:
<!DOCTYPE html>
<html>
<head>
<title>Hasil Pencarian</title>
</head>
<body>
<h1>Hasil Pencarian untuk: {{ $keyword }}</h1>
@if($posts->count() > 0)
<ul>
@foreach($posts as $post)
<li>
<h2>{{ $post->title }}</h2>
<p>{{ Str::limit($post->content, 200) }}</p>
<p>Oleh: {{ $post->author }}</p>
</li>
@endforeach
</ul>
@else
<p>Tidak ada hasil ditemukan.</p>
@endif
</body>
</html>
Membuat Form Pencarian:
Terakhir, buat form pencarian di view Anda (misalnya, di welcome.blade.php atau layout utama):
<form action="{{ route('search') }}" method="GET">
<input type="text" name="keyword" placeholder="Cari...">
<button type="submit">Cari</button>
</form>
Sekarang, Anda memiliki fitur pencarian dasar yang berfungsi! Cobalah dengan memasukkan kata kunci ke dalam form pencarian dan lihat hasilnya.
4. Meningkatkan Akurasi: Penggunaan strtolower dan strtoupper (Improving Accuracy with String Functions)
Pencarian dasar kita berfungsi, tetapi case-sensitive. Artinya, “Laravel” dan “laravel” dianggap berbeda. Untuk meningkatkan akurasi, kita bisa menggunakan fungsi strtolower atau strtoupper untuk mengubah kata kunci dan data di database menjadi huruf kecil atau huruf besar.
Modifikasi Controller:
<?php
namespace AppHttpControllers;
use AppModelsPost;
use IlluminateHttpRequest;
class SearchController extends Controller
{
public function index(Request $request)
{
$keyword = strtolower($request->input('keyword')); // Ubah kata kunci menjadi huruf kecil
$posts = Post::whereRaw('LOWER(title) LIKE ?', ["%$keyword%"])
->orWhereRaw('LOWER(content) LIKE ?', ["%$keyword%"])
->get();
return view('search.results', compact('posts', 'keyword'));
}
}
Penjelasan:
$keyword = strtolower($request->input('keyword'));: Mengubah kata kunci menjadi huruf kecil.Post::whereRaw('LOWER(title) LIKE ?', ["%$keyword%"]): MenggunakanwhereRawuntuk menjalankan query SQL mentah.LOWER(title)mengubah nilai kolomtitlemenjadi huruf kecil.["%$keyword%"]: Mengikat kata kunci yang sudah diubah menjadi huruf kecil sebagai parameter query.
Sekarang, pencarian Anda akan case-insensitive.
5. Optimasi Kinerja: Penggunaan Indexing Database (Optimizing Performance with Database Indexing)
Pencarian dengan LIKE pada kolom yang besar bisa lambat. Untuk meningkatkan kinerja, kita bisa menambahkan index pada kolom title dan content.
Modifikasi Migrasi:
Buka file migrasi create_posts_table.php dan tambahkan index:
<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->string('author');
$table->timestamps();
$table->index('title'); // Tambahkan index pada kolom title
$table->index('content'); // Tambahkan index pada kolom content
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('posts');
}
};
Jalankan migrasi:
php artisan migrate:fresh
Perintah migrate:fresh akan menghapus semua tabel di database dan menjalankan migrasi dari awal. Ini penting karena kita mengubah struktur tabel. Pastikan Anda memiliki backup data sebelum menjalankan perintah ini!
Dengan index, database dapat mencari data dengan lebih cepat.
6. Pencarian Lanjutan: Menggunakan Beberapa Kriteria dan Relasi (Advanced Search: Multiple Criteria and Relationships)
Terkadang, Anda membutuhkan pencarian yang lebih kompleks dengan beberapa kriteria atau pencarian melalui relasi. Eloquent menyediakan cara yang fleksibel untuk menangani hal ini.
Contoh: Mencari berdasarkan judul, konten, dan penulis:
<?php
namespace AppHttpControllers;
use AppModelsPost;
use IlluminateHttpRequest;
class SearchController extends Controller
{
public function index(Request $request)
{
$keyword = strtolower($request->input('keyword'));
$posts = Post::where(function ($query) use ($keyword) {
$query->whereRaw('LOWER(title) LIKE ?', ["%$keyword%"])
->orWhereRaw('LOWER(content) LIKE ?', ["%$keyword%"]);
})
->where('author', 'LIKE', "%" . $request->input('author') . "%") // Filter berdasarkan penulis
->get();
return view('search.results', compact('posts', 'keyword'));
}
}
Penjelasan:
where(function ($query) use ($keyword) { ... }): Menggunakan closure untuk mengelompokkan kondisi pencarian judul dan konten dengan “OR”.->where('author', 'LIKE', "%" . $request->input('author') . "%"): Menambahkan kondisi pencarian berdasarkan penulis. Perhatikan bahwa kita menggunakanLIKEuntuk pencarian parsial.
Contoh: Mencari melalui relasi:
Asumsikan model Post memiliki relasi belongsTo dengan model Category. Kita bisa mencari postingan berdasarkan nama kategori:
<?php
namespace AppHttpControllers;
use AppModelsPost;
use IlluminateHttpRequest;
class SearchController extends Controller
{
public function index(Request $request)
{
$keyword = strtolower($request->input('keyword'));
$categoryName = $request->input('category');
$posts = Post::where(function ($query) use ($keyword) {
$query->whereRaw('LOWER(title) LIKE ?', ["%$keyword%"])
->orWhereRaw('LOWER(content) LIKE ?', ["%$keyword%"]);
})
->whereHas('category', function ($query) use ($categoryName) {
$query->where('name', 'LIKE', "%$categoryName%");
})
->get();
return view('search.results', compact('posts', 'keyword'));
}
}
Penjelasan:
->whereHas('category', function ($query) use ($categoryName) { ... }): MenggunakanwhereHasuntuk melakukan query pada relasicategory.$query->where('name', 'LIKE', "%$categoryName%"): Mencari kategori yang namanya mengandung$categoryName.
Pastikan Anda sudah mendefinisikan relasi category di model Post.
7. Menggunakan Full-Text Search dengan MySQL (Full-Text Search with MySQL)
Untuk performa pencarian yang lebih baik, terutama pada teks yang panjang, pertimbangkan untuk menggunakan fitur Full-Text Search MySQL.
Modifikasi Migrasi:
<?php
use IlluminateDatabaseMigrationsMigration;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateSupportFacadesSchema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->string('author');
$table->timestamps();
$table->fullText('title'); // Tambahkan fulltext index pada kolom title
$table->fullText('content'); // Tambahkan fulltext index pada kolom content
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('posts');
}
};
Jalankan migrasi dengan php artisan migrate:fresh.
Modifikasi Controller:
<?php
namespace AppHttpControllers;
use AppModelsPost;
use IlluminateHttpRequest;
use IlluminateSupportFacadesDB;
class SearchController extends Controller
{
public function index(Request $request)
{
$keyword = $request->input('keyword');
$posts = Post::where(function ($query) use ($keyword) {
$query->whereRaw("MATCH(title, content) AGAINST(? IN BOOLEAN MODE)", [$keyword]);
})
->get();
return view('search.results', compact('posts', 'keyword'));
}
}
Penjelasan:
MATCH(title, content) AGAINST(? IN BOOLEAN MODE): Menggunakan fungsiMATCHdanAGAINSTuntuk melakukan full-text search.IN BOOLEAN MODEmemungkinkan Anda menggunakan operator seperti+(harus ada),-(tidak boleh ada), dan*(wildcard).
Catatan: Fitur Full-Text Search hanya tersedia untuk tipe kolom TEXT atau VARCHAR.
8. Pagination: Menangani Hasil Pencarian yang Banyak (Pagination for Large Result Sets)
Jika hasil pencarian sangat banyak, menampilkan semuanya dalam satu halaman akan membuat halaman menjadi berat dan sulit dinavigasi. Pagination adalah solusi yang tepat.
Modifikasi Controller:
<?php
namespace AppHttpControllers;
use AppModelsPost;
use IlluminateHttpRequest;
class SearchController extends Controller
{
public function index(Request $request)
{
$keyword = strtolower($request->input('keyword'));
$posts = Post::whereRaw('LOWER(title) LIKE ?', ["%$keyword%"])
->orWhereRaw('LOWER(content) LIKE ?', ["%$keyword%"])
->paginate(10); // Menampilkan 10 hasil per halaman
return view('search.results', compact('posts', 'keyword'));
}
}
Penjelasan:
->paginate(10): Menggunakan methodpaginateuntuk membagi hasil menjadi halaman-halaman. Parameter10menentukan jumlah hasil per halaman.
Modifikasi View:
Tambahkan link pagination di view search.results.blade.php:
<!DOCTYPE html>
<html>
<head>
<title>Hasil Pencarian</title>
</head>
<body>
<h1>Hasil Pencarian untuk: {{ $keyword }}</h1>
@if($posts->count() > 0)
<ul>
@foreach($posts as $post)
<li>
<h2>{{ $post->title }}</h2>
<p>{{ Str::limit($post->content, 200) }}</p>
<p>Oleh: {{ $post->author }}</p>
</li>
@endforeach
</ul>
{{ $posts->links() }} <!-- Tampilkan link pagination -->
@else
<p>Tidak ada hasil ditemukan.</p>
@endif
</body>
</html>
{{ $posts->links() }} akan menghasilkan link pagination yang diperlukan.
9. Menggunakan Scout: Solusi Pencarian Full-Text yang Kuat (Leveraging Scout for Powerful Full-Text Search)
Laravel Scout menyediakan antarmuka sederhana berbasis driver untuk pencarian full-text. Scout mendukung driver seperti Algolia, Meilisearch, dan database SQL. Ini adalah solusi yang lebih canggih daripada hanya menggunakan Full-Text Search MySQL.
Instalasi Scout:
composer require laravel/scout
Konfigurasi:
Konfigurasikan driver pencarian di config/scout.php. Misalnya, jika Anda menggunakan Algolia, Anda perlu menginstal Algolia PHP SDK dan mengatur kunci API Anda.
Tambahkan Searchable Trait ke Model:
<?php
namespace AppModels;
use IlluminateDatabaseEloquentFactoriesHasFactory;
use IlluminateDatabaseEloquentModel;
use LaravelScoutSearchable;
class Post extends Model
{
use HasFactory, Searchable;
// ...
}
Import Data ke Index:
php artisan scout:import "AppModelsPost"
Modifikasi Controller:
<?php
namespace AppHttpControllers;
use AppModelsPost;
use IlluminateHttpRequest;
class SearchController extends Controller
{
public function index(Request $request)
{
$keyword = $request->input('keyword');
$posts = Post::search($keyword)->paginate(10);
return view('search.results', compact('posts', 'keyword'));
}
}
Penjelasan:
Post::search($keyword): Menggunakan methodsearchdari Scout untuk mencari data.
Scout memberikan fleksibilitas dan performa yang lebih baik untuk pencarian full-text.
10. Menampilkan Saran Pencarian (Search Suggestions)
Menampilkan saran pencarian saat pengguna mengetik dapat sangat meningkatkan pengalaman pengguna. Anda bisa menggunakan JavaScript dan AJAX untuk mengimplementasikan fitur ini.
Contoh Sederhana:
-
Buat Route untuk Saran Pencarian:
Route::get('/search/suggestions', [AppHttpControllersSearchController::class, 'suggestions'])->name('search.suggestions'); -
Buat Method
suggestionsdi Controller:public function suggestions(Request $request) { $keyword = $request->input('keyword'); $suggestions = Post::where('title', 'LIKE', "%$keyword%") ->limit(5) ->pluck('title'); return response()->json($suggestions); } -
Gunakan JavaScript untuk Menampilkan Saran:
const searchInput = document.querySelector('input[name="keyword"]'); const suggestionsList = document.getElementById('suggestions'); searchInput.addEventListener('keyup', function() { const keyword = this.value; if (keyword.length > 2) { // Hanya tampilkan saran jika keyword minimal 3 karakter fetch(`/search/suggestions?keyword=${keyword}`) .then(response => response.json()) .then(data => { suggestionsList.innerHTML = ''; data.forEach(suggestion => { const li = document.createElement('li'); li.textContent = suggestion; suggestionsList.appendChild(li); }); }); } else { suggestionsList.innerHTML = ''; // Kosongkan daftar saran jika keyword kurang dari 3 karakter } }); -
Tambahkan Elemen
uluntuk Menampilkan Saran di View:<form action="{{ route('search') }}" method="GET"> <input type="text" name="keyword" placeholder="Cari..."> <button type="submit">Cari</button> <ul id="suggestions"></ul> </form>
11. Kesimpulan: Memilih Pendekatan yang Tepat untuk Kebutuhan Anda (Choosing the Right Approach)
Membuat fitur pencarian di Laravel Eloquent bisa dilakukan dengan berbagai cara, mulai dari yang sederhana menggunakan where hingga yang canggih menggunakan Full-Text Search, Scout, dan saran pencarian. Pilihan tergantung pada kebutuhan aplikasi Anda, ukuran data, dan tingkat performa yang diinginkan.
- Pencarian Sederhana dengan
where: Cocok untuk aplikasi kecil dengan data yang sedikit dan kebutuhan pencarian yang sederhana. - Full-Text Search MySQL: Cocok untuk aplikasi dengan data teks yang panjang dan kebutuhan pencarian yang lebih canggih, tetapi terbatas pada kemampuan MySQL.
- Laravel Scout: Cocok untuk aplikasi yang membutuhkan performa tinggi dan fleksibilitas dalam memilih driver pencarian.
Dengan panduan ini, Anda sekarang memiliki pengetahuan yang cukup untuk membuat fitur search dengan Laravel Eloquent yang efektif dan efisien. Selamat mencoba dan semoga sukses!
12. Tips Tambahan: Keamanan dan Validasi (Security and Validation Tips)
Selain implementasi teknis, penting untuk memperhatikan keamanan dan validasi saat membuat fitur search dengan Laravel Eloquent.
- Sanitasi Input: Selalu sanitasi input pengguna untuk mencegah serangan SQL injection. Anda bisa menggunakan helper
e()atau metode validasi Laravel. - Validasi Input: Validasi input pengguna untuk memastikan kata kunci pencarian memenuhi kriteria tertentu (misalnya, panjang minimum, karakter yang diizinkan).
- Lindungi Route: Lindungi route pencarian dengan middleware otentikasi jika diperlukan.
- Limitasi Rate: Implementasikan limitasi rate untuk mencegah penyalahgunaan fitur pencarian.
- Hindari Menampilkan Informasi Sensitif: Pastikan hasil pencarian tidak menampilkan informasi sensitif yang tidak seharusnya diakses oleh pengguna.
Dengan mengikuti tips ini, Anda dapat memastikan fitur pencarian Anda aman dan andal.









