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

Raymond Kolbe rkolbe at gmail.com
Thu Nov 15 16:29:58 CST 2007


It works! Thank you so much!.....again.

Raymond K.

On Nov 15, 2007 4:55 PM, Raymond Kolbe <rkolbe at gmail.com> wrote:

> 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/aca03cf1/attachment-0001.html


More information about the Solar-talk mailing list