[Solar-talk] Using 'through' - a relationship headache

Raymond Kolbe rkolbe at gmail.com
Thu Nov 15 15:55:17 CST 2007


Rodrigo...you are the man!

I haven't tested the code yet (once I am done typing this email I will) but
from your explanation above I was on the right track for the most
part....it's always the small things that get me.

Off to implement/play with this now.

Thanks a ton. I'll let you know how it turns out ;-)

--Raymond K.

On Nov 15, 2007 1:27 PM, Rodrigo Moraes <rodrigo.moraes at gmail.com> wrote:

> On Nov 15, 2007 1:08 PM, Raymond Kolbe wrote:
> > I have tried many different methods to accomplish this, many which make
> > people go 'eh?'. What am I missing with this setup? I made sure 1,000
> times
> > that the data does exist in the tables.
> >
> > Any help is much appreciated.
>
> Hey. You need to setup a has-many-through relationship. It is not the
> most basic one, but once you've set up one, you have the recipe to try
> others. So take a breath and let's start. :)
>
> Here are some notes:
>
> 1. I renamed the primary keys to simply 'id', as it is the default.
> You can move back to the original names, but set the property
> $_primary_col in the models to tell Solar the name of the primary key.
>
> 2. Add a primary key to the intermediate table ('connectiontracker').
> It is necessary for the magic. As a general rule, always set a primary
> key in your tables. This will make the model happy.
>
> 3. Ok, now the trick. When you have an intermediate table mapping the
> record to another, you need to define *two* relationships: one for the
> intermediate table record, and other for the target record. In
> restaurants you'd set:
>
>        $this->_hasMany('connection_tracker', array(
>            'foreign_class' => 'Vendor_Model_ConnectionTracker',
>            'foreign_col'   => 'restaurant_id',
>        ));
>
>        $this->_hasMany('pingcode', array(
>            'foreign_class'       => 'Vendor_Model_PingCodes',
>            'foreign_col'         => 'id',
>            'through'             => 'connection_tracker',
>            'through_foreign_col' => 'pingcode_id',
>            'fetch'               => 'one',
>        ));
>
> See that the second _hasMany():
>
> a) uses the first relationship, 'connection_tracker', as a bridge for
> the target record, defining how to fetch it ("load it through the
> foreign column 'pingcode_id' using the relationship
> 'connection_tracker'").
>
> b) returns the result as it was a fetchOne(), because 'fetch' is set
> to 'one'. it seems that in your case you don't need a collection, but
> only one record, but if you need a collection, remove the 'fetch' key
> from the relationship. so, i think we can call this a
> "has-one-through" relationship, versus the common "has-many-through".
>
> Now, pingcode only needs to have the *opposite* of the restaurants
> relationship:
>
>        $this->_hasMany('connection_tracker', array(
>            'foreign_class' => 'Vendor_Model_ConnectionTracker',
>            'foreign_col'   => 'pingcode_id',
>        ));
>
>        $this->_hasMany('restaurant', array(
>            'foreign_class'       => 'Vendor_Model_Restaurants',
>            'foreign_col'         => 'id',
>            'through'             => 'connection_tracker',
>            'through_foreign_col' => 'restaurant_id',
>            'fetch'               => 'one',
>        ));
>
> ... and the intermediate model, ConnectionTracker, has just plain
> belongTo's:
>
>    $this->_belongsTo('restaurant', array(
>        'foreign_class' => 'Vendor_Model_Restaurants',
>        'native_col'    => 'restaurant_id',
>        'foreign_col'   => 'id',
>    ));
>
>    $this->_belongsTo('pingcode', array(
>        'foreign_class' => 'Vendor_Model_PingCodes',
>        'native_col'    => 'pingcode_id',
>        'foreign_col'   => 'id',
>    ));
>
> Now, if there are appropriate records in the tables, you can do:
>
>    $model = Solar::factory('Vendor_Model_Restaurants');
>    $restaurant = $model->fetch(1);
>
>    echo $restaurant->pingcode->name;
>
> ...and:
>
>    $model = Solar::factory('Vendor_Model_PingCodes');
>    $pingcode = $model->fetch(1);
>
>    echo $pingcode->restaurant->name;
>
> Done.  I tested it, and it worked. :)
>
> The tested classes are here: http://pastebin.com/m613a3606
>
> let me know if you have problems.
>
> -- rodrigo
>
> ps: we need a wiki page with some model recipes - a dozen common table
> schemes (like the above) and how to setup their relationships.
> _______________________________________________
> Solar-talk mailing list
> Solar-talk at lists.solarphp.com
> http://mailman-mail3.webfaction.com/listinfo/solar-talk
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mailman-mail3.webfaction.com/pipermail/solar-talk/attachments/20071115/040e14e4/attachment.html


More information about the Solar-talk mailing list