PHPackages                             anders/ami-react - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Queues &amp; Workers](/categories/queues)
4. /
5. anders/ami-react

ActiveLibrary[Queues &amp; Workers](/categories/queues)

anders/ami-react
================

Async, event-driven access to the Asterisk Manager Interface (AMI)

v0.3.1(9y ago)021MITPHPPHP &gt;=5.3

Since Jul 18Pushed 8y agoCompare

[ Source](https://github.com/oskonnikov/php-ami-react)[ Packagist](https://packagist.org/packages/anders/ami-react)[ Docs](https://github.com/clue/php-ami-react)[ RSS](/packages/anders-ami-react/feed)WikiDiscussions master Synced 3d ago

READMEChangelogDependencies (4)Versions (6)Used By (0)

anders/ami-react [![Build Status](https://camo.githubusercontent.com/48d9b6f9e97d22cc3fc64e8e5bc0ae77a4449e254e58134afef79ff8e58bff43/68747470733a2f2f7472617669732d63692e6f72672f6f736b6f6e6e696b6f762f7068702d616d692d72656163742e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/oskonnikov/php-ami-react)
========================================================================================================================================================================================================================================================================================================================

[](#andersami-react-)

Simple async, event-driven access to the Asterisk Manager Interface (AMI) Custom version

The [Asterisk PBX](http://asterisk.org/) is a popular open source telephony solution that offers a wide range of telephony features. The [Asterisk Manager Interface (AMI)](https://wiki.asterisk.org/wiki/display/AST/The+Asterisk+Manager+TCP+IP+API)allows you to control and monitor the PBX. Among others, it can be used to originate a new call, execute Asterisk commands or monitor the status of subscribers, channels or queues.

- **Async execution of Actions** - Send any number of actions (commands) to the asterisk in parallel and process their responses as soon as results come in. The Promise-based design provides a *sane* interface to working with out of bound responses.
- **Event-driven core** - Register your event handler callbacks to react to incoming events, such as an incoming call or a change in a subscriber state.
- **Lightweight, SOLID design** - Provides a thin abstraction that is [*just good enough*](http://en.wikipedia.org/wiki/Principle_of_good_enough)and does not get in your way. Future or custom actions and events require no changes to be supported.
- **Good test coverage** - Comes with an automated tests suite and is regularly tested against versions as old as Asterisk 1.8+

**Table of contents**

- [Quickstart example](#quickstart-example)
- [Usage](#usage)
    - [Factory](#factory)
        - [createClient)](#createclient)
    - [Client](#client)
        - [on()](#on)
        - [close()](#close)
        - [end()](#end)
        - [Advanced](#advanced)
            - [createAction()](#createaction)
            - [request()](#request)
    - [ActionSender](#actionsender)
        - [Actions](#actions)
        - [Processing](#processing)
        - [Custom actions](#custom-actions)
    - [Message](#message)
        - [getFieldValue()](#getfieldvalue)
        - [getFieldValues()](#getfieldvalues)
        - [getFields()](#getfields)
        - [getActionId()](#getactionid)
    - [Response](#response)
        - [getCommandOutput()](#getcommandoutput)
    - [Action](#action)
    - [Event](#event)
        - [getName()](#getname)
- [Install](#install)
- [Tests](#tests)
- [License](#license)

Quickstart example
------------------

[](#quickstart-example)

Once [installed](#install), you can use the following code to access your local Asterisk Telephony instance and issue some simple commands via AMI:

```
$loop = React\EventLoop\Factory::create();
$factory = new Factory($loop);

$factory->createClient('user:secret@localhost')->then(function (Client $client) {
    echo 'Client connected' . PHP_EOL;

    $sender = new ActionSender($client);
    $sender->listCommands()->then(function (Response $response) {
        echo 'Available commands:' . PHP_EOL;
        var_dump($response);
    });
});

$loop->run();
```

See also the [examples](examples).

Usage
-----

[](#usage)

### Factory

[](#factory)

The `Factory` is responsible for creating your [`Client`](#client) instance. It also registers everything with the main [`EventLoop`](https://github.com/reactphp/event-loop#usage).

```
$loop = \React\EventLoop\Factory::create();
$factory = new Factory($loop);
```

If you need custom DNS or proxy settings, you can explicitly pass a custom instance of the [`ConnectorInterface`](https://github.com/reactphp/socket-client#connectorinterface):

```
$factory = new Factory($loop, $connector);
```

#### createClient()

[](#createclient)

The `createClient(string $amiUrl): PromiseInterface` method can be used to create a new [`Client`](#client). It helps with establishing a plain TCP/IP or secure SSL/TLS connection to the AMI and issuing an initial `login` action.

```
$factory->createClient('user:secret@localhost')->then(
    function (Client $client) {
        // client connected and authenticated
    },
    function (Exception $e) {
        // an error occured while trying to connect or authorize client
    }
);
```

> Note: The given $amiUrl *must* include a host, it *should* include a username and secret and it *can* include a scheme (tcp/ssl) and port definition.

### Client

[](#client)

The `Client` is responsible for exchanging messages with the Asterisk Manager Interface and keeps track of pending actions.

If you want to send outgoing actions, see below for the [`ActionSender`](#actionsender) class.

#### on()

[](#on)

The `on(string $eventName, callable $eventHandler): void` method can be used to register a new event handler. Incoming events and errors will be forwarded to registered event handler callbacks:

```
$client->on('event', function (Event $event) {
    // process an incoming AMI event (see below)
});
$client->on('close', function () {
    // the connection to the AMI just closed
});
$client->on('error', function (Exception $e) {
    // and error has just been detected, the connection will terminate...
});
```

#### close()

[](#close)

The `close(): void` method can be used to force-close the AMI connection and reject all pending actions.

#### end()

[](#end)

The `end(): void` method can be used to soft-close the AMI connection once all pending actions are completed.

#### Advanced

[](#advanced)

Creating [`Action`](#action) objects, sending them via AMI and waiting for incoming [`Response`](#response) objects is usually hidden behind the [`ActionSender`](#actionsender) interface.

If you happen to need a custom or otherwise unsupported action, you can also do so manually as follows. Consider filing a PR though :)

##### createAction()

[](#createaction)

The `createAction(string $name, array $fields): Action` method can be used to construct a custom AMI action. A unique value will be added to "ActionID" field automatically (needed to match incoming responses).

##### request()

[](#request)

The `request(Action $action): PromiseInterface` method can be used to queue the given messages to be sent via AMI and wait for a [`Response`](#response) object that matches the value of its "ActionID" field.

### ActionSender

[](#actionsender)

The `ActionSender` wraps a given [`Client`](#client) instance to provide a simple way to execute common actions. This class represents the main interface to execute actions and wait for the corresponding responses.

```
$sender = new ActionSender($client);
```

#### Actions

[](#actions)

All public methods resemble their respective AMI actions.

```
$sender->ping()->then(function (Response $response) {
    // response received for ping action
});
```

Listing all available actions is out of scope here, please refer to the [class outline](src/ActionSender.php).

#### Processing

[](#processing)

Sending actions is async (non-blocking), so you can actually send multiple action requests in parallel. The AMI will respond to each action with a [`Response`](#response) object. The order is not guaranteed. Sending actions uses a [Promise](https://github.com/reactphp/promise)-based interface that makes it easy to react to when an action is *fulfilled*(i.e. either successfully resolved or rejected with an error):

```
$sender->ping()->then(
    function (Response $response) {
        // response received for ping action
    },
    function (Exception $e) {
        // an error occured while executing the action

        if ($e instanceof ErrorException) {
            // we received a valid error response (such as authorization error)
            $response = $e->getResponse();
        } else {
            // we did not receive a valid response (likely a transport issue)
        }
    }
});
```

#### Custom actions

[](#custom-actions)

Using the `ActionSender` is not strictly necessary, but is the recommended way to execute common actions.

If you happen to need a new or otherwise unsupported action, or additional arguments, you can also do so manually. See the advanced [`Client`](#client) usage above for details. A PR that updates the `ActionSender` is very much appreciated :)

### Message

[](#message)

The `Message` is an abstract base class for the [`Response`](#response), [`Action`](#action) and [`Event`](#event) value objects. It provides a common interface for these three message types.

Each `Message` consists of any number of fields with each having a name and one or multiple values. Field names are matched case-insensitive. The interpretation of values is application specific.

#### getFieldValue()

[](#getfieldvalue)

The `getFieldValue(string $key): ?string` method can be used to get the first value for the given field key. If no value was found, `null` is returned.

#### getFieldValues()

[](#getfieldvalues)

The `getFieldValues(string $key): string[]` method can be used to get a list of all values for the given field key. If no value was found, an empty `array()` is returned.

#### getFields()

[](#getfields)

The `getFields(): array` method can be used to get an array of all fields.

#### getActionId()

[](#getactionid)

The `getActionId(): string` method can be used to get the unique action ID of this message. This is a shortcut to get the value of the "ActionID" field.

#### Response

[](#response)

The `Response` value object represents the incoming response received from the AMI. It shares all properties of the [`Message`](#message) parent class.

##### getCommandOutput()

[](#getcommandoutput)

The `getCommandOutput(): ?string` method can be used to get the resulting output of a "command" [`Action`](#action). This value is only available if this is actually a response to a "command" action, otherwise it defaults to `null`.

```
$sender->command('help')->then(function (Response $response) {
    echo $response->getCommandOutput();
});
```

#### Action

[](#action)

The `Action` value object represents an outgoing action message to be sent to the AMI. It shares all properties of the [`Message`](#message) parent class.

#### Event

[](#event)

The `Event` value object represents the incoming event received from the AMI. It shares all properties of the [`Message`](#message) parent class.

##### getName()

[](#getname)

The `getName(): ?string` method can be used to get the name of the event. This is a shortcut to get the value of the "Event" field.

Install
-------

[](#install)

The recommended way to install this library is [through Composer](http://getcomposer.org). [New to Composer?](http://getcomposer.org/doc/00-intro.md)

This will install the latest supported version:

```
$ composer require clue/ami-react:^0.3
```

See also the [CHANGELOG](CHANGELOG.md) for details about version upgrades.

Tests
-----

[](#tests)

In order to run the tests, you need PHPUnit:

```
$ phpunit
```

The test suite contains both unit tests and functional integration tests. The functional tests require access to a running Asterisk server instance and will be skipped by default. If you want to also run the functional tests, you need to supply *your* AMI login details in an environment variable like this:

```
$ LOGIN=username:password@localhost phpunit
```

License
-------

[](#license)

MIT

###  Health Score

24

—

LowBetter than 32% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity6

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 98.7% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~278 days

Total

4

Last Release

3482d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/ac71c65d6b053239764bc36a5578232e89e3106f49435628cef5114ad29521a7?d=identicon)[anders2014](/maintainers/anders2014)

---

Top Contributors

[![clue](https://avatars.githubusercontent.com/u/776829?v=4)](https://github.com/clue "clue (74 commits)")[![bonan](https://avatars.githubusercontent.com/u/1701850?v=4)](https://github.com/bonan "bonan (1 commits)")

---

Tags

asyncreactamiAsterisk Manager Interface

### Embed Badge

![Health badge](/badges/anders-ami-react/health.svg)

```
[![Health](https://phpackages.com/badges/anders-ami-react/health.svg)](https://phpackages.com/packages/anders-ami-react)
```

###  Alternatives

[react/socket

Async, streaming plaintext TCP/IP and secure TLS socket server and client connections for ReactPHP

1.3k116.9M402](/packages/react-socket)[league/geotools

Geo-related tools PHP 7.3+ library

1.4k5.3M26](/packages/league-geotools)[react/dns

Async DNS resolver for ReactPHP

535114.1M100](/packages/react-dns)[clue/ami-react

Streaming, event-driven access to the Asterisk Manager Interface (AMI), built on top of ReactPHP.

85110.1k10](/packages/clue-ami-react)[react/promise-timer

A trivial implementation of timeouts for Promises, built on top of ReactPHP.

34141.9M96](/packages/react-promise-timer)[react/async

Async utilities and fibers for ReactPHP

2238.8M171](/packages/react-async)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
