videlalvaro/php-amqplib — pull request #19 by cthos (2012-05-08 01:30:26+00:00)
Title: Change $channel_id in the AMQPChannel class to be passed by reference

## The Problem

I was trying to do queue_declare on a passive connection to see if it existed. This results in the channel being closed (which is expected), but when the channel closes itself it leaves a reference open in the AMQPConnection class, because of the following:

```php

public function channel($channel_id = null)
{
if (isset($this->channels[$channel_id])) {
return $this->channels[$channel_id];
} else {
$ch = new AMQPChannel($this->connection, $channel_id);
$this->channels[$channel_id] = $ch;
return $ch;
}
}

```

If you pass nothing for $channel_id, it winds up going through the AMQPChannel constructor which does:

```php
if ($channel_id == null) {
$channel_id = $connection->get_free_channel_id();
}

parent::__construct($connection, $channel_id);

// The Parent constructor does this:
$connection->channels[$channel_id] = $this;
```

So, what winds up happening is $this->connection->channels has 2 references to the same channel, one with a numeric key, and one with the key of ''. When do_close is called, it removes the reference to the numeric key, but leaves the empty string key. The next time you call ->channel() it will give you back that bad reference with key '', which causes _method on a non object_ errors down the road.

## Solution

I changed the $channel_id to be passed by reference, so when it gets set in the channel constructor, it gets set appropriately.

Alternatively, since those are getting set in multiple places you could just remove the other $this->channels[$channel_id] = $ch; call in the AMQPConnection class. I didn't want to do that though because I wasn't terribly sure where else it was being used in the flow.