Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

General Questions /

General questions about getting started with SilverStripe that don't fit in any of the categories above.

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

has_many in DataExtension


Go to End


4 Posts   1087 Views

Avatar
Chazz

Community Member, 7 Posts

7 June 2015 at 5:45am

Hello,

I have a DataExtension with a has_many

class ProductDetailExtension extends DataExtension { 


    private static $has_many = array(
        'FeatureDetails' => 'FeatureDetail'
    );

which I want to apply to different DataObjects and Pages

Product:
  extensions:
    - ProductDetailExtension
ServicePage:
  extensions:
    - ProductDetailExtension

Now I have to put the has_one in FeatureDetail which corresponds to the has_many in the ProductDetailExtension

class FeatureDetail extends DataObject {

    private static $db = array(
    );

    private static $has_one = array(
        'Feature' => 'Feature',
        'ProductService' => '<ProductDetailExtension>' 
    );

Am I right that there is really no simple built-in way to do this?

Thinking about it (and looking into the comments Addon) I see one complicated way:

Defining FeatureDetail in this way

class FeatureDetail extends DataObject {

    private static $db = array(
    );

    private static $has_one = array(
        'Feature' => 'Feature',
        'ParentID' => 'Int',
        'BaseClass' = 'VarChar'
    );

and writing custom methods to save and get FeatureDetails in the extension.
Is this really necessary in SilverStripe?

Avatar
Pyromanik

Community Member, 419 Posts

7 June 2015 at 7:32am

Interesting, I've never really considered this before.
Off hand; no, I don't believe there is an easy way.

You could create a parent class type, ThingsWeDoPage, and have the extension apply to that instead.
There are ways to hide it from the creation menu in the CMS so that Content Editors can only create Product or Service pages.

Or you can create extensions galore (or a single extension that covers all needs in your business domain) and apply that to FeatureDetail. That way you keep the Feature Detail code (presumably a module) and the business domain code (mysite) separated, but not needlessly abstracted into multiple little extensions to carry back and forth.

Avatar
Chazz

Community Member, 7 Posts

8 June 2015 at 2:06am

Thanks for the reply Pryomanik (and the replies to all my other questions)

A parent class seems complicated as the extension should by applied to DataObjects (Product) and/or Pages (ServicePage).

With the extensions galore I'm not sure where you're heading exactly ;)

One other way I tought about was introducing a extra layer with an extra table: FeatureDetailHolder

class FeatureDetailHolder extends DataObject {
    
    private static $has_many = array(
        'FeatureDetails' => 'FeatureDetail'
    );

and then putting a has_one on the extension

class ProductDetailExtension extends DataExtension { 


    private static $has_one = array(
        'FeatureDetailHolder' => 'FeatureDetailHolder'
    );

A third idea (from stackoverflow), which I now used, is to change the has_many to a many_many relation, omitting the reverse belongs_many_many relation, which I don't need anyway. And if needed to write custom relation getters.
That way tables ServicePage_FeatureDetails, Product_FeatureDetails ... are created and everything seems to work fine.

Avatar
Pyromanik

Community Member, 419 Posts

9 June 2015 at 9:27am

I meant that you'd need to write an extension for every page you related FeatureDetail to & apply it to FeatureDetail (ie, an extension to implement each has_one).
But realistically you could just do this with one extension with many has_one definitions in it. It's a little coupled, but that's probably fine since it's kinda the whole point - so long as it stays with the rest of your business domain code.