Controllers, routes and home page.

Silverstripe Version: 4

I’m trying to migrate an existing project into SS.

It’s a one page site with content “blocks” managed by the CMS. I realise it would probably be easier to make all these blocks as part of the home page type/template/layout in the CMS.

That’s not how it was though and this is more an exercise of “I could do this before in the old system, can I do it in SS”.

What I want:
A model/module in the CMS to manage content blocks that is seperate to the idea of a page. I’m pretty sure I can do this from the Lessons series.
A controller for the home page. In here I’ll add css/js and get the data from the above model to make available in the view.

So, super simple…

Currently I’m stuck at the routes, I think. The home page always loads page.ss and skips the controller.

routes.yml:

---
Name: routes
After: framework/_config/routes#coreroutes
---
SilverStripe\Control\Director:
  rules:
    '': 'HomePageController'

Controller:

use SilverStripe\Control\Controller;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\View\Requirements;

class HomePageController extends Controller
{
	private static $allowed_actions = [
        'index'
    ];

    protected function init()
	{
		parent::init();

	    Requirements::css('css/some.css');
        Requirements::javascript('javascript/some.js');
	}

	public function index(HTTPRequest $request)
	{
		echo 'Home page::Index';

		die;
	}
}

I was extending PageController with the same result. I’m missing something obvious or doing something dumb, take pity.

You can use Silverstripe Elemental to do that. It allows you to add pre-defined blocks into a page.

For the other issue, if you’re just having the home page managed in the CMS, you shouldn’t need any custom routing or special controllers, etc. it should just work out of the box. Just add your CSS / JS requirements to the init() function in PageController.php and you should be away.

Thanks, I got that part done with a DataObject and extending modelAdmin. Data is all in.

The page itself isn’t managed in the CMS. Is the PageController still the right way to handle this?

Please try to flush the cache ie ?flush=1

Cheers, yeah I’ve been flushing and dev/building like mad…

U can either do it through elemental module, or through custom tinymce plugins;

I prefer the latter because of ease of managing the “entire” view instead of a grid

If your page isnt managed in cms, you will still need a controller to handle the view; and routes to point to this controller

Looks like your are missing ‘After’, please follow routing , but I not pro with yaml file, so i don’t know this will work.

After:
  - '#rootroutes'
  - '#coreroutes'

Thanks Thomas, After is at the top of the file after the name.
The value is different though from what you have. I changed the routes file to:

---
Name: mysiteroutes
After:
  - '#rootroutes'
  - '#coreroutes'
---
SilverStripe\Control\Director:
  rules:
    '': 'HomeController'

I head to my root in the browser and nothing seems to hit the HomeController. It still goes to PageController.
If I remove the PageController and Page file(s) the admin throws a 500.

I suspect it is this route in cms which runs after everything that is causing your issue; not sure what is the best practice for overriding that though:

https://github.com/silverstripe/silverstripe-cms/blob/master/_config/routes.yml

Yeah I’d agree with you - thanks for finding that. I started hacking at the Director class and my version of '':'HomeController' doesn’t show up. If I do a different URL segment like 'pain':'PainController' I can see it getting into the Director. If I use After - '*' as well has no effect.

I tried to create yml as mentioned below, but does not seems to work, looks like to bug. And if replace empty string ie ’ ’ with ‘home’: ‘SilverStripe\Lessons\HomePageController’, works fine.


Name: mycustomroutes
After:

  • #coreroutes
  • #rootroutes

SilverStripe\Control\Director:
rules:
‘’: ‘SilverStripe\Lessons\HomePageController’

Hey Thomas, yeah CW_Chong posted a link just above that seems to show the cause of that.

When you say it works with ‘home’ in the route, do you have /home in the URL or not?

Yes if i do /home, returns ‘Home page::Index’ ie for ‘home’: ‘SilverStripe\Lessons\HomePageController’

@thomas28 yeah that’s as expected right. Like my example above with “pain” as the segment.

The problem is when you want no segment at all or a catch all.

Not sure if you solved your route issue. But I ran into the same issue with my routes, and seemed like I needed to add - ‘#modelascontrollerroutes’ to the “After” block of myroutes, like this;

Name: approutes
After:
  - '#rootroutes'
  - '#coreroutes'
  - '#modelascontrollerroutes'
---

The reason is that #modelascontrollerroutes (/vendor/silverstripe/cms/_config/routes.yml) have the following line;

'': 'SilverStripe\CMS\Controllers\RootURLController'

Oh okay, interesting. With this specific problem it was a one page site so I didn’t use routes and put it straight into PageController::index.

This is what I would do

  1. You need a new Page type: Homepage.php (namespace MyProject/Layout)
  2. Create a page with the type in the CMS
  3. Create a .ss file at themes/THEMENAME/templates/MyProject/Layout/Layout/Homepage.ss
  4. flush

ps: if you must override index function, make sure you also tell it which template to use for rendering, by calling renderWith function, and giving it the template name - otherwise you will get a blank page with nothing in it but only the echo

What I did in the end was similar to that @leochenftw

I’ve done it two different ways in different projects.

Neither used routes.yaml.

The first just used PageController::index to get the module entries and view the page with $this->customise()->renderWith().

The second uses a HomePage class, HomePageController and HomePage template in Layouts. I load the extra data later via an AJAX call to a method in the controller.