diff --git a/extensions/sphinx/ActiveRecord.php b/extensions/sphinx/ActiveRecord.php
index 690a59d..58325c6 100644
--- a/extensions/sphinx/ActiveRecord.php
+++ b/extensions/sphinx/ActiveRecord.php
@@ -11,6 +11,7 @@ use yii\base\InvalidConfigException;
 use yii\base\InvalidParamException;
 use yii\base\Model;
 use yii\base\ModelEvent;
+use yii\base\NotSupportedException;
 use yii\base\UnknownMethodException;
 use yii\db\ActiveRelationInterface;
 use yii\db\Expression;
@@ -92,6 +93,10 @@ class ActiveRecord extends Model
 	 * @var array related models indexed by the relation names
 	 */
 	private $_related = [];
+	/**
+	 * @var string snippet value for this Active Record instance.
+	 */
+	private $_snippet;
 
 	/**
 	 * Returns the Sphinx connection used by this AR class.
@@ -248,6 +253,90 @@ class ActiveRecord extends Model
 	}
 
 	/**
+	 * Builds a snippet from provided data and query, using specified index settings.
+	 * @param string|array $source is the source data to extract a snippet from.
+	 * It could be either a single string or array of strings.
+	 * @param string $query the full-text query to build snippets for.
+	 * @param array $options list of options in format: optionName => optionValue
+	 * @return string|array built snippet in case "source" is a string, list of built snippets
+	 * in case "source" is an array.
+	 */
+	public static function callSnippets($source, $query, $options = [])
+	{
+		$command = static::getDb()->createCommand();
+		$command->callSnippets(static::indexName(), $source, $query, $options);
+		if (is_array($source)) {
+			return $command->queryColumn();
+		} else {
+			return $command->queryScalar();
+		}
+	}
+
+	/**
+	 * Returns tokenized and normalized forms of the keywords, and, optionally, keyword statistics.
+	 * @param string $text the text to break down to keywords.
+	 * @param boolean $fetchStatistic whether to return document and hit occurrence statistics
+	 * @return array keywords and statistics
+	 */
+	public static function callKeywords($text, $fetchStatistic = false)
+	{
+		$command = static::getDb()->createCommand();
+		$command->callKeywords(static::indexName(), $text, $fetchStatistic);
+		return $command->queryAll();
+	}
+
+	/**
+	 * @param string $snippet
+	 */
+	public function setSnippet($snippet)
+	{
+		$this->_snippet = $snippet;
+	}
+
+	/**
+	 * @param string $query snippet source query
+	 * @param array $options list of options in format: optionName => optionValue
+	 * @return string snippet value
+	 */
+	public function getSnippet($query = null, $options = [])
+	{
+		if ($query !== null) {
+			$this->_snippet = $this->fetchSnippet($query, $options);
+		}
+		return $this->_snippet;
+	}
+
+	/**
+	 * Builds up the snippet value from the given query.
+	 * @param string $query the full-text query to build snippets for.
+	 * @param array $options list of options in format: optionName => optionValue
+	 * @return string snippet value.
+	 */
+	protected function fetchSnippet($query, $options = [])
+	{
+		return static::callSnippets($this->getSnippetSource(), $query, $options);
+	}
+
+	/**
+	 * Returns the string, which should be used as a source to create snippet for this
+	 * Active Record instance.
+	 * Child classes must implement this method to return the actual snippet source text.
+	 * For example:
+	 * ```php
+	 * public function getSnippetSource()
+	 * {
+	 *     return $this->snippetSourceRelation->content;
+	 * }
+	 * ```
+	 * @return string snippet source string.
+	 * @throws \yii\base\NotSupportedException if this is not supported by the Active Record class
+	 */
+	public function getSnippetSource()
+	{
+		throw new NotSupportedException($this->className() . ' does not provide snippet source.');
+	}
+
+	/**
 	 * Returns the name of the column that stores the lock version for implementing optimistic locking.
 	 *
 	 * Optimistic locking allows multiple users to access the same record for edits and avoids
@@ -1137,7 +1226,7 @@ class ActiveRecord extends Model
 	 */
 	public function offsetSet($offset, $item)
 	{
-		// Bypass relation owner restriction to 'yii\db\ActiveRecord' at [[ActiveRelationTrait::findWith()]]:
+		// Bypass relation owner restriction to 'yii\db\ActiveRecord' at [[yii\db\ActiveRelationTrait::findWith()]]:
 		try {
 			$relation = $this->getRelation($offset);
 			if (is_object($relation)) {
diff --git a/tests/unit/extensions/sphinx/ActiveRecordTest.php b/tests/unit/extensions/sphinx/ActiveRecordTest.php
index fe15697..815ebe8 100644
--- a/tests/unit/extensions/sphinx/ActiveRecordTest.php
+++ b/tests/unit/extensions/sphinx/ActiveRecordTest.php
@@ -202,4 +202,27 @@ class ActiveRecordTest extends SphinxTestCase
 		$records = RuntimeIndex::find()->all();
 		$this->assertEquals(0, count($records));
 	}
+
+	public function testCallSnippets()
+	{
+		$query = 'pencil';
+		$source = 'Some data sentence about ' . $query;
+
+		$snippet = ArticleIndex::callSnippets($source, $query);
+		$this->assertNotEmpty($snippet, 'Unable to call snippets!');
+		$this->assertContains('<b>' . $query . '</b>', $snippet, 'Query not present in the snippet!');
+
+		$rows = ArticleIndex::callSnippets([$source], $query);
+		$this->assertNotEmpty($rows, 'Unable to call snippets!');
+		$this->assertContains('<b>' . $query . '</b>', $rows[0], 'Query not present in the snippet!');
+	}
+
+	public function testCallKeywords()
+	{
+		$text = 'table pencil';
+		$rows = ArticleIndex::callKeywords($text);
+		$this->assertNotEmpty($rows, 'Unable to call keywords!');
+		$this->assertArrayHasKey('tokenized', $rows[0], 'No tokenized keyword!');
+		$this->assertArrayHasKey('normalized', $rows[0], 'No normalized keyword!');
+	}
 }
\ No newline at end of file