Search code examples
phpmysqlhas-manysilverstripehas-one

Silverstripe accessing has_many data from a separate page type


I'd like to start by saying that I'm new to Silver Stripe development and PHP/MySQL in general, so please be kind.

I have a site that requires me to have a pricing page that displays the company's pricing plans on both the pricing page (duh) and the homepage. So, the goal is to be able to access the data from my Pricing.php page type with my HomePage.ss.

I'm trying to make this as future proof as possible so I've created a ServicePlan.php that extends DataObject and uses a FieldList to create the pricing records and associate them with the Pricing page type via a $has_many and $has_one relationship. Based on my limited knowledge this seems like the best way to accomplish this.

Here's the code that I've written to accomplish this.

ServicePlan.php

class ServicePlan extends DataObject {

private static $db = array (
    'PlanColor' => 'Varchar',
    'PlanName' => 'Varchar',
    'PlanPrice' => 'Varchar',
    'PlanRenewal' => 'Varchar',
);

private static $has_one = array (
    'Pricing' => 'Pricing'
);
private static $summary_fields = array (
    'PlanName' => 'Name of Plan',
    'PlanPrice' => 'Price',
    'PlanRenewal' => 'Renewal Period',
);
public function getCMSFields() {
    $fields = FieldList::create(
        TextField::create('PlanName'),
        TextField::create('PlanRenewal'),
        TextField::create('PlanPrice'),
        TextField::create('PlanColor')
    );
    return $fields;
}

public function getServicePlans() {
    return $this->Pricing();
}

Pricing.php

class Pricing extends Page {
private static $has_many = array (
    'ServicePlans' => 'ServicePlan',
);

public function getCMSFields() {
    $fields = parent::getCMSFields();


    $fields->addFieldsToTab('Root.Plans', GridField::create(
        'ServicePlans',
        'Orenda Force Service Plan Information',
        $this->ServicePlans(),
        GridFieldConfig_RecordEditor::create()
    ));

    return $fields;
    }
}

class Pricing_Controller extends Page_Controller {

}

HomePage.php

class HomePage extends Page {
}

class HomePage_Controller extends Page_Controller {
    public function ServiceTeasers($count = 2) {
        $holder = ServicesHolder::get()->First();
        return ($holder) ? ServicesPage::get()->limit($count) : false;
    }

    public function MembershipPlans() {
        $Pricing = Pricing::get();
        return $plan;
    }
}

Layout/HomePage.ss

...//

<% loop $MembershipPlans %>
    <div class="col-1-3 card pricing">
        <div class="pricing__header  primary $PlanColor">
            <p class="pricing__plan-name">$PlanName</p>
            <p class="pricing__price">$PlanPrice<sub>$PlanRenewal</sub></p>
        </div>
        <div class="card__contents">
            <h3 class="title-06">Plan details</h3>
            <ul>
                <li>unlimited training</li>
                <li>individual nutrition/meal plans</li>
            </ul>
        </div>
    </div>
    $Content
<% end_loop %>

...//

I'm having no issues accessing the content

Layout/Pricing.ss

<section class="body pricing">
    <div class="content">
    <h2 class="title-02 text-monochrome">Pricing</h2>
        <% loop $ServicePlans %>
            <div class="col-1-3 card pricing">
                <div class="pricing__header $PlanColor">
                    <p class="pricing__plan-name">$PlanName</p>
                    <p class="pricing__price">$PlanPrice<sub>$PlanRenewal</sub></p>
                </div>
                <div class="card__contents">
                    <h3 class="title-06">Plan details</h3>
                    <ul>
                        <li>unlimited training</li>
                        <li>individual nutrition/meal plans</li>
                    </ul>
                </div>
            </div>
        <% end_loop %>
    </div>
</section>

I really appreciate any help that you all can provide, I've been trying to figure this out for a couple days and I've been hitting a brick wall time and time again. What am I doing wrong?

This question is the closest I've gotten and it didn't seem to solve my issue. Should I move the FieldList to the Pricing.php page?


Solution

  • It seems that for your home page you have most of what you need already. You're just missing the loop for the has_many that the Price page has. Since your MembershipPlans() function in the HomePage_Controller returns all of the price pages as a DataList you can access the related objects by looping through the relation name, in this case <% loop $ServicePlans %>.

    HomePage.ss

    <% loop $MembershipPlans %><!-- loop Price pages -->
    <% loop $ServicePlans %><!-- this is your loop for the ServicePlans related to the particular Price page -->
    <div class="col-1-3 card pricing">
        <div class="pricing__header  primary $PlanColor">
            <p class="pricing__plan-name">$PlanName</p>
            <p class="pricing__price">$PlanPrice<sub>$PlanRenewal</sub></p>
        </div>
        <div class="card__contents">
            <h3 class="title-06">Plan details</h3>
            <ul>
                <li>unlimited training</li>
                <li>individual nutrition/meal plans</li>
            </ul>
        </div>
    </div>
    <% end_loop %><!-- end ServicePlans relation loop -->
    $Content<!-- Content for particular Price page -->
    <% end_loop %><!-- end Price pages loop -->