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.

Data Model Questions /

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

How can I create a CheckboxSetField based off of the pages available in another section?


Go to End


5 Posts   2214 Views

Avatar
fatwreck

Community Member, 3 Posts

26 May 2016 at 5:54am

Im new at Silverstripe so please be gentle.

I would like to create a CheckboxSetField list under a tab in my Facilities page. The list would be made from the child pages available under my Services section.

I think I need to use the $many_many relationship explained in the tutorial (https://www.silverstripe.org/learn/lessons/working-with-data-relationships-many-many), but UncleCheese is generating his Categories CheckboxSetField list from a GridField.

I made a static list based off of (http://api.silverstripe.org/3.1/class-CheckboxSetField.html) that works, but the array needs to be pulled from the Service section child page list.

        $fields->addFieldsToTab('Root.ServicesAvailable', array (
            HeaderField::create('InfoHeader', 'Services Available'),
            new CheckboxSetField(
                $name = "services",
                $title = "Services offered by this facility:",
                $source = array(
                    "1" => "Technology",
                    "2" => "Gardening",
                    "3" => "Cooking",
                    "4" => "Sports"
                ),
                $value = "1"
            )
        ));

So far I have:

FacilityHolder.php

<?php

class FacilityHolder extends Page {

	private static $has_many = array (
		'Locations' => 'Location',
		'Services' => 'ServicePage',
	);

}

class FacilityHolder_Controller extends Page_Controller {

	private static $allowed_actions = array (
		'show'
	);

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

		if(!$location) {
			return $this->httpError(404, 'Could not be found.');
		}

		return array (
			'Location' => $location,
			'Title' => $location->Title
		);
	}

    public function GetLocation() {
        return Location::get();
    }    

    public function ServicesAvailable() {
        return Location::get()
        ->filter(array(
            'services' => true
        ));
    }    

}

ServicePage.php

<?php

class ServicePage extends Page {

    private static $db = array (
        'ServTeaser' => 'Text',
    );

    private static $has_one = array (
        'Icon' => 'Image',   
        'FacilityHolder' => 'FacilityHolder' 	
    );

    private static $belongs_many_many = array (
    	'Services' => 'ServicePage',
    );

    private static $can_be_root = false;
        
    public function getCMSFields() {
        $fields = parent::getCMSFields();
        
        $fields->addFieldToTab('Root.Main', TextareaField::create('ServTeaser', 'Short Teaser'), 'Content');
        $fields->addFieldToTab('Root.Main', $icon = UploadField::create('Icon', 'Icon'), 'Content');

        $icon->getValidator()->setAllowedExtensions(array('png','gif','jpg','jpeg','svg'));
        $icon->setFolderName('icons');

        return $fields;
    }
}

class ServicePage_Controller extends Page_Controller {
    
}

Location.php

       private static $has_one = array(
            'Category' => 'LocationCategory',
            'FactSheet' => 'File',
            'FacilityHolder' => 'FacilityHolder'
        );

        private static $many_many = array (
            'Services' => 'ServicePage',
        );

        // create and populate Services Available tab
        $fields->addFieldsToTab('Root.ServicesAvailable', array (
            HeaderField::create('InfoHeader', 'Services Available'),
            new CheckboxSetField(
                $name = "services",
                $title = "Services offered by this facility:",
                $source = array(
                    "1" => "Technology",
                    "2" => "Gardening",
                    "3" => "Cooking",
                    "4" => "Sports"
                ),
                $value = "1"
            )
        ));

Thanks for looking.

Avatar
martimiz

Forum Moderator, 1391 Posts

8 June 2016 at 11:47pm

It depends...
if all the childpages in your service section are of the type ServicePage, then you can just get all servicepages like this:

$source = ServicePage::get()->map('ID', 'Title');

If you want all childpages of a certain page with ID=12, then you can

$source = SiteTree::get()->filter(array('ParentID' => 12))->map('ID', 'Title');

Or probably even somewhat more complex :)

$source = SiteTree::get()->filter(array('Title' => 'My section'))->first()->Children()->map('ID', 'Title');

If the sections children have children themselves that you also want to include then it becomes more complex - I would avoid that :)

Avatar
fatwreck

Community Member, 3 Posts

18 June 2016 at 4:36am

Finally back to my SS project. Apologies for the late thank you martimiz! This is just what I needed.

I can now pull ServicePage.php pages into a CheckboxSetField list in the backend which is great. I can tick off what services are available for each facility. But a have the feeling I won't be able to pull the associated data along with it to the website. For example getting the ServicePage.php $Icon, $ServTeaser ect to output to my FacilityHolder_show.ss page. Currently the checked off boxes are outputting IDs.

The throughline for all of this is complicated.

I want data from the ServicePage.php page to output to my FacilityHolder_show.ss page. FacilityHolder_show.ss pages are auto-generated from my FacilityHolder.php page. The Facilities on that page are generated from my Locator.php file.

I think I need a crash course in pulling data from the database. I got a handle on the straight forward stuff but when things get complicated I get lost.

FacilityHolder.php

<?php

class FacilityHolder extends Page {

	private static $has_many = array (
		'Locations' => 'Location',
	);	

    private static $many_many = array(
        'Services' => 'ServicePage',
    );

}

class FacilityHolder_Controller extends Page_Controller {

	private static $allowed_actions = array (
		'show'
	);

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

		if(!$location) {
			return $this->httpError(404, 'Could not be found.');
		}

		return array (
			'Location' => $location,
			'Title' => $location->Title
		);
	}

    public function GetLocation() {
        return Location::get();
    }    

    public function ServicesAvailable() {
        // return ServicePage::get()->map('ID', 'Icon');
        return Location::get()

        ->filter(array(
            'services' => true
        ));
    }

    public function ServicesTest() {
        return ServicePage::get();
        if($this->services()->exists()) {
            return implode(', ', $this->services()->column('Title'));
        }
    }

}

Avatar
martimiz

Forum Moderator, 1391 Posts

26 June 2016 at 11:50pm

Edited: 26/06/2016 11:53pm

to summarize: your FacilityHolder now has a couple of Services attached to it, which are Service_page objects. And you want to display the data from these Services on your FacilityHolder?

In that case in the template of your Facility page (which would be called FacilityHolder.ss and live in YourTheme/templates/(Layout)) you would do something like this:

<%  if $Services %>
  <% loop $Services %>
    <div>
      $Title
      $ServTeaser
      $Icon.setWidth(100)
    </div>
  <% end_loop %>
<% end_if %>

Avatar
fatwreck

Community Member, 3 Posts

7 July 2016 at 12:02pm

Hi again. I've got it working now and thought I should post in case others see this. Question was more about how to properly query the database and pull what you want out in order to manipulate.

Controller ended up looking like this.

class FacilityHolder_Controller extends Page_Controller {

	private static $allowed_actions = array (
		'show'
	); 

	public function show(SS_HTTPRequest $request) {
		$location = Location::get()->find('Slug', $request->param('ID'));

		if(!$location) {
			return $this->httpError(404, 'Could not be found.');
		}
    
        if ($location->services) {
          $servicesID = explode(',', $location->services);
          $services_array = new ArrayList(); 
          
          foreach ($servicesID as $ID) {
              $services_array->push(ServicePage::get()->byID($ID));
          }
            return array (
              'Location' => $location,
              'Title' => $location->Title,
              'Services' => $services_array,
            );
        } else {
            return array (
              'Location' => $location,
              'Title' => $location->Title,
            );
        }
	}

    public function GetLocation() {
        return Location::get();
    }
}

Thanks for the advice.