

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# Oggetti di comando nella AWS SDK per PHP versione 3
<a name="guide_commands"></a>

 AWS SDK per PHP utilizza il [modello di comando](http://en.wikipedia.org/wiki/Command_pattern) per incapsulare i parametri e il gestore che verranno utilizzati per trasferire una richiesta HTTP in un secondo momento.

## Uso implicito dei comandi
<a name="implicit-use-of-commands"></a>

Se si esaminano le classi di client, è possibile vedere che i metodi corrispondenti alle operazioni delle API in realtà non esistono. La loro implementazione avviene utilizzando il metodo magico `__call()`. Questi pseudo-metodi sono in realtà collegamenti che incapsulano l'utilizzo degli oggetti di comando di SDK.

In genere, non è necessario interagire direttamente con gli oggetti di comando. Quando si chiamano metodi come `Aws\S3\S3Client::putObject()`, in realtà SDK crea un `Aws\CommandInterface` in base ai parametri forniti, esegue il comando e restituisce un oggetto `Aws\ResultInterface` popolato (o genera un'eccezione in caso di errore). Un flusso simile si verifica quando viene chiamato un metodo `Async` di un client (ad esempio, `Aws\S3\S3Client::putObjectAsync()`): il client crea un comando in base ai parametri forniti, serializza una richiesta HTTP, avvia la richiesta e restituisce una promessa.

I seguenti esempi sono equivalenti da un punto di vista funzionale.

```
$s3Client = new Aws\S3\S3Client([
    'version' => '2006-03-01',
    'region'  => 'us-standard'
]);

$params = [
    'Bucket' => 'amzn-s3-demo-bucket',
    'Key'    => 'baz',
    'Body'   => 'bar'
];

// Using operation methods creates a command implicitly
$result = $s3Client->putObject($params);

// Using commands explicitly
$command = $s3Client->getCommand('PutObject', $params);
$result = $s3Client->execute($command);
```

## Parametri di comando
<a name="command-parameters"></a>

Tutti i comandi supportano alcuni parametri speciali che non fanno parte di un'API del servizio, ma che controllano invece il comportamento di SDK.

### `@http`
<a name="http"></a>

Quando si utilizza questo parametro, è possibile ottimizzare il modo in cui il gestore HTTP sottostante esegue la richiesta. Le opzioni che possono essere incluse nel parametro `@http` sono le stesse che possono essere impostate quando si crea un'istanza del client con l'[opzione client "http"](guide_configuration.md#config-http).

```
// Configures the command to be delayed by 500 milliseconds
$command['@http'] = [
    'delay' => 500,
];
```

### `@retries`
<a name="retries"></a>

Come nel caso dell'[opzione client "nuovi tentativi"](guide_configuration.md#config-retries), `@retries` controlla il numero massimo di nuovi tentativi di un comando prima che venga considerato non riuscito. Impostalo su `0` per disabilitare i nuovi tentativi.

```
// Disable retries
$command['@retries'] = 0;
```

**Nota**  
Se i nuovi tentativi sono stati disabilitati per un client, non è possibile abilitarli in modo selettivo su singoli comandi passati al client in questione.

## Creazione di oggetti di comando
<a name="creating-command-objects"></a>

È possibile creare un comando utilizzando il metodo `getCommand()` di un client. Non esegue o trasferisce immediatamente una richiesta HTTP, ma viene eseguito soltanto quando viene passato al metodo `execute()` del client. In questo modo, è possibile modificare l'oggetto di comando prima di eseguire il comando.

```
$command = $s3Client->getCommand('ListObjects');
$command['MaxKeys'] = 50;
$command['Prefix'] = 'foo/baz/';
$result = $s3Client->execute($command);

// You can also modify parameters
$command = $s3Client->getCommand('ListObjects', [
    'MaxKeys' => 50,
    'Prefix'  => 'foo/baz/',
]);
$command['MaxKeys'] = 100;
$result = $s3Client->execute($command);
```

## Comando `HandlerList`
<a name="command-handlerlist"></a>

Quando un comando viene creato da un client, gli viene assegnato un clone dell'oggetto `Aws\HandlerList` del client. Al comando viene assegnato un **clone** dell'elenco dei gestori del client per consentire a un comando di utilizzare middleware e gestori personalizzati che non interessano altri comandi eseguiti dal client.

In questo modo, è possibile utilizzare un client HTTP diverso per ogni comando (ad esempio, `Aws\MockHandler`) e aggiungere un comportamento personalizzato per ogni comando tramite middleware. I seguenti esempi utilizzano un `MockHandler` per creare risultati fittizi anziché inviare richieste HTTP effettive.

```
use Aws\Result;
use Aws\MockHandler;

// Create a mock handler
$mock = new MockHandler();
// Enqueue a mock result to the handler
$mock->append(new Result(['foo' => 'bar']));
// Create a "ListObjects" command
$command = $s3Client->getCommand('ListObjects');
// Associate the mock handler with the command
$command->getHandlerList()->setHandler($mock);
// Executing the command will use the mock handler, which returns the
// mocked result object
$result = $client->execute($command);

echo $result['foo']; // Outputs 'bar'
```

Oltre a modificare il gestore utilizzato dal comando, è anche possibile includere un middleware personalizzato nel comando. L'esempio seguente utilizza il middleware `tap`, che funge da osservatore nell'elenco dei gestori.

```
use Aws\CommandInterface;
use Aws\Middleware;
use Psr\Http\Message\RequestInterface;

$command = $s3Client->getCommand('ListObjects');
$list = $command->getHandlerList();

// Create a middleware that just dumps the command and request that is
// about to be sent
$middleware = Middleware::tap(
    function (CommandInterface $command, RequestInterface $request) {
        var_dump($command->toArray());
        var_dump($request);
    }
);

// Append the middleware to the "sign" step of the handler list. The sign
// step is the last step before transferring an HTTP request.
$list->append('sign', $middleware);

// Now transfer the command and see the var_dump data
$s3Client->execute($command);
```

## `CommandPool`
<a name="command-pool"></a>

`Aws\CommandPool` consente di eseguire comandi simultaneamente utilizzando un'iterazione che produce oggetti `Aws\CommandInterface`. `CommandPool` garantisce che un numero costante di comandi venga eseguito simultaneamente durante l'iterazione sui comandi nel pool (mentre i comandi vengono completati, ne vengono eseguiti altri per garantire dimensioni del pool costanti).

Di seguito è riportato un semplice esempio di invio di alcuni comandi utilizzando `CommandPool`.

```
use Aws\S3\S3Client;
use Aws\CommandPool;

// Create the client
$client = new S3Client([
    'region'  => 'us-standard',
    'version' => '2006-03-01'
]);

$bucket = 'amzn-s3-demo-bucket';
$commands = [
    $client->getCommand('HeadObject', ['Bucket' => $bucket, 'Key' => 'a']),
    $client->getCommand('HeadObject', ['Bucket' => $bucket, 'Key' => 'b']),
    $client->getCommand('HeadObject', ['Bucket' => $bucket, 'Key' => 'c'])
];

$pool = new CommandPool($client, $commands);

// Initiate the pool transfers
$promise = $pool->promise();

// Force the pool to complete synchronously
$promise->wait();
```

Questo esempio per `CommandPool` è piuttosto elementare. L'esempio seguente è più complesso. Supponiamo che tu voglia caricare file su disco in un bucket Amazon S3. Per ottenere un elenco dei file del disco, è possibile utilizzare la funzione `DirectoryIterator` di PHP. Questa iterazione genera oggetti `SplFileInfo`. `CommandPool` accetta un'iterazione che genera oggetti `Aws\CommandInterface`, perciò occorre eseguire la mappatura sugli oggetti `SplFileInfo` per restituire oggetti `Aws\CommandInterface`.

```
<?php
require 'vendor/autoload.php';

use Aws\Exception\AwsException;
use Aws\S3\S3Client;
use Aws\CommandPool;
use Aws\CommandInterface;
use Aws\ResultInterface;
use GuzzleHttp\Promise\PromiseInterface;

// Create the client
$client = new S3Client([
    'region'  => 'us-standard',
    'version' => '2006-03-01'
]);

$fromDir = '/path/to/dir';
$toBucket = 'amzn-s3-demo-bucket';

// Create an iterator that yields files from a directory
$files = new DirectoryIterator($fromDir);

// Create a generator that converts the SplFileInfo objects into
// Aws\CommandInterface objects. This generator accepts the iterator that
// yields files and the name of the bucket to upload the files to.
$commandGenerator = function (\Iterator $files, $bucket) use ($client) {
    foreach ($files as $file) {
        // Skip "." and ".." files
        if ($file->isDot()) {
            continue;
        }
        $filename = $file->getPath() . '/' . $file->getFilename();
        // Yield a command that is executed by the pool
        yield $client->getCommand('PutObject', [
            'Bucket' => $bucket,
            'Key'    => $file->getBaseName(),
            'Body'   => fopen($filename, 'r')
        ]);
    }
};

// Now create the generator using the files iterator
$commands = $commandGenerator($files, $toBucket);

// Create a pool and provide an optional array of configuration
$pool = new CommandPool($client, $commands, [
    // Only send 5 files at a time (this is set to 25 by default)
    'concurrency' => 5,
    // Invoke this function before executing each command
    'before' => function (CommandInterface $cmd, $iterKey) {
        echo "About to send {$iterKey}: "
            . print_r($cmd->toArray(), true) . "\n";
    },
    // Invoke this function for each successful transfer
    'fulfilled' => function (
        ResultInterface $result,
        $iterKey,
        PromiseInterface $aggregatePromise
    ) {
        echo "Completed {$iterKey}: {$result}\n";
    },
    // Invoke this function for each failed transfer
    'rejected' => function (
        AwsException $reason,
        $iterKey,
        PromiseInterface $aggregatePromise
    ) {
        echo "Failed {$iterKey}: {$reason}\n";
    },
]);

// Initiate the pool transfers
$promise = $pool->promise();

// Force the pool to complete synchronously
$promise->wait();

// Or you can chain the calls off of the pool
$promise->then(function() { echo "Done\n"; });
```

### Configurazione di `CommandPool`
<a name="commandpool-configuration"></a>

Il costruttore `Aws\CommandPool` accetta varie opzioni di configurazione.

**concurrency (callable\$1int)**  
Numero massimo di comandi da eseguire simultaneamente. È possibile fornire una funzione per ridimensionare il pool in modo dinamico. La funzione include l'attuale numero di richieste in sospeso e dovrebbe restituire un numero intero che rappresenta il nuovo limite delle dimensioni del pool.

**before (callable)**  
Funzione che consente di eseguire l'invocazione prima dell'invio di un comando. La funzione `before` accetta il comando e la chiave dell'iterazione del comando. È possibile modificare il comando secondo necessità nella funzione `before` prima di inviare il comando.

**fulfilled (callable)**  
Funzione che consente di effettuare l'invocazione quando una promessa viene soddisfatta. La funzione include l'oggetto risultato, l'ID dell'iterazione da cui proveniva il risultato e la promessa in forma aggregata che può essere risolta o respinta se occorre cortocircuitare il pool.

**rejected (callable)**  
Funzione che consente di effettuare l'invocazione quando una promessa viene respinta. La funzione include un oggetto `Aws\Exception`, l'ID dell'iterazione da cui proveniva l'eccezione e la promessa in forma aggregata che può essere risolta o respinta se occorre cortocircuitare il pool.

### Raccolta manuale dei rifiuti tra i comandi
<a name="manual-garbage-collection-between-commands"></a>

Se pool di comandi di grandi dimensioni causano il raggiungimento del limite di memoria, la causa è da ricercarsi nei riferimenti ciclici generati dall'SDK che non sono ancora stati raccolti dal [garbage collector PHP](https://www.php.net/manual/en/features.gc.php) quando il limite di memoria è stato raggiunto. L'invocazione manuale dell'algoritmo di raccolta tra i comandi può consentire la raccolta dei cicli prima del raggiungimento di tale limite. L'esempio seguente crea un `CommandPool` che richiama l'algoritmo di raccolta utilizzando un callback prima dell'invio di ogni comando. L'invocazione di garbage collector comporta costi di prestazioni e l'uso ottimale dipende dal caso d'uso e dall'ambiente.

```
$pool = new CommandPool($client, $commands, [
    'concurrency' => 25,
    'before' => function (CommandInterface $cmd, $iterKey) {
        gc_collect_cycles();
    }
]);
```