Jump to:

3430 Posts in 1057 Topics by 734 members

Data Model Questions

SilverStripe Forums » Data Model Questions » [WORKAROUND] Two different many_many and belongs_many_many relationships on the same two tables

Moderators: martimiz, Sean, biapar, Willr, Ingo, swaiba, simon_w

Page: 1 2
Go to End
Author Topic: 1284 Views
  • NathanBrauer
    Avatar
    Community Member
    11 Posts

    [WORKAROUND] Two different many_many and belongs_many_many relationships on the same two tables Link to this post

    Hello SS World

    I was stumped on this for a while but I figured it out so I figured I'd share my results.
    Update: Nevermind, it doesn't seem to be working. After reading this message, continue to the responses!
    Update #2: I found a workaround to get this to work. Make sure you read the whole thread. The workaround is the 7th post.

    I was trying to build two classes: Person, Company
    A Person can be an Employee of a Company.
    A Person can Represent a Company, but not necessarily be an employee of that company.

    Both of these relationships would be represented by this table structure (one for each) if it was outside of Silverstripe:

    | ID | PersonID | CompanyID |

    Now I just needed to get SS to recognize which is which.

    // In Person.php
    static $belongs_many_many = array(
       'Represents'   => 'Company',
       'Employers'   => 'Company',
    );

    // In Company.php
    static $many_many = array(
       'Representatives'=> 'Person',
       'Employees'    => 'Person',
    );

    As you can see, now Silverstripe won't know which is which. If I call $Person->Employers(), it won't know whether to look in Company_Representatives or Company_Employees for the right data.

    The solution is to use dot notation on the class with <b>belongs_many_many</b> (and <u>NOT</u> the other) where the added parameter would be the reference key from many_many.

    // In Person.php
    static $belongs_many_many = array(
       'Represents'   => 'Company.Representatives',
       'Employers'   => 'Company.Employees',
    );

    // In Company.php
    static $many_many = array(
       'Representatives'=> 'Person',
       'Employees'    => 'Person',
    );

    P.S. This should be added to the docs. A dual has_one/has_many relationship is described there but it's not very clear and it doesn't state how to do it with many_many.

  • swaiba
    Avatar
    Forum Moderator
    1784 Posts

    Re: [WORKAROUND] Two different many_many and belongs_many_many relationships on the same two tables Link to this post

    wow - thank you so much for the post, I've hacked my way around this a couple of times - but now I have the elegant solution!

  • danzzz
    Avatar
    Community Member
    175 Posts

    Re: [WORKAROUND] Two different many_many and belongs_many_many relationships on the same two tables Link to this post

    hi nathan,

    I tried this, but get an error ...

    I have a DataObject "Shop", where I save webshops. Each webshop can be in many countries and can deliver to many countries.

    here my code:

    Country.php

    class Country extends DataObject {
    static $many_many = array(
    'Shops' => 'Shop',
       'DeliveryCountries' => 'Shop'
    );
    }

    Shop.php

    class Shop extends DataObject {
    static $belongs_many_many = array(
       'Shops' => 'Shop.Shops',
       'DeliveryCountries' => 'Shop.DeliveryCountries',
    );
    }

    SS build the tables with success, I have this tables now:

    Country
    Country_Shops
    Country_DeliveryContries

    But there is this error:

    Error: "Bad class to singleton() - Country.Shops" at line 346 of /var/www/xxx.com/sapphire/core/Core.php

    whats wrong here?

    thx

  • NathanBrauer
    Avatar
    Community Member
    11 Posts

    Re: [WORKAROUND] Two different many_many and belongs_many_many relationships on the same two tables Link to this post

    Hi @danzzz,

    I actually ran into some problems while testing this too. Here's how I fixed it:

    // In Person.php
    static $belongs_many_many = array(
    'Represents' => 'Company',
    'Employers' => 'Company.Employees',
    );

    // In Company.php
    static $many_many = array(
    'Representatives'=> 'Person',
    'Employees' => 'Person',
    );

    What changed?
    In the first $belongs_many_many attribute, I used only the class/table name and did not include the identifier.

    Danzzz, try that. It does sound like your problem may be different though. If that doesn't work you may not be able to do it with a Singleton class.

  • NathanBrauer
    Avatar
    Community Member
    11 Posts

    Re: [WORKAROUND] Two different many_many and belongs_many_many relationships on the same two tables Link to this post

    Ok, I take it back.
    Everything was working until I tried to access Person->Employers (error I got was: Unknown class passed as parameter -- see trace below)

    swaiba, were you able to get this working?

    is_subclass_of(MVEntity.Employees,DataObject)
    Line 568 of Object.php
    Object::prepare_statics(MVEntity.Employees)
    Line 381 of Object.php
    Object::uninherited_static(MVEntity.Employees,many_many)
    Line 1745 of DataObject.php
    DataObject->many_many(ReportsTo)
    Line 1374 of DataObject.php
    DataObject->getManyManyComponents(ReportsTo)
    call_user_func_array(Array,Array)
    Line 711 of Object.php
    Object->__call(ReportsTo,Array)
    Line 86 of Page.php
    Person->Employers()
    Line 86 of Page.php

  • swaiba
    Avatar
    Forum Moderator
    1784 Posts

    Re: [WORKAROUND] Two different many_many and belongs_many_many relationships on the same two tables Link to this post

    as much as I liked it - I haven't tried it.

    I want it to work and yet I've had a work around for a while and it's just not elegant (use Text in db array, use it to store an id csv list, edit with a custom checkboxfieldset).

  • NathanBrauer
    Avatar
    Community Member
    11 Posts

    Re: [WORKAROUND] Two different many_many and belongs_many_many relationships on the same two tables Link to this post

    Alright, I couldn't figure out how to fix it, but I found out a hack that gets almost the exact same results

    This is what should work but doesn't:

    // In Person.php
    static $belongs_many_many = array(
    'Represents' => 'Company.Representatives',
    'Employers' => 'Company.Employees',
    );

    // In Company.php
    static $many_many = array(
    'Representatives'=> 'Person',
    'Employees' => 'Person',
    );

    This is an almost seemless workaround that DOES work:

    // In Person.php
    static $belongs_many_many = array(
    'Represents' => 'Company'
    );
    static $many_many = array(
    'Employers'=> 'Company'
    );

    // In Company.php
    static $many_many = array(
    'Representatives'=> 'Person'
    );
    static $belongs_many_many = array(
    'Employees' => 'Person'
    );

    This basically has the results we want (Company->Representatives(), Company->Employees(), Person->Represents(), and Person->Employers() all work properly) but instead of having the tables Company_Representatives and Company_Employees, we have Company_Representatives and Person_Employers. Except for that difference, everything else should work exactly the same.

  • NathanBrauer
    Avatar
    Community Member
    11 Posts
    1284 Views
Page: 1 2
Go to Top

Want to know more about the company that brought you SilverStripe? Then check out SilverStripe.com

Comments on this website? Please give feedback.