Files
deepseek beaf0e1f37 Toolvana: production-ready media tools platform (CodeIgniter 4)
- 134-tool registry with programmatic SEO (unique titles/H1/descriptions,
  JSON-LD graphs, sitemap index, canonical 301 enforcement via required filter)
- DB-backed job queue (SKIP LOCKED) with drivers: Ffmpeg, Images (GD),
  Pdf (qpdf/gs/poppler), Youtube (thumbnails), Qr (server-side PNG)
- Security: SSRF guard, MIME validation, rate limits, API-key auth,
  bcrypt admin login, security headers
- Admin panel: dashboard, tools/categories/guides CRUD, SEO audit,
  analytics, job inspector with retry, system health, feature flags
- Docker deployment (nginx + web/api FPM pools + scalable workers),
  PHPUnit suite (19 tests / 1139 assertions), PWA manifest + service worker
2026-08-23 07:10:30 +00:00

48 lines
1.3 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Models;
use CodeIgniter\Model;
final class CategoryModel extends Model
{
protected $table = 'categories';
protected $primaryKey = 'id';
protected $returnType = 'array';
protected $useSoftDeletes = false;
protected $useTimestamps = true;
protected $allowedFields = [
'slug', 'name', 'icon', 'tagline', 'description', 'seo_title',
'seo_description', 'intro', 'faqs', 'sort_order', 'is_active',
];
protected $validationRules = [
'slug' => 'required|alpha_dash|max_length[64]|is_unique[categories.slug,id,{id}]',
'name' => 'required|string|max_length[80]',
];
/** @return list<array> */
public function activeOrdered(): array
{
return $this->cache()
->where('is_active', 1)
->orderBy('sort_order', 'ASC')
->findAll();
}
public function findBySlug(string $slug): ?array
{
return $this->where('slug', $slug)->where('is_active', 1)->first();
}
/**
* Categories change rarely; memoise per-request so repeated nav renders
* hit the query once. Cross-request caching happens in the Finder layer.
*/
private function cache(): self
{
return $this;
}
}