<?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
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],
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:
So instead of this:
do this: