
Для механизма поиска используем расширение Yii2 Zend Lucene Search Component V2
Устанавливаем его через composer.
Могут быть ошибки, что не находятся нужные версии. У меня всё подтянулось с такими строками в сcmposer.json
<span>"zendframework/zendsearch": "2.0.0rc5", "zendframework/zend-stdlib": "2.3.1 as 2.0.0rc5", "himiklab/yii2-search-component-v2": "*"</span>
Добавляю в конфиг для консоли в массив components (это config/console.php)
'search' => [ 'class' => 'himiklab\yii2\search\Search', 'models' => [ 'app\models\Blog', ], ],
и его же добавляю в конфиг самого приложения (config/web.php).
в папке commands создаю контроллер SearchController.php для вызова через консоль, чтобы создать поисковый индекс по классу Blog
<?php namespace app\commands; use Yii; use yii\console\Controller; class SearchController extends Controller { // Of course, this function should be in the console part of the application! public function actionIndexing() { /** @var \himiklab\yii2\search\Search $search */ $search = Yii::$app->search; $search->index(); } }
в UrlManager -> rules мне пришлось добавить правило для вызова действия поиска после ввода запроса. Иначе роуты конфликтуют с другими
'blog'=>'blog/index', 'blog/create'=>'blog/create', <strong>'blog/search'=>'blog/search',</strong> 'blog/<section:\w+>'=>'blog/index', 'blog/<tag:\w+>'=>'blog/index',
Вот это действие, добавляю его в контроллер BlogController.php
public function actionSearch($q = '') { /** @var \himiklab\yii2\search\Search $search */ $search = Yii::$app->search; $searchData = $search->find($q); // Search by full index. //$searchData = $search->find($q, ['model' => 'page']); // Search by index provided only by model `page`. $dataProvider = new ArrayDataProvider([ 'allModels' => $searchData['results'], 'pagination' => ['pageSize' => 10], ]); return $this->render( 'found', [ 'hits' => $dataProvider->getModels(), 'pagination' => $dataProvider->getPagination(), 'query' => $searchData['query'] ] ); }
также ему понадобилось подключить вверху этого контроллера строку
use yii\data\ArrayDataProvider;
в модели models/Blog подключаю поведение
use himiklab\yii2\search\behaviors\SearchBehavior;
и в массив поведений добавляю 'search'
public function behaviors() { return [ ... 'search' => [ 'class' => SearchBehavior::className(), 'searchScope' => function ($model) { /** @var \yii\db\ActiveQuery $model */ $model->select(['title', 'text', 'id', 'alias']); //$model->andWhere(['indexed' => true]); }, 'searchFields' => function ($model) { /** @var self $model */ return [ ['name' => 'title', 'value' => $model->title], ['name' => 'body', 'value' => strip_tags($model->text)], ['name' => 'url', 'value' => '/blog/'.$model->id.'-'.$this->alias, 'type' => SearchBehavior::FIELD_KEYWORD], // ['name' => 'model', 'value' => 'page', 'type' => SearchBehavior::FIELD_UNSTORED], ]; } ], ]; }
копирую целиком из папки расширения yii2-search-component-v2 модуль search в корневую папку с модулями /modules (если её нет, то создаю её)
в нужном месте вида вставляю окно поиска
<?= $this->render('_search_form', ['text' => '']) ?>
_search_form.php создаю в этой же папке где лежит сей вид. Вот содержимое _search_form.php
<?php use yii\helpers\Html; use yii\helpers\Url; ?> <?= Html::beginForm(Url::to(['/blog/search']), 'get', ['class' => 'form-inlin']) ?> <div class="input-group"> <?= Html::textInput('q', $text, ['class' => 'form-control', 'placeholder' => 'Поиск...']) ?> <span class="input-group-btn"> <?= Html::submitButton('<i class="glyphicon glyphicon-search"></i>', ['class' => 'btn btn-primary']) ?> </span> </div><!-- /input-group --> <?= Html::endForm() ?> <br/>
и вот содержимое файла вида found.php с результатами поиска
use yii\helpers\Html; $query = yii\helpers\Html::encode($query); $this->params['breadcrumbs'][] = ['label' => 'Блог', 'url' => ['/blog']]; $this->title = "Результаты поиска по запросу \"$query\""; $this->params['breadcrumbs'][] = $this->title; app\modules\search\SearchAssets::register($this); $this->registerJs("jQuery('.search').highlight('{$query}');"); ?> <div class="row"> <div class="col-md-6 col-md-offset-2"> <?php if (!empty($hits)): foreach ($hits as $hit): ?> <h3><a href="<?= yii\helpers\Url::to($hit->url, true) ?>"><?= $hit->title ?></a></h3> <p class="search"><?= $hit->body ?></p> <hr /> <?php endforeach; else: ?> <div class="alert alert-danger"><h3>По запросу "<?= $query ?>" ничего не найдено!</h3></div> <?php endif; echo yii\widgets\LinkPager::widget([ 'pagination' => $pagination, ]); ?> </div> <div class="col-md-3"> <?= $this->render('_search_form', ['text' => "{$query}"]) ?> <?= app\components\SectionsWidget::widget() ?> <hr> <?= app\components\TagsWidget::widget() ?> </div> </div>
Вот и всё.
Чтобы поиск давал результаты, надо через консоль выполнить команду
./yii search/indexing
Вот что должно быть видно в консоли (при команде ./yii выполненной в папке проекта вы увидите, что появилась доступная команда search/indexing)
Аматизировать создание поискового индекса с помощью КРОНа
Далее, чтобы периодически не выполнять эту команду вручную по мере публикации новых статей, удобно автоматизировать её вызов с помощью КРОН на хостинге. Например, задайте в КРОНе вызов
sh $HOME/inspire2/makesearchindex.sh
один раз в сутки. Создайте в корневой папке этот файл makesearchindex.sh с содержимым
#!/bin/bashcd $HOME/inspire2 ./yii search/indexing
Возможные ошибки
1. Если будет ошибка
Exception 'yii\base\UnknownPropertyException' with message 'Getting unknown property: yii\console\Application::search'
значит в компонентах консоли не указали компонент 'search' или в нём пути к классу или модели.
2. При вводе запроса и нажатии кнопки поиска такая ошибка
Getting unknown property: yii\web\Application::search
Значит забыли добавить в конфиг приложения компонент 'search'
17 августа 2015, Программирование, веб-кодинг, Расширения, виджеты / Метки: поиск

