- P1: Product::listing() 分页(WHERE status=1+LIMIT/OFFSET+总数),ProductController 改用并加翻页器,消除列表全表
- P1: outputSitemap() 加 storage/cache/sitemap.xml 文件缓存(TTL 3600s),消除每次爬虫全表
- P2: 首页 banner 改 whereLimit('status',1,20)
- P2: asset() 追加 ?v=filemtime 版本串,theme.css 改后自动击穿 1y 浏览器缓存
- P2: nginx 启用 gzip(文本资源压缩)
- P2: Model::count() $val 隐式可空改 mixed(PHP 8.4+ 弃用)
64 lines
2.5 KiB
PHP
64 lines
2.5 KiB
PHP
<?php
|
||
namespace App\Models;
|
||
|
||
use Core\Model;
|
||
|
||
class Product extends Model
|
||
{
|
||
protected $table = 'products';
|
||
protected $orderBy = 'sort_order';
|
||
|
||
public function byCategory(int $catId): array
|
||
{
|
||
return $this->whereAll('category_id', $catId);
|
||
}
|
||
public function featured(int $limit = 6): array
|
||
{
|
||
// V0.9.1:改用 whereLimit('status',1,$limit),MySQL 下走带 LIMIT 的索引查询,
|
||
// 不再 SELECT * 全表拉回再 array_filter(原写法每次请求都全表扫描)。
|
||
return $this->whereLimit('status', 1, $limit);
|
||
}
|
||
/**
|
||
* V0.9.4:产品列表分页。仅取 status=1 的活跃商品,按 $orderBy 排序,带 LIMIT/OFFSET;
|
||
* 同时返回总数用于翻页。避免每次列表请求都 SELECT * 全表拉回再 array_filter(原写法随 SKU 增长变重)。
|
||
* 文件模式回退为全表过滤 + array_slice。
|
||
* @return array{items:array,total:int}
|
||
*/
|
||
public function listing(int $page, int $perPage, ?int $catId = null): array
|
||
{
|
||
$page = max(1, $page);
|
||
$perPage = max(1, $perPage);
|
||
$offset = ($page - 1) * $perPage;
|
||
if (\Core\Db::driver() === 'mysql') {
|
||
$where = 'WHERE status = 1';
|
||
$args = [];
|
||
if ($catId !== null) { $where .= ' AND category_id = ?'; $args[] = $catId; }
|
||
$items = \Core\Db::query(
|
||
"SELECT * FROM `{$this->table}` {$where} ORDER BY `{$this->orderBy}` ASC LIMIT ? OFFSET ?",
|
||
array_merge($args, [$perPage, $offset])
|
||
)->fetchAll();
|
||
$total = (int) \Core\Db::query("SELECT COUNT(*) FROM `{$this->table}` {$where}", $args)->fetchColumn();
|
||
return ['items' => $items, 'total' => $total];
|
||
}
|
||
// 文件模式兜底
|
||
$all = array_filter($this->all(), fn($p) => ($p['status'] ?? 1) == 1);
|
||
if ($catId !== null) $all = array_filter($all, fn($p) => ($p['category_id'] ?? 0) == $catId);
|
||
$all = array_values($all);
|
||
return ['items' => array_slice($all, $offset, $perPage), 'total' => count($all)];
|
||
}
|
||
public function specsArray($p): array
|
||
{
|
||
$s = $p['specs'] ?? '';
|
||
if (is_array($s)) return $s;
|
||
$dec = json_decode((string)$s, true);
|
||
return is_array($dec) ? $dec : [];
|
||
}
|
||
public function galleryArray($p): array
|
||
{
|
||
$g = $p['gallery'] ?? '';
|
||
if (is_array($g)) return $g;
|
||
$dec = json_decode((string)$g, true);
|
||
return is_array($dec) ? $g : [];
|
||
}
|
||
}
|