Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
815 changes: 253 additions & 562 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
copyright = f"2012-{date.today().year}, {author}"

# We track release notes in CHANGELOG.md and do not hardcode package versions here.
version = "4.x"
version = "current"
release = version

extensions = [
Expand Down
69 changes: 52 additions & 17 deletions docs/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
Configuration
=============

Creating a Connection
---------------------
Driver Setup
------------

Use one of the supported drivers:
MySQLi driver:

.. code-block:: php

Expand All @@ -15,12 +15,15 @@ Use one of the supported drivers:
use Foolz\SphinxQL\Drivers\Mysqli\Connection;

$conn = new Connection();
$conn->setParams(array(
$conn->setParams([
'host' => '127.0.0.1',
'port' => 9306,
));
'options' => [
MYSQLI_OPT_CONNECT_TIMEOUT => 2,
],
]);

You can also use the PDO driver:
PDO driver:

.. code-block:: php

Expand All @@ -29,25 +32,57 @@ You can also use the PDO driver:
use Foolz\SphinxQL\Drivers\Pdo\Connection;

$conn = new Connection();
$conn->setParams(array(
$conn->setParams([
'host' => '127.0.0.1',
'port' => 9306,
));
'charset' => 'utf8',
]);

Connection Parameters
---------------------

``setParams()`` and ``setParam()`` accept:
``setParams()`` and ``setParam()`` support:

- ``host`` (string, default ``127.0.0.1``)
- ``port`` (int, default ``9306``)
- ``socket`` (string|null, default ``null``)
- ``username`` (string|null, optional)
- ``password`` (string|null, optional)
- ``options`` (array, driver-specific client options)
- ``socket`` (string|null)
- ``username`` (string|null)
- ``password`` (string|null)
- ``charset`` (PDO DSN option)
- ``options`` (array, driver-specific options)

Notes:

- Setting ``host`` to ``localhost`` is normalized to ``127.0.0.1``.
- Socket notation like ``unix:/path/to/socket`` is converted to ``socket``.

Escaping and Quoting
--------------------

Value escaping and quoting are connection-driven.

.. code-block:: php

<?php

$quotedText = $conn->quote('hello'); // 'hello'
$quotedInt = $conn->quote(42); // 42
$quotedNull = $conn->quote(null); // null
$quotedList = $conn->quote([1, 2, 3]); // (1,2,3)

For raw SQL fragments, use ``SphinxQL::expr()``.

.. code-block:: php

<?php

use Foolz\SphinxQL\SphinxQL;

Strict Validation Notes
-----------------------
$sql = (new SphinxQL($conn))
->select()
->from('rt')
->option('field_weights', SphinxQL::expr('(title=80, content=35)'))
->compile()
->getCompiled();

The query builder validates critical inputs at runtime in 4.0.
Prefer explicit values over implicit coercion.
// SELECT * FROM rt OPTION field_weights = (title=80, content=35)
33 changes: 20 additions & 13 deletions docs/contribute.rst
Original file line number Diff line number Diff line change
@@ -1,31 +1,37 @@
Contribute
==========

Thanks for improving SphinxQL Query Builder.

Pull Requests
-------------

1. Fork `SphinxQL Query Builder <https://github.com/FoolCode/SphinxQL-Query-Builder>`_
2. Create a new branch for each feature or improvement
3. Submit a pull request with your branch against the default branch
1. Fork `SphinxQL Query Builder <https://github.com/FoolCode/SphinxQL-Query-Builder>`_.
2. Create a branch for your change.
3. Open a pull request against the default branch.

It is very important that you create a new branch for each feature, improvement, or fix so that may review the changes and merge the pull requests in a timely manner.
Please keep each pull request focused on one logical change.

Coding Style
------------
Development Guidelines
----------------------

All pull requests should follow modern PHP style conventions (PSR-12 compatible formatting).
- Follow PSR-12 style.
- Add/update tests for behavior changes.
- Update docs when public API behavior changes.

Testing
-------

All pull requests must be accompanied with passing tests and code coverage. The SphinxQL Query Builder uses `PHPUnit <https://github.com/sebastianbergmann/phpunit/>`_ for testing.
Run the Docker-based matrix used in CI:

Documentation
-------------
.. code-block:: bash

./scripts/run-tests-docker.sh

Documentation is built with Sphinx and the Furo theme.
This runs PHPUnit for both mysqli and PDO configurations.

Build locally:
Build Docs Locally
------------------

.. code-block:: bash

Expand All @@ -35,4 +41,5 @@ Build locally:
Issue Tracker
-------------

You can find our issue tracker at our `SphinxQL Query Builder <https://github.com/FoolCode/SphinxQL-Query-Builder>`_ repository.
Use the GitHub issue tracker:
`github.com/FoolCode/SphinxQL-Query-Builder/issues <https://github.com/FoolCode/SphinxQL-Query-Builder/issues>`_.
87 changes: 87 additions & 0 deletions docs/features/facet.rst
Original file line number Diff line number Diff line change
@@ -1,2 +1,89 @@
Facets
======

``Facet`` builds ``FACET`` clauses for grouped aggregations.

Building a Facet
----------------

.. code-block:: php

<?php

use Foolz\SphinxQL\Facet;

$facet = (new Facet($conn))
->facet(['gid'])
->orderBy('gid', 'ASC');

Common compiled outputs from tests:

- ``facet(['gid'])`` -> ``FACET gid``
- ``facet(['gid', 'title', 'content'])`` -> ``FACET gid, title, content``
- ``facet(['alias' => 'gid'])`` -> ``FACET gid AS alias``
- ``facetFunction('COUNT', 'gid')`` -> ``FACET COUNT(gid)``
- ``facetFunction('INTERVAL', ['price', 200, 400, 600, 800])`` -> ``FACET INTERVAL(price,200,400,600,800)``

Using FACET with SELECT
-----------------------

FACET is returned as an extra result set, so use ``executeBatch()``.

.. code-block:: php

<?php

use Foolz\SphinxQL\Facet;
use Foolz\SphinxQL\SphinxQL;

$batch = (new SphinxQL($conn))
->select()
->from('rt')
->facet(
(new Facet($conn))
->facet(['gid'])
->orderBy('gid', 'ASC')
)
->executeBatch()
->getStored();

// $batch[0] => SELECT rows
// $batch[1] => FACET rows with gid + count(*)

Advanced Facet Options
----------------------

Add ``BY``:

.. code-block:: php

$facet = (new Facet($conn))
->facet(['gid', 'title', 'content'])
->by('gid');

Sort by expression:

.. code-block:: php

$facet = (new Facet($conn))
->facet(['gid', 'title'])
->orderByFunction('COUNT', '*', 'DESC');

Paginate facet rows:

.. code-block:: php

$facet = (new Facet($conn))
->facet(['gid', 'title'])
->orderByFunction('COUNT', '*', 'DESC')
->limit(5, 5);

Validation Notes
----------------

``Facet`` throws ``SphinxQLException`` for invalid inputs such as:

- empty ``facet()`` columns
- invalid order directions
- invalid ``limit()`` / ``offset()``
- ``facetFunction()`` without parameters
74 changes: 74 additions & 0 deletions docs/features/match-builder.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
MatchBuilder
============

``MatchBuilder`` helps compose advanced ``MATCH()`` expressions.

Use it directly, or pass a callback to ``SphinxQL::match()``.

Standalone Build
----------------

.. code-block:: php

<?php

use Foolz\SphinxQL\MatchBuilder;
use Foolz\SphinxQL\SphinxQL;

$sq = new SphinxQL($conn);

$match = (new MatchBuilder($sq))
->field('content')
->match('directly')
->orMatch('lazy')
->compile()
->getCompiled();

// @content directly | lazy

Inline with Query Builder
-------------------------

.. code-block:: php

$rows = (new SphinxQL($conn))
->select()
->from('rt')
->match(function ($m) {
$m->field('content')
->match('directly')
->orMatch('lazy');
})
->execute()
->getStored();

Real Compiled Examples from Tests
---------------------------------

- ``match('test case')`` -> ``(test case)``
- ``match('test')->orMatch('case')`` -> ``test | case``
- ``phrase('test case')`` -> ``"test case"``
- ``proximity('test case', 5)`` -> ``"test case"~5``
- ``quorum('this is a test case', 3)`` -> ``"this is a test case"/3``
- ``field('body', 50)->match('test')`` -> ``@body[50] test``
- ``ignoreField('title', 'body')->match('test')`` -> ``@!(title,body) test``
- ``zone(['h3', 'h4'])`` -> ``ZONE:(h3,h4)``
- ``zonespan('th', 'test')`` -> ``ZONESPAN:(th) test``

Expressions and Escaping
------------------------

Raw expression bypass:

.. code-block:: php

use Foolz\SphinxQL\SphinxQL;

$expr = (new MatchBuilder($sq))
->match(SphinxQL::expr('test|case'))
->compile()
->getCompiled();

// test|case

Without ``Expression``, special characters are escaped.
Loading