Skip to main content
The SearchController provides HTMX-powered search functionality for categories and icons, returning partial views for dynamic UI updates.

Class Overview

namespace App\Http\Controllers;

use App\Models\Category;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Config;

class SearchController extends Controller

Routes

MethodRouteActionMiddleware
POST/search/iconssearchIconsauth, verified
POST/search/categories/{type}searchCategoriesauth, verified

Methods

searchCategories()

Search user’s categories by name and type.
public function searchCategories(Request $request, $type)
request
Request
required
The HTTP request containing search query
type
string
required
Category type filter: income, expense, correction, or transfer
Request Parameters:
Search query to filter categories by name (case-insensitive partial match)
Returns: View - Partial view categories.partials.results with filtered categories Response Data:
categories
Collection<Category>
Filtered categories matching search criteria, ordered by latest first, with eager-loaded transactions
Query Logic:
  1. Filter by current user
  2. Filter by category type
  3. Filter by name (partial match)
  4. Order by latest created
  5. Eager load transaction relationships
Example Implementation:
public function searchCategories(Request $request, $type)
{
    $search = $request->input('search');

    $categories = Category::query()
        ->latest()
        ->with('transactions')
        ->where('user_id', Auth::user()->id)
        ->where('type', $type)
        ->where(function ($query) use ($search) {
            $query->where('name', 'like', '%'.$search.'%');
        })
        ->get();

    return view('categories.partials.results', compact('categories'));
}
HTMX Usage:
<input 
    type="text" 
    name="search"
    hx-post="/search/categories/expense"
    hx-trigger="keyup changed delay:300ms"
    hx-target="#category-results"
    placeholder="Search expense categories..."
>

<div id="category-results">
    <!-- Results rendered here -->
</div>

searchIcons()

Search available icons by name and metadata tags.
public function searchIcons(Request $request)
request
Request
required
The HTTP request containing icon search query
Request Parameters:
Search query to filter icons by name or metadata tags (case-insensitive)
Returns: View - Partial view categories.partials.icons with filtered icons Response Data:
icons
array<string>
Array of icon filenames matching the search query
Search Algorithm:
  1. Load icon metadata from config/icons.php
  2. Sort icons alphabetically
  3. Filter by:
    • Icon filename contains query (case-insensitive)
    • OR any metadata tag contains query (case-insensitive)
  4. Return matching icon filenames
Example Implementation:
public function searchIcons(Request $request)
{
    $query = strtolower($request->input('icon-search', ''));
    $iconMetadata = Config::get('icons');

    usort($iconMetadata, function ($a, $b) {
        return strcmp($a['icon'], $b['icon']);
    });

    $icons = [];

    foreach ($iconMetadata as $data) {
        if (stripos($data['icon'], $query) !== false || $this->matchesKeywords($query, $data['tags'])) {
            $icons[] = $data['icon'];
        }
    }

    return view('categories.partials.icons', compact('icons'));
}

private function matchesKeywords($query, $keywords)
{
    foreach ($keywords as $keyword) {
        if (stripos($keyword, $query) !== false) {
            return true;
        }
    }
    return false;
}
Icon Metadata Structure:
// config/icons.php
return [
    [
        'icon' => 'shopping-cart.png',
        'tags' => ['shopping', 'cart', 'purchase', 'buy']
    ],
    [
        'icon' => 'restaurant.png',
        'tags' => ['food', 'dining', 'restaurant', 'meal']
    ],
    // ... more icons
];
HTMX Usage:
<input 
    type="text" 
    name="icon-search"
    hx-post="/search/icons"
    hx-trigger="keyup changed delay:300ms"
    hx-target="#icon-grid"
    placeholder="Search icons..."
>

<div id="icon-grid">
    <!-- Icon grid rendered here -->
</div>

Example Requests

Search Categories

# Search expense categories for "food"
POST /search/categories/expense
Content-Type: application/x-www-form-urlencoded

search=food

# Response: HTML partial with matching categories

Search Icons

# Search icons for "shopping"
POST /search/icons
Content-Type: application/x-www-form-urlencoded

icon-search=shopping

# Response: HTML partial with icon grid (shopping-cart.png, etc.)

Performance Notes

Both search methods use HTMX with debouncing (delay:300ms) to reduce server requests while typing.
Icon search loads all metadata into memory. For large icon sets (>1000 icons), consider caching the metadata or implementing pagination.

Build docs developers (and LLMs) love