
== Connections

Each node in your cluster is represented by a Connection object inside the client.  These objects are responsible
for communicating to the node, logging success or failure and reporting the results back to the Transport.

There are two Connection classes in the client which you can choose from:

=== GuzzleConnection (default)

The connection class uses the third party Guzzle HTTP library for communication.  Guzzle is an excellent library which
wraps PHP's cURL functionality.  This object is default because Guzzle has much experience fighting the oddities
and quirks of PHP cURL.

=== CurlMultiConnection

This is a lightweight connection class that also utilizes PHP's cURL functionality (it uses the same set of curl-multiselect
functionality that Guzzle does).  This class is entirely self-contained, however, so it can offer real advantages in speed
when it comes to autoloading costs (since Guzzle requires several classes to be autoloaded).  It has not been as
rigorously tested as Guzzle, which is why it is not default.

Once the relevant files have been autoloaded, performance between Guzzle and CurlMultiConnection is identical since
they both leverage the same underlying cURL calls.  It is recommended to only use CurlMultiConnection when you need
very fast autoloading, such as autocompletion.

=== Changing your ConnectionClass

Changing the connection class is very simple: instantiate the client with your chosen connection implementation:

[source,php]
----
$params['connectionClass'] = '\Elasticsearch\Connections\CurlMultiConnection';
$client = new Elasticsearch\Client($params);
----
{zwsp} +

=== Extending an existing Connection Class

Like many other components, you can completely replace the Connection object with your own.
The easiest way to do this is to over-ride one of the existing connection classes:

[source,php]
----
namespace MyProject;

class MyConnection extends \Elasticsearch\Connections\GuzzleConnection {

    /**
     * Perform an HTTP request on the cluster
     *
     * @param string      $method HTTP method to use for request
     * @param string      $uri    HTTP URI to use for request
     * @param null|string $params Optional URI parameters
     * @param null|string $body   Optional request body
     * @param array       $options
     *
     * @return array
     */
    public function performRequest($method, $uri, $params = null, $body = null, $options = array())
    {
        // do pre-request stuff
        $response = parent::performRequest($method, $uri, $params, $body, $options);
        // do post-request stuff
        return $response;
    }
}
----
{zwsp} +

This allows you to leverage the existing boilerplate and just over-ride the methods that you wish to tinker with.  You
can then use your new class by specifying it at instantiation.


[source,php]
----
$params['connectionClass'] = '\MyProject\MyConnection';
$client = new Elasticsearch\Client($params);
----
{zwsp} +


=== Writing your own Connection Class

If you wish to completely write your own connection class, you just need to implement the `ConnectionInterface`.

[source,php]
----
namespace Elasticsearch\Connections;

use Psr\Log\LoggerInterface;

interface ConnectionInterface
{
    public function __construct($hostDetails, $connectionParams, LoggerInterface $log, LoggerInterface $trace);

    public function getTransportSchema();

    public function isAlive();

    public function markAlive();

    public function markDead();

    public function getLastRequestInfo();

    public function performRequest($method, $uri, $params = null, $body = null);
}
----

The abstract `AbstractConnection` class provides useful boilerplate which you may wish to extend, such as various
utility logging methods.

=== Getting information about the last request

Logging is useful, but it is difficult to dial the verobisity to exactly what you want.  Sometimes you just want a
method that returns details about the last request and response.

For example, here we execute a search and then request details about that search:

[source,php]
----
$client = new Elasticsearch\Client();

$results = $client->search([
    'index' => 'test',
    'type' => 'test',
    'body' => [
        'query' => [
            'filtered' => [
                'filter' => [
                    'term' => [
                        'first_name' => 'zach'
                    ]
                ]
            ]
        ]
    ]
]);

$info = $client->transport->getLastConnection()->getLastRequestInfo();
print_r($info);
----

This will yield an output such as:

[source,php]
----
Array
(
    [request] => Array
        (
            [uri] => http://localhost:9200/test/test/_search?
            [body] => {"query":{"filtered":{"filter":{"term":{"first_name":"zach"}}}}}
            [options] => Array
                (
                )
            [method] => POST
        )
    [response] => Array
        (
            [body] => {"took":45,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":0,"max_score":null,"hits":[]}}
            [info] => Array
                (
                    [url] => http://localhost:9200/test/test/_search
                    [content_type] => application/json; charset=UTF-8
                    [http_code] => 200
                    [header_size] => 87
                    [request_size] => 191
                    [filetime] => -1
                    [ssl_verify_result] => 0
                    [redirect_count] => 0
                    [total_time] => 0.053979
                    [namelookup_time] => 0.001221
                    [connect_time] => 0.001941
                    [pretransfer_time] => 0.002086
                    [size_upload] => 64
                    [size_download] => 123
                    [speed_download] => 2278
                    [speed_upload] => 1185
                    [download_content_length] => 123
                    [upload_content_length] => 64
                    [starttransfer_time] => 0.053467
                    [redirect_time] => 0
                    [certinfo] => Array
                        (
                        )
                    [primary_ip] => ::1
                    [primary_port] => 9200
                    [local_ip] => ::1
                    [local_port] => 51168
                    [redirect_url] =>
                )
            [status] => 200
        )
)
----