Relying on BELONGS_TO relations after querying 'with-through' turned out to be a bad idea. These properties aren't cached during the query, so every access means additional query for every row in the relations table which is unacceptable.

My solution was to add 'index' property to the first relation of the first table, set to the field which is a foreign key of the second table, so that rows queried from the relations table are indexed by IDs of the second table (as rows from the relations table and second table are one-to-one in this query). This way, after the request, I can iterate through rows of the second table and get corresponding rows from the relations table.

The extension does this (with slightly different relation specs) but I think something like the above should be part of the framework. There's nothing exotic about data that logically belongs to a relation between objects rather than to the objects. In SQL RDBMS they are conventionally put in a join table. It should be easy to access the data.

It works for part of the problem. When filling a zii.CGridView display of viewers you might want all viewers, not just those that appear in the join table.

But at least it doesn't use the undocumented feature that two independently-gotten arrays of AR objects are index aligned. Creocoder's suggestion is especially worrying since he hinted this stuff may be changing in 1.1.9.