// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements.  See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License.  You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
= PHP Thin Client

== Prerequisites
* link:http://php.net/manual/en/install.php[PHP version 7.2 or higher,window=_blank] and link:https://getcomposer.org/download[Composer Dependency Manager,window=_blank]
* php-xml module
* link:http://php.net/manual/en/mbstring.installation.php[PHP Multibyte String extension].
Depending on your PHP configuration, you may need to additionally install/configure it.

== Installation

The PHP thin client is shipped as a Composer package and a zip archive. Use any of the methods to install the client in your environment.

=== Using Composer

include::includes/install-php-composer.adoc[]

=== Using ZIP Archive

The thin client can be installed from the zip archive available for download from the Apache Ignite website:

*  Download the link:https://ignite.apache.org/download.cgi#binaries[Apache Ignite PHP Thin Client,window=_blank].
*  Unpack the archive and navigate to the root folder.
*  Use the command below to install the package.

[source,shell]
----
composer install --no-dev
----

To use the client in your application, include the `vendor/autoload.php` file, generated by Composer, to your source code.

[source,php]
----
require_once "<php_client_root_dir>/vendor/autoload.php";
----

== Creating a Client Instance
All operations of the PHP thin client are performed through a `Client` instance. You can create as many `Client` instances
as needed. All of them will work independently.

[source, php]
----
use Apache\Ignite\Client;

$client = new Client();
----

== Connecting to Cluster

To connect to a cluster, define a `ClientConfiguration` object with the desired connection parameters and use the `Client.connect(...)` method.

[source, php]
----
include::code-snippets/php/ConnectingToCluster.php[tag=connecting,indent=0]
----

The `ClientConfiguration` constructor accepts a list of node endpoints. At least one endpoint must be specified. If you specify more than one, the thin client will use them for link:thin-clients/getting-started-with-thin-clients#client-connection-failover[failover purposes].

If the client cannot connect to the cluster, a `NoConnectionException`  is thrown when attempting to perform any remote operation.

If the client unexpectedly loses the connection before or during an operation, an `OperationStatusUnknownException` is thrown.
In this case, it is not known if the operation has been actually executed in the cluster or not.
The client will try to reconnect to the next node specified in the configuration when the next operation is called by the application.

Call the `disconnect()` method to close the connection.


== Using Key-Value API

=== Getting/Creating a Cache Instance

The client instance provides three methods for obtaining an instance of a cache:

* `getCache(name)` — returns an existing cache by name. The method does not verify if the cache exists in the cluster; instead, you will get an exception when attempting to perform any operation with the cache.
* `getOrCreateCache(name, config)` — returns an existing cache by name or creates a cache with the given configuration.
* `createCache(name, config)` — creates a cache with the given name and parameters.

This is how you can create a cache:

[source, php]
----
include::code-snippets/php/UsingKeyValueApi.php[tag=createCache,indent=0]
----

=== Basic Key-Value Operations

The following code snippet illustrates how to perform basic key-value operations with a cache instance:

[source, php]
----
include::code-snippets/php/UsingKeyValueApi.php[tag=basicOperations,indent=0]
----

////
TODO
=== Asynchronous Execution
////


== Scan Queries
The `Cache.query(ScanQuery)` method can be used to fetch all entries from the cache. It returns a cursor object with the standard PHP Iterator interface — use this cursor to iterate over the result set lazily, one by one. In addition, the cursor has methods to get all results at once.

////
*TODO: illustrate how to use the iterator in the example*
////

[source, php]
----
include::code-snippets/php/UsingKeyValueApi.php[tag=scanQry,indent=0]
----

== Executing SQL Statements
The PHP thin client supports all link:sql-reference[SQL commands] that are supported by Ignite.
The commands are executed via the `query(SqlFieldQuery)` method of the cache object.
The method accepts an instance of `SqlFieldsQuery` that represents a SQL statement.
The `query()` method returns a cursor object with the standard PHP Iterator interface — use this cursor to iterate over the result set lazily, one by one. In addition, the cursor has methods to get all results at once.

[source, php]
----
include::code-snippets/php/UsingKeyValueApi.php[tag=executingSql,indent=0]
----

== Security

=== SSL/TLS
To use encrypted communication between the thin client and the cluster, you have to enable it both in the cluster configuration and the client configuration. Refer to the link:thin-clients/getting-started-with-thin-clients#enabling-ssltls-for-thin-clients[Enabling SSL/TLS for Thin Clients] section for the instruction on the cluster configuration.

Here is an example configuration for enabling SSL in the thin client:
[source, php]
----
include::code-snippets/php/Security.php[tag=tls,indent=0]
----

=== Authentication
Configure link:security/authentication[authentication on the cluster side] and provide a valid user name and password in the client configuration.

[source, php]
----
include::code-snippets/php/Security.php[tag=authentication,indent=0]
----



