Php-amqplib: Declare exchange with arguments not possible

Created on 28 May 2016  路  6Comments  路  Source: php-amqplib/php-amqplib

<?php

require __DIR__ . '/vendor/autoload.php';

$connection = new \PhpAmqpLib\Connection\AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();

$channel->exchange_declare('test_exchange', 'direct', false, false, true, false, false, ['foo' => 'bar']);

leeds to:

Fatal error: Uncaught PhpAmqpLib\Exception\AMQPOutOfRangeException: AMQP-rabbit doesn't define data of type [] in /home/sasa/code/amqp-tests/vendor/php-amqplib/php-amqplib/PhpAmqpLib/Wire/AMQPAbstractCollection.php on line 414

PhpAmqpLib\Exception\AMQPOutOfRangeException: AMQP-rabbit doesn't define data of type [] in /home/sasa/code/amqp-tests/vendor/php-amqplib/php-amqplib/PhpAmqpLib/Wire/AMQPAbstractCollection.php on line 414

Call Stack:
    0.0001     362272   1. {main}() /home/sasa/code/amqp-tests/php_amqplib_declare.php:0
    0.0528    1588384   2. PhpAmqpLib\Channel\AMQPChannel->exchange_declare() /home/sasa/code/amqp-tests/php_amqplib_declare.php:8
    0.0528    1588384   3. PhpAmqpLib\Helper\Protocol\Protocol091->exchangeDeclare() /home/sasa/code/amqp-tests/vendor/php-amqplib/php-amqplib/PhpAmqpLib/Channel/AMQPChannel.php:349
    0.0528    1588624   4. PhpAmqpLib\Wire\AMQPWriter->write_table() /home/sasa/code/amqp-tests/vendor/php-amqplib/php-amqplib/PhpAmqpLib/Helper/Protocol/Protocol091.php:287
    0.0528    1588840   5. PhpAmqpLib\Wire\AMQPAbstractCollection::getDataTypeForSymbol() /home/sasa/code/amqp-tests/vendor/php-amqplib/php-amqplib/PhpAmqpLib/Wire/AMQPWriter.php:425

Most helpful comment

Just ran into the same issue and found the solution so I thought I'd leave a note for anybody else who finds this issue on Google:

The documentation and code hints are confusing on this, but instead of passing an array, you should pass an AMQPTable object:

new AMQPTable(['foo' => 'bar'])

So instead of this:

$channel->exchange_declare('test_exchange', 'direct', false, false, true, false, false, ['foo' => 'bar']);

do this:

$channel->exchange_declare('test_exchange', 'direct', false, false, true, false, false, new AMQPTable(['foo' => 'bar']));

All 6 comments

Same problem is with exchange to exchange binding with arguments.

What does work is when I do something like this upfront:

        $arguments = [];
        foreach ($this->arguments as $k => $v) {
            if (is_array($v)) {
                $arguments[$k] = ['A', $v];
            } elseif (is_int($v)) {
                $arguments[$k] = ['I', $v];
            } elseif (is_bool($v)) {
                $arguments[$k] = ['t', $v];
            } elseif (is_string($v)) {
                $arguments[$k] = ['S', $v];
            } else {
                throw new Exception\InvalidArgumentException('Unknown argument type ' . gettype($v));
            }
        }

and then using $arguments instead of $this->arguments

This is expected. Here are the supported Rabbit AMQP types so your hardcoding is not generic enough to support this.

Just ran into the same issue and found the solution so I thought I'd leave a note for anybody else who finds this issue on Google:

The documentation and code hints are confusing on this, but instead of passing an array, you should pass an AMQPTable object:

new AMQPTable(['foo' => 'bar'])

So instead of this:

$channel->exchange_declare('test_exchange', 'direct', false, false, true, false, false, ['foo' => 'bar']);

do this:

$channel->exchange_declare('test_exchange', 'direct', false, false, true, false, false, new AMQPTable(['foo' => 'bar']));

For those who cannot directly change $channel->exchange_declare() call, like, people who use RabbitMQ Symfony bundle, you can solve it like that:

Instead of providing

['foo' => 'bar']

as argument, provide

['foo' => [ARGUMENT_TYPE, 'bar']]

Where ARGUMENT_TYPE is one of \PhpAmqpLib\Wire\AMQPAbstractCollection type constants.

List or available argument types:

private static $_types_091 = array(
        self::T_INT_SHORTSHORT => 'b',
        self::T_INT_SHORTSHORT_U => 'B',
        self::T_INT_SHORT => 'U',
        self::T_INT_SHORT_U => 'u',
        self::T_INT_LONG => 'I',
        self::T_INT_LONG_U => 'i',
        self::T_INT_LONGLONG => 'L',
        self::T_INT_LONGLONG_U => 'l',
        self::T_DECIMAL => 'D',
        self::T_TIMESTAMP => 'T',
        self::T_VOID => 'V',
        self::T_BOOL => 't',
        self::T_STRING_SHORT => 's',
        self::T_STRING_LONG => 'S',
        self::T_ARRAY => 'A',
        self::T_TABLE => 'F'
);

and

private static $_types_080 = array(
        self::T_INT_LONG => 'I',
        self::T_DECIMAL => 'D',
        self::T_TIMESTAMP => 'T',
        self::T_STRING_LONG => 'S',
        self::T_TABLE => 'F'
);

for 0-9-1 and 0-8 accordingly.

Following up on @ArchieDoe, this would look like this:

'exclusive' => [AMQPAbstractCollection::getSupportedDataTypes()[AMQPAbstractCollection::T_BOOL], true],
Was this page helpful?
0 / 5 - 0 ratings