電商後台需支援商品關鍵字全文搜尋、價格區間篩選、Ajax 無重整分頁。技術棧:Yii 2.0、Sphinx Search、Pjax/Ajax 分頁。
<?php
namespace backend\controllers;
use Yii;
use yii\web\Controller;
use yii\data\Pagination;
use SphinxClient;
use backend\models\Goods;
class SouController extends Controller
{
public function actionIndex()
{
$sou = Yii::$app->request->get('sou', '');
$p1 = Yii::$app->request->get('p1', '');
$p2 = Yii::$app->request->get('p2', '');
// 1. Sphinx 搜尋
$cl = new SphinxClient();
$cl->SetServer('127.0.0.1', 9312);
$cl->SetConnectTimeout(3);
$cl->SetArrayResult(true);
if ($sou) {
$cl->SetMatchMode(SPH_MATCH_ANY); // 任一關鍵字
} else {
$cl->SetMatchMode(SPH_MATCH_FULLSCAN); // 全掃描
}
// 價格區間過濾(屬性需在索引定義為 int)
if ($p1 && $p2) {
$cl->SetFilterRange('price', (int)$p1, (int)$p2);
}
$res = $cl->Query($sou, 'mysql_goods');
if (!$res || empty($res['matches'])) {
$ids = [];
} else {
$ids = array_column($res['matches'], 'id');
}
// 2. MySQL 二次查詢取完整欄位
$query = Goods::find()->where(['id' => $ids]);
$countQuery = clone $query;
$pages = new Pagination([
'totalCount' => $countQuery->count(),
'defaultPageSize' => 3,
]);
$models = $query->offset($pages->offset)
->limit($pages->limit)
->all();
// 3. 關鍵字高亮(簡易版)
foreach ($models as $k => $v) {
$models[$k]['goods_name'] = str_replace(
$sou,
"$sou",
$v['goods_name']
);
}
return $this->render('index', [
'res' => $models,
'pages' => $pages,
'sou' => $sou,
'p1' => $p1,
'p2' => $p2,
]);
}
}
?>
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\widgets\LinkPager;
$form = ActiveForm::begin([
'action' => ['sou/index'],
'method' => 'get',
]) ?>
<center>
<div id="list">
商品名稱: <input type="text" name="sou" value="<?= Html::encode($sou) ?>">
價格區間: <input type="text" name="p1" value="<?= Html::encode($p1) ?>">---
<input type="text" name="p2" value="<?= Html::encode($p2) ?>">
<input type="submit" value="搜尋">
<table border="1" style="width:500px;">
<tr><th>ID</th><th>商品名稱</th><th>商品價格</th></tr>
<?php foreach ($res as $v): ?>
<tr>
<td><?= $v['id'] ?></td>
<td><?= $v['goods_name'] ?></td>
<td><?= $v['price'] ?></td>
</tr>
<?php endforeach; ?>
</table>
<!-- 分頁 -->
<?= LinkPager::widget(['pagination' => $pages]) ?>
</div>
</center>
<?php ActiveForm::end() ?>
<?php $this->beginBlock('ajax_pager') ?>
$(document).on('click', '.pagination a', function(e) {
e.preventDefault();
var href = $(this).attr('href');
$.post(href, function(html) {
$('#list').html(html);
});
});
<?php $this->endBlock();
$this->registerJs($this->blocks['ajax_pager'], \yii\web\View::POS_END); ?>
SPH_MATCH_ANY 適合關鍵字搜尋;SPH_MATCH_FULLSCAN 配合屬性過濾(如價格)可實現無關鍵字的篩選。.pagination a 點擊,用 $.post 取回整個 #list 區塊 HTML 直接替換,保持搜尋條件與高亮狀態。Html::encode() 輸出使用者輸入;高亮替換僅針對可信關鍵字,實務上建議用 HtmlPurifier。yii\widgets\Pjax 獲得瀏覽器歷史支援與 SEO 友善。