Skip to main content
The SummonerIconController handles HTTP requests for the summoner icon catalog with search, filtering, and administrative CRUD operations.

Overview

Located at source/app/Http/Controllers/SummonerIconController.php, this controller:
  • Displays paginated icon catalog (72 icons per page)
  • Filters by title, esports team, and release year
  • Sorts by icon ID (newest first)
  • Implements 1-hour caching with query-specific cache keys
  • Provides full CRUD operations for icon management
  • Shows individual icon detail pages

Class Definition

namespace App\Http\Controllers;

use App\Models\SummonerIcon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Spatie\QueryBuilder\QueryBuilder;

class SummonerIconController extends Controller
{
    // Controller methods
}

Routes

Defined in source/routes/web.php:51-52:
Route::get('icons', static fn () => (new SummonerIconController)->index())
    ->name('assets.icons.index');
    
Route::get('icon/{summonerIcon}', static fn (SummonerIcon $summonerIcon) => (new SummonerIconController)->show($summonerIcon))
    ->name('assets.icons.show');

Methods

index()

Displays a filterable, paginated listing of summoner icons.
public function index()
{
    $cacheKey = 'icons_' . md5(serialize(request()->query()));

    $icons = Cache::remember($cacheKey, 60 * 60, function () {
        return QueryBuilder::for(SummonerIcon::class)
            ->allowedFilters(['title', 'esports_team', 'release_year'])
            ->defaultSort('-icon_id')
            ->paginate(72)
            ->appends(request()->query());
    });

    return view('icons.index', ['icons' => $icons]);
}

Query Parameters

filter[title]
string
Filter by icon title (exact match)Example: ?filter[title]=Worlds 2023
filter[esports_team]
string
Filter by esports team abbreviationExample: ?filter[esports_team]=T1
filter[release_year]
integer
Filter by release yearExample: ?filter[release_year]=2023
page
integer
default:"1"
Page number for pagination (72 icons per page)Example: ?page=2

Return Value

view
Illuminate\View\View
Rendered icons.index Blade template

View Data

icons
LengthAwarePaginator<SummonerIcon>
Paginated collection of summoner icons (72 per page)

Cache Strategy

Icons are cached for 1 hour with a unique cache key per query combination using MD5 hash of serialized query parameters.
Cache Key Format: icons_{md5_hash_of_query} Examples:
  • icons_d41d8cd98f00b204e9800998ecf8427e (no filters)
  • icons_a3c2f1e9b8d7c6a5b4e3d2c1f0e9d8c7 (with filters)

Default Sorting

->defaultSort('-icon_id')
Icons are sorted by icon_id in descending order (newest icons first). The - prefix indicates descending sort.

Usage Examples

GET /icons

show()

Displays a specific icon’s detail page.
public function show(SummonerIcon $summonerIcon)
{
    $icon = $summonerIcon;
    return view('icons.show', ['icon' => $icon]);
}

Parameters

summonerIcon
SummonerIcon
required
SummonerIcon model instance (automatically resolved via route model binding)

Return Value

view
Illuminate\View\View
Rendered icons.show Blade template

View Data

icon
SummonerIcon
Individual summoner icon model

Usage Example

GET /icon/t1-worlds-2023-abc123
GET /icon/fnatic-lec-2024-def456

store()

Creates a new summoner icon (administrative function).
public function store(Request $request)
{
    $request->validate([
        'icon_id' => ['required', 'integer'],
        'title' => ['nullable'],
        'release_year' => ['nullable', 'integer'],
        'legacy' => ['required'],
        'image' => ['required'],
        'esports_team' => ['nullable'],
        'esports_region' => ['nullable'],
        'esports_event' => ['nullable'],
        'description' => ['nullable'],
    ]);

    return SummonerIcon::create($request->validated());
}

Validation Rules

icon_id
integer
required
Riot Games API icon ID
title
string
Icon display title
release_year
integer
Year the icon was released
legacy
boolean
required
Whether the icon is legacy (limited availability)
image
string
required
CDN URL for the icon image
esports_team
string
Team abbreviation (e.g., “T1”, “G2”)
esports_region
string
Region code (e.g., “LCK”, “LEC”)
esports_event
string
Event name (e.g., “Worlds 2023”)
description
string
Icon description text

Return Value

icon
SummonerIcon
Newly created SummonerIcon model instance

update()

Updates an existing summoner icon.
public function update(Request $request, SummonerIcon $summonerIcon)
{
    $request->validate([
        'icon_id' => ['required', 'integer'],
        'title' => ['nullable'],
        'release_year' => ['nullable', 'integer'],
        'legacy' => ['required'],
        'image' => ['required'],
        'esports_team' => ['nullable'],
        'esports_region' => ['nullable'],
        'esports_event' => ['nullable'],
        'description' => ['nullable'],
    ]);

    $summonerIcon->update($request->validated());

    return $summonerIcon;
}

Parameters

summonerIcon
SummonerIcon
required
Icon to update (resolved via route model binding)

Return Value

icon
SummonerIcon
Updated SummonerIcon model instance

destroy()

Deletes a summoner icon.
public function destroy(SummonerIcon $summonerIcon)
{
    $summonerIcon->delete();
    return response()->json();
}

Parameters

summonerIcon
SummonerIcon
required
Icon to delete (resolved via route model binding)

Return Value

response
JsonResponse
Empty JSON response with 200 status code

Spatie Query Builder

This controller uses Spatie Query Builder for filtering:
QueryBuilder::for(SummonerIcon::class)
    ->allowedFilters(['title', 'esports_team', 'release_year'])
    ->defaultSort('-icon_id')
    ->paginate(72)

Allowed Filters

Column: titleType: Exact matchExample: ?filter[title]=Worlds matches icons with exactly “Worlds” in the title
Column: esports_teamType: Exact matchExample: ?filter[esports_team]=T1 matches only T1 team icons
Column: release_yearType: Exact match (integer)Example: ?filter[release_year]=2023 matches only 2023 releases

Pagination

perPage
integer
default:"72"
Number of icons displayed per page
Pagination URLs:
/icons?page=1
/icons?page=2&filter[esports_team]=T1
/icons?page=3&filter[release_year]=2023

Performance Considerations

Query-Specific Caching

Each unique query combination gets its own cache key

1-Hour Cache

Icons cached for 1 hour per query

Large Pages

72 icons per page reduces number of requests

Indexed Queries

Ensure filterable columns are indexed

SummonerIcon Model

View the SummonerIcon model API reference

Assets Feature

Learn about the game assets browsing feature

Emote Controller

View the emote controller documentation

Architecture

Understand the MVC architecture

Build docs developers (and LLMs) love