1PHP bindings for Xapian
2***********************
3
4The PHP5 bindings for Xapian are packaged in the ``xapian``
5extension.  The PHP API provided by this extension largely follows Xapian's C++
6API.  This document lists the differences and additions.
7
8As of Xapian version 1.3.2, these bindings require at least PHP 5.5.
9(Older versions of PHP are now out of security support, but if you really need
10support for them then Xapian 1.2 supports PHP 5.0 and later).  PHP 7 is supported
11by a separate set of bindings (this approach was taken due to extensive changes
12to PHP's C extension API between PHP 5 and PHP 7).
13
14PHP strings, arrays, etc., are converted automatically to and from the
15corresponding C++ types in the bindings, so generally you can pass arguments as
16you would expect.  One thing to be aware of though is that SWIG implements
17dispatch functions for overloaded methods based on the types of the parameters,
18so you can't always pass in a string containing a number (e.g.
19``"42"``) where a number is expected as you usually can in PHP.
20You need to
21explicitly convert to the type required - e.g. use ``(int)`` to
22convert to an integer, ``(string)`` to string, ``(double)``
23to a floating point number.
24
25With version 1.2.6 and later, you can subclass Xapian classes in PHP and
26virtual methods defined in PHP are called from C++ in the way you'd expect.
27
28PHP has a lot of reserved words of various sorts, which sadly clash with common
29method names.  Because of this ``empty()`` methods of various
30container-like classes are wrapped as ``is_empty()`` for PHP
31and the ``clone()`` method of the ``XapianWeight``
32class and subclasses is wrapped as ``clone_object()``.
33
34The ``examples`` subdirectory contains examples showing how to use the
35PHP bindings based on the simple examples from ``xapian-examples``:
36`simpleindex.php5 <examples/simpleindex.php5>`_,
37`simplesearch.php5 <examples/simplesearch.php5>`_,
38`simpleexpand.php5 <examples/simpleexpand.php5>`_,
39`simplematchdecider.php5 <examples/simplematchdecider.php5>`_.
40
41Note that these examples are written to work with the command line (CLI)
42version of the PHP interpreter, not through a webserver.  Xapian's PHP
43bindings may of course also be used under CGI, Apache's modphp, ISAPI,
44etc.
45
46Installation
47============
48
49Assuming you have a suitable version of PHP installed, running
50configure will automatically enable the PHP bindings, and
51``make install`` will install the extension shared library in
52the location reported by ``php-config --extension-dir``.
53
54Check that php.ini has a line like ``extension_dir = "<location reported by php-config --extension-dir>"``.
55
56
57Then add this line to php.ini: ``extension = xapian.so`` (or
58whatever the library is called - not all UNIX systems use ``.so``
59as the extension, and MS Windows uses ``.dll``).
60
61If you're using PHP as a webserver module (e.g. mod_php with Apache), you
62may need to restart the webserver for this change to take effect.
63
64You also need to add ``include&nbsp;"xapian.php"``
65to your PHP scripts which use Xapian in order to get the PHP class wrappers.
66
67Exceptions
68##########
69
70Exceptions thrown by Xapian are translated into PHP Exception objects
71which are thrown into the PHP script.
72
73Object orientation
74##################
75
76These PHP bindings use a PHP object oriented style.
77
78To construct an object, use
79``$object = new XapianClassName(...);``.  Objects are destroyed
80when they go out of scope - to explicitly destroy an object you can use
81``unset($object);`` or ``$object = Null;``
82
83You invoke a method on an object using ``$object->method_name()``.
84
85Unicode Support
86###############
87
88The Xapian::Stem, Xapian::QueryParser, and
89Xapian::TermGenerator classes all assume text is in UTF-8.  If you want
90to index strings in a different encoding, use the PHP `iconv function <http://php.net/iconv>`_ to convert them to UTF-8 before passing them to Xapian, and when reading values back from Xapian.
91
92Iterators
93#########
94
95Since Xapian 1.3.2, Xapian's iterators (except ``XapianLatLongCoordsIterator``)
96are wrapped as PHP iterators, so can be used in ``foreach``.
97
98There's one important thing to beware of currently - the ``rewind()`` method
99on ``XapianPositionIterator``, ``XapianPostingIterator``,
100``XapianTermIterator`` and ``XapianValueIterator`` currently does nothing.  We
101can't make it simply throw an exception, as ``foreach`` calls ``rewind()``
102before iteration starts - each iterator needs to track if ``next()`` has been
103called yet, and we've not yet implemented machinery for that.  This doesn't
104affect the standard pattern of iterating once with ``foreach``, but if you want
105to iterate a second time, you can't reuse the iterator (but it will currently
106fail quietly).
107
108You can safely call ``rewind()`` on ``XapianESetIterator`` and
109``XapianMSetIterator``.
110
111The ``current()`` method returns the result of dereferencing the iterator
112in C++ (e.g. for a ``TermIterator``, it returns the term as a string - see
113the section below for more details) and the ``key()`` method returns the
114iterator object, which you can call other methods on, for example::
115
116    foreach ($db->allterms_begin() as $k => $term) {
117	print "{$k->get_termfreq()}\t$term\n";
118    }
119
120As well as the standard PHP iterator methods, MSetIterator and ESetIterator
121also support ``prev()`` to go back one place.
122
123Iterator dereferencing
124######################
125
126C++ iterators are often dereferenced to get information, eg
127``(*it)``. With PHP these are all mapped to named methods, as
128follows:
129
130+------------------+----------------------+
131| Iterator         | Dereferencing method |
132+==================+======================+
133| PositionIterator |   ``get_termpos()``  |
134+------------------+----------------------+
135| PostingIterator  |   ``get_docid()``    |
136+------------------+----------------------+
137| TermIterator     |   ``get_term()``     |
138+------------------+----------------------+
139| ValueIterator    |   ``get_value()``    |
140+------------------+----------------------+
141| MSetIterator     |   ``get_docid()``    |
142+------------------+----------------------+
143| ESetIterator     |   ``get_term()``     |
144+------------------+----------------------+
145
146Other methods, such as ``MSetIterator::get_document()``, are
147available unchanged.
148
149MSet
150####
151
152MSet objects have some additional methods to simplify access (these
153work using the C++ array dereferencing):
154
155+------------------------------------+----------------------------------------+
156| Method name                        |            Explanation                 |
157+====================================+========================================+
158| ``get_hit(index)``                 |   returns MSetIterator at index        |
159+------------------------------------+----------------------------------------+
160| ``get_document_percentage(index)`` | ``convert_to_percent(get_hit(index))`` |
161+------------------------------------+----------------------------------------+
162| ``get_document(index)``            | ``get_hit(index)->get_document()``     |
163+------------------------------------+----------------------------------------+
164| ``get_docid(index)``               | ``get_hit(index)->get_docid()``        |
165+------------------------------------+----------------------------------------+
166
167
168Database Factory Functions
169##########################
170
171
172- ``Xapian::Auto::open_stub(file)`` is wrapped as ``Xapian::auto_open_stub(file)`` (now deprecated)
173- ``Xapian::Chert::open()`` is wrapped as ``Xapian::chert_open()`` (now deprecated)
174- ``Xapian::InMemory::open()`` is wrapped as ``Xapian::inmemory_open()`` (now deprecated)
175- ``Xapian::Remote::open(...)`` is wrapped as ``Xapian::remote_open(...)`` (both the TCP and "program" versions are wrapped - the SWIG wrapper checks the parameter list to decide which to call).
176- ``Xapian::Remote::open_writable(...)`` is wrapped as ``Xapian::remote_open_writable(...)`` (both the TCP and "program" versions are wrapped - the SWIG wrapper checks the parameter list to decide which to call).
177
178Constants
179#########
180
181Constants are wrapped as ``const`` members of the appropriate class.
182So ``Xapian::DB_CREATE_OR_OPEN`` is available as
183``Xapian::DB_CREATE_OR_OPEN``, ``Xapian::Query::OP_OR`` is
184available as ``XapianQuery::OP_OR``, and so on.
185
186Functions
187#########
188
189Non-class functions are wrapped in the natural way, so the C++
190function ``Xapian::version_string`` is wrapped under the same
191name in PHP.
192
193Query
194#####
195
196In C++ there's a Xapian::Query constructor which takes a query operator and
197start/end iterators specifying a number of terms or queries, plus an optional
198parameter.  In PHP, this is wrapped to accept an array listing the terms
199and/or queries (you can specify a mixture of terms and queries if you wish)
200For example:
201
202::
203
204   $subq = new XapianQuery(XapianQuery::OP_AND, "hello", "world");
205   $q = new XapianQuery(XapianQuery::OP_AND, array($subq, "foo", new XapianQuery("bar", 2)));
206
207
208
209MatchAll and MatchNothing
210-------------------------
211
212In Xapian 1.3.0 and later, these are wrapped as static methods
213``XapianQuery::MatchAll()`` and ``XapianQuery::MatchNothing()``.
214
215If you want to be compatible with earlier versions, you can continue to use
216``new XapianQuery('')`` for MatchAll and
217``new XapianQuery()`` for MatchNothing.
218
219
220Enquire
221#######
222
223There is an additional method ``get_matching_terms()`` which takes
224an MSetIterator and returns a list of terms in the current query which
225match the document given by that iterator.  You may find this
226more convenient than using the TermIterator directly.
227