README.md 7.23 KB
Newer Older
Qiang Xue committed
1 2
Sphinx Extension for Yii 2
==========================
3

Qiang Xue committed
4
This extension adds [Sphinx](http://sphinxsearch.com/docs) full text search engine extension for the Yii 2 framework.
5
It supports all Sphinx features including [Runtime Indexes](http://sphinxsearch.com/docs/current.html#rt-indexes).
6 7


Klimov Paul committed
8 9 10 11 12 13 14
Requirements
------------

At least Sphinx version 2.0 is required. However, in order to use all extension features, Sphinx version 2.2 or
higher is required.


15 16 17 18 19 20
Installation
------------

The preferred way to install this extension is through [composer](http://getcomposer.org/download/).

Either run
Qiang Xue committed
21

22
```
23
php composer.phar require --prefer-dist yiisoft/yii2-sphinx "*"
24 25 26
```

or add
Qiang Xue committed
27 28

```json
29 30 31
"yiisoft/yii2-sphinx": "*"
```

Qiang Xue committed
32
to the require section of your composer.json.
33 34


35 36
Configuration
-------------
37

Qiang Xue committed
38
This extension interacts with Sphinx search daemon using MySQL protocol and [SphinxQL](http://sphinxsearch.com/docs/current.html#sphinxql) query language.
39
In order to setup Sphinx "searchd" to support MySQL protocol following configuration should be added:
Qiang Xue committed
40

41 42 43
```
searchd
{
44 45
    listen = localhost:9306:mysql41
    ...
46 47
}
```
48

49 50 51 52
To use this extension, simply add the following code in your application configuration:

```php
return [
53 54 55 56 57 58 59 60 61
    //....
    'components' => [
        'sphinx' => [
            'class' => 'yii\sphinx\Connection',
            'dsn' => 'mysql:host=127.0.0.1;port=9306;',
            'username' => '',
            'password' => '',
        ],
    ],
62
];
63 64
```

65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132

Basic Usage
-----------

Since this extension uses MySQL protocol to access Sphinx, it shares base approach and much code from the
regular "yii\db" package. Running SphinxQL queries a very similar to regular SQL ones:

```php
$sql = 'SELECT * FROM idx_item WHERE group_id = :group_id';
$params = [
    'group_id' => 17
];
$rows = Yii::$app->sphinx->createCommand($sql, $params)->queryAll();
```

You can also use a Query Builder:

```php
use yii\sphinx\Query;

$query = new Query;
$rows = $query->select('id, price')
    ->from('idx_item')
    ->andWhere(['group_id' => 1])
    ->all();
```

> Note: Sphinx limits the number of records returned by any query to 10 records by default.
  If you need to get more records you should specify limit explicitly.


Composing 'MATCH' statement
---------------------------

Sphinx usage does not make sense unless you are using its fulltext search ability.
In SphinxSQL it is provided via 'MATCH' statement. You can always compose it manually as a part of the 'where'
condition, but if you are using `yii\sphinx\Query` you can do it via `yii\sphinx\Query::match()`:

```php
use yii\sphinx\Query;

$query = new Query;
$rows = $query->from('idx_item')
    ->match($_POST['search'])
    ->all();
```

Please note that Sphinx 'MATCH' statement argument uses complex internal syntax for better tuning.
By default `yii\sphinx\Query::match()` will escape all special characters related to this syntax from
its argument. So if you wish to use complex 'MATCH' statement, you should use `yii\db\Expression` for it:

```php
use yii\sphinx\Query;
use yii\db\Expression;

$query = new Query;
$rows = $query->from('idx_item')
    ->match(new Expression(':match', ['match' => '@(content) ' . Yii::$app->sphinx->escapeMatchValue($_POST['search'])]))
    ->all();
```

> Note: if you compose 'MATCH' argument, make sure to use `yii\sphinx\Connection::escapeMatchValue()` to properly
  escape any special characters, which may break the query.


Using the ActiveRecord
----------------------

133 134 135 136 137 138 139 140 141
This extension provides ActiveRecord solution similar ot the [[\yii\db\ActiveRecord]].
To declare an ActiveRecord class you need to extend [[\yii\sphinx\ActiveRecord]] and
implement the `indexName` method:

```php
use yii\sphinx\ActiveRecord;

class Article extends ActiveRecord
{
142 143 144 145 146 147 148
    /**
     * @return string the name of the index associated with this ActiveRecord class.
     */
    public static function indexName()
    {
        return 'idx_article';
    }
149 150 151
}
```

152 153 154 155

Working with data providers
---------------------------

156 157 158 159 160 161 162 163 164
You can use [[\yii\data\ActiveDataProvider]] with the [[\yii\sphinx\Query]] and [[\yii\sphinx\ActiveQuery]]:

```php
use yii\data\ActiveDataProvider;
use yii\sphinx\Query;

$query = new Query;
$query->from('yii2_test_article_index')->match('development');
$provider = new ActiveDataProvider([
165 166 167 168
    'query' => $query,
    'pagination' => [
        'pageSize' => 10,
    ]
169 170 171 172 173 174 175 176 177
]);
$models = $provider->getModels();
```

```php
use yii\data\ActiveDataProvider;
use app\models\Article;

$provider = new ActiveDataProvider([
178 179 180 181
    'query' => Article::find(),
    'pagination' => [
        'pageSize' => 10,
    ]
182 183
]);
$models = $provider->getModels();
Qiang Xue committed
184
```
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252


Building Snippets (Excerpts)
----------------------------

Snippet (excerpt) - is a fragment of the index source text, which contains highlighted words from fulltext search
condition. Sphinx has a powerful build-in mechanism to compose snippets. However, since Sphinx does not store the
original indexed text, the snippets for the rows in query result should be build separately via another query.
Such query may be performed via `yii\sphinx\Command::callSnippets()`:

```php
$sql = "SELECT * FROM idx_item WHERE MATCH('about')";
$rows = Yii::$app->sphinx->createCommand($sql)->queryAll();

$rowSnippetSources = [];
foreach ($rows as $row) {
    $rowSnippetSources[] = file_get_contents('/path/to/index/files/' . $row['id'] . '.txt');
}

$snippets = Yii::$app->sphinx->createCommand($sql)->callSnippets('idx_item', $rowSnippetSources, 'about');
```

You can simplify this workflow using [[yii\sphinx\Query::snippetCallback]].
It is a PHP callback, which receives array of query result rows as an argument and must return the
array of snippet source strings in the order, which match one of incoming rows.
Example:

```php
use yii\sphinx\Query;

$query = new Query;
$rows = $query->from('idx_item')
    ->match($_POST['search'])
    ->snippetCallback(function ($rows) {
        $result = [];
        foreach ($rows as $row) {
            $result[] = file_get_contents('/path/to/index/files/' . $row['id'] . '.txt');
        }
        return $result;
    })
    ->all();

foreach ($rows as $row) {
    echo $row['snippet'];
}
```

If you are using Active Record, you can [[yii\sphinx\ActiveQuery::snippetByModel()]] to compose a snippets.
This method retrieves snippet source per each row calling `getSnippetSource()` method of the result model.
All you need to do is implement it in your Active Record class, so it return the correct value:

```php
use yii\sphinx\ActiveRecord;

class Article extends ActiveRecord
{
    public function getSnippetSource()
    {
        return file_get_contents('/path/to/source/files/' . $this->id . '.txt');;
    }
}

$articles = Article::find()->snippetByModel()->all();

foreach ($articles as $article) {
    echo $article->snippet;
}
```
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276


Using Gii generator
-------------------

This extension provides a code generator, which can be integrated with yii 'gii' module. It allows generation of the
Active Record code. In order to enable it, you should adjust your application configuration in following way:

```php
return [
    //....
    'modules' => [
        // ...
        'gii' => [
            'class' => 'yii\gii\Module',
            'generators' => [
                'sphinxModel' => [
                    'class' => 'yii\sphinx\gii\model\Generator'
                ]
            ],
        ],
    ]
];
```