unclecheese / SilverSmith

The SilverSmith toolset for SilverStripe framework 3.0
34 stars 14 forks source link

Multiple ManyMany Relations between two Objects #6

Open jrast opened 12 years ago

jrast commented 12 years ago

I have this code in my _project.yml file:

Components:
  Tour:
    Fields: []
    Components:
      Mitglied:
        Type: manymany
        Name: Teilnehmer
        Interface:
          Type: grid
      Mitglied:
        Type: manymany
        Name: Leiter
        Interface:
          Type: grid
  Mitglied:
    Parent: Member
    Fields: []
    Components:
      Tour:
        Type: manymany
        Name: TeilgenommeneTouren
      Tour:
        Type: manymany
        Name: GeleiteteTouren

And this is the generated Code (only the important part): Tour.php:

    static $many_many = array (
        'Leiter' => 'Mitglied',
    );

    static $belongs_many_many = array (
        'Mitglieds' => 'Mitglied',
    );

Mitglied.php:

    static $many_many = array (
        'GeleiteteTouren' => 'Tour',
    );

    static $belongs_many_many = array (
        'Tours' => 'Tour',
    );

As you can see, the $belongs_many_many part has not the name specified in the _project.yml File.

If I find some time next week, I'll have a look at this. I just opend this issue that we don't forget about it.

unclecheese commented 12 years ago

Good question! SilverSmith has limited handling of $belongs_many_many at this point. The name is automatically assigned as the plural form of the related class.

The rationale behind this is that creating relationships should be as fast and as easy as possible, and creating the $belongs_many_many side to a $many_many always feels like an extra step to me -- like creating a $has_one against a $has_many.

Right now SilverSmith automatically handles the reciprocal of the relationship, but I would like to be able to offer the option to customize it. Maybe something like:

Components:
  Something:
    Type: manymany
    Name: Somethings 
    InverseName: OtherThings  #belongs_many_many

A second issue with your YAML is that you define multiple keys having the same name, which will override the previous entries, effectively leaving you with just the last node defined with that name.

You've exposed a shortcoming of the YAML spec -- and that is, creating multiple relations to the same class is not possible because everything is namespaced to the classname, not the relation name.

Why the classname, and not something like this?

Components:
  People:
    Type: many
    Class: Person
    #etc..

Again, it goes back to the wanting to require as little input from the user as possible. SilverSmith can automatically NAME the relationship, but the class name is always required.

Clearly, you can see the tradeoff for that level of simplicity. It precludes you from making multiple realtionships to the same class. I personally have never needed to do that, but I can see in your example that you need to.

I'd like to change the spec to namespace to the name of the relationship, not the class, but that's a major API overhaul, and backward compatibility would be a huge issue.

What do you think?

jrast commented 12 years ago

So this is actually a lot bigger issue than I expected. I thougt at first that there is just a problem about getting the right name (missing $object->getName()) or so.

For me, this would be a nice to have and not a must. I mean, these two relations are the only two I have in a more or less complex datastructure.

jrast commented 12 years ago

Maybe another consideration about the structure I posted in the first post: I could add $many_many_ExtraFields, this would solve my problem. Because this way i could simplify my project file to this:

Components:
  Tour:
    Fields: []
  Mitglied:
    Parent: Member
    Fields: []
    Components:
      Tour:
        Type: manymany
        Name: Touren      

And in the $many_many_ExtraFields i add the needed conditions.

So maybe it's better to not easily allow the user to create multiple components of the same class because it's anyway a hint for bad design of the data structure?

So, the only thing wich is missing in SilverSmith is the ReverseName. And a option to add the many_many_ExtraFields directly in the YAML. But how to achieve this?

How about something like this:

Tour:
  Type: manymany
  ExtraFields:
    IsLeiter: Boolean # FieldName : DBField-Type

But what happens if someone adds ExtraFields to a one- or many-Relation?