1
votes

I am extending the member class with DataExtension and I wish to add a Link() method. I have 2 pages, MembersPage.php and MemberExtension.php. I am trying to create a structure of www.mysite.com/members/show/1 so that I am able to view other members profiles. At the moment if I got to the url I put above, it works. I can see my member details, however if I go to www.mysite.com/members the error crashes and I get the following error:

Call to undefined method MemberExtension::MembersPage() in ../mysite/code/Secure/Extensions/MemberExtension.php on line 8

Line 8 is referring to:

return $this->MembersPage()->Link('show/'.$this->ID);

From everything I have read in SS3 is that DataExtension will actually merge methods together on compile time and give the illusion as if this was one class and not a child of the class. This being true, I do not understand how it cannot find MembersPage() method. Is it because my MembersPage is inside mysite folder and not in the framework folders? Is there a config setting I have to add to make this work?

Here is the code:

MembersPage.php

class MembersPage extends Page {
    private static $has_many = array (
        'Members' => 'Member',
    );
    public function getCMSFields() {
        $fields = parent::getCMSFields();
        $fields->addFieldToTab('Root.Members', GridField::create(
            'Members',
            'Members on this page',
            $this->Members(),
            GridFieldConfig_RecordEditor::create()
        ));
        return $fields;
    }
}
class MembersPage_Controller extends Page_Controller {
    private static $allowed_actions = array (
        'show'
    );

    public function show(SS_HTTPRequest $request) {
        $member = Member::get()->byID($request->param('ID'));

        if(!$member) {
            return $this->httpError(404,'That member could not be found');
        }

        return array (
            'Member' => $member
        );
    }
}

MemberExtension.php

<?php
class MemberExtension extends DataExtension {
    private static $has_one = array (
        'MembersPage' => 'MembersPage'
    );

    public function Link() {
        return $this->MembersPage()->Link('show/'.$this->ID);
    }
}

EDIT:

I tried experimenting, if I move Link method to Member class that is inside framework/security folder then everything works fine for me. Question now is, how do I get this method to work from MemberExtension class?

EDIT2:

It Works!
<% loop $Members %>
    <div>
        <a href="$Link">Visit Member</a>
        <h3>
            <a href="$Link">$FirstName</a>
        </h3>
    </div>
<% end_loop %>
1
What template are you using? Seems it tries to get an non existant member, therefor the Link() method won't work, cause MembersPage() is empty... - wmk
MembersPage is not empty - Bagzli
template has the same name - Bagzli
Can you paste the relevant part of the template? - wmk
@wmk I have added the template under edit2 - Bagzli

1 Answers

6
votes

Found it... The error is also very descriptive... and common when moving some code from a class to its decorator...

Call to undefined method MemberExtension::MembersPage()

So what does this mean? In class MemberExtension there is no method called MembersPage(). Which is true. It's an automagic method in Member class to get the MembersPage has_one relation. So how can we call something in Member from MembersExtension, which is plugged into Member as a decorater? Simply use $this->owner instead of $this!

So this should work:

<?php
class MemberExtension extends DataExtension {
    private static $has_one = array (
        'MembersPage' => 'MembersPage'
    );

    public function Link() {
        //check if MembersPage has_one relation is set
        return $this->owner->MembersPageID ? 
            $this->owner->MembersPage()->Link('show/'.$this->owner->ID)
            : '';
    }
}