Fatal error: Class 'Page' not found in MAMP/htdocs/trevorpan/gallery/code/GalleryPage.php on line 3

Silverstripe Version:

This is my first time upgrading a SS site; if you have any ideas of where I’m going wrong please share.

After running the silverstripe update tool I believe the namespaces were added to Page.php

I’m presuming the namespace Page is not global and therefore inaccessible. I read this post https://github.com/silverstripe/silverstripe-framework/issues/5844

use Sminnee\AppNamespace as App;

class Page extends App\Page { private static $hide_pagetype = true; }
class Page_Controller extends App\Page_Controller {}

However, I cannot see a \AppNamespace folder. So I’m not sure how implement the above.

There’s a post from today’s SS forum about Class ‘Page’ not found, however my /dev/build does not work and that is not the same issue I’m facing.

The environment is set to “dev”.

//Source: /Applications/MAMP/htdocs/trevorpan/mysite/code/Page.php

namespace Page;

use SiteTree;
use TextField;
use DropdownField;
use UploadField;
use ContentController;
use Requirements;

class Page extends SiteTree {

	public static $db = array(
			'Tagline' => 'Varchar(355)',
			'ContentWidth' => 'Varchar(100)',

	public static $has_one = array(
        'FeaturedImage' => 'Image', 


    public function getCMSFields() {
        $fields = parent::getCMSFields();
        $fields->addFieldToTab("Root.Main", new TextField('Tagline', 'Tagline'));
        $fields->addFieldToTab("Root.Main", new DropdownField('ContentWidth', 'ContentWidth', array('One'=>'One', 'Two'=>'Two', 'Full'=>'Full')));
        $fields->addFieldToTab("Root.Images", $featuredimage = UploadField::create('FeaturedImage', _t('FeaturedImage', 'FeaturedImage')));
        $featuredimage->getValidator()->setAllowedExtensions(array('jpg', 'jpeg', 'png', 'gif'));

        return $fields;

class Page_Controller extends ContentController {

	 * An array of actions that can be accessed via a request. Each array element should be an action name, and the
	 * permissions or conditions required to allow the user to access it.
	 * <code>
	 * array (
	 *     'action', // anyone can access this action
	 *     'action' => true, // same as above
	 *     'action' => 'ADMIN', // you must have ADMIN permissions to access this action
	 *     'action' => '->checkAction' // you can only access this action if $this->checkAction() returns true
	 * );
	 * </code>
	 * @var array
	public static $allowed_actions = array (

	public function init() {

		// Note: you should use SS template require tags inside your templates
		// instead of putting Requirements calls here.  However these are
		// included so that our older themes still work


**end of file**


class GalleryPage extends Page {
	public static $many_many = array(
  	'Images' => 'Image'	
  public function Images() {
  	return $this->getManyManyComponents(
  		"\"GalleryPage_Images\".\"SortOrder\" ASC"
  public function ImagesCaptions() {
  	$captions = GalleryPage_Images::get()
			->where("\"GalleryPageID\" = '{$this->ID}'")
			->map('ImageID', 'Caption')

  public function getCMSFields() {

  	$fields = parent::getCMSFields();

  	$uploadField = new GalleryUploadField('Images', '');
  	$fields->addFieldToTab('Root.Images', $uploadField);

  	return $fields;

class GalleryPage_Controller extends Page_Controller {
  public function init() {



class GalleryPage_ImageExtension extends DataExtension {

	public static $belongs_many_many = array(
    'Pages' => 'Page'

  public function getUploadFields() {

  	$fields = $this->owner->getCMSFields();

  	$fileAttributes = $fields->fieldByName('Root.Main.FilePreview')->fieldByName('FilePreviewData');
  	$fileAttributes->push(TextareaField::create('Caption', 'Caption:')->setRows(4));

  	$fields->removeFieldsFromTab('Root.Main', array(
  	return $fields;
  public function Caption() {

  	//TODO: Make this more generic and not require a db query each time
  	$controller = Controller::curr();
		$page = $controller->data();

  	$joinObj = GalleryPage_Images::get()
			->where("\"GalleryPageID\" = '{$page->ID}' AND \"ImageID\" = '{$this->owner->ID}'")
		return $joinObj->Caption;

class GalleryPage_Images extends DataObject {
	static $db = array (
	'GalleryPageID' => 'Int',
	'ImageID' => 'Int',
    'Caption' => 'Text',
    'SortOrder' => 'Int'

Your own code and classes don’t really need to be namespaced, and I think that any SS modules that expect a Page class will expect it to be in the global namespace. If you remove the namespace Page line, does it build okay then?

Just to be clear - if you have a class of Page inside a Page namespace then the full name of your class is effectively Page\Page.

Hi Jono,

Thank you. I’ve tried out below and receive the following error.


//extends Page\Page

class GalleryPage {

error: Fatal error : Class ‘Page_Controller’ not found in /Applications/MAMP/htdocs/trevorpan/gallery/code/GalleryPage.php on line 37

then I tried as you mentioned:

<?php class GalleryPage extends Page\Page { public static $many_many = array( 'Images' => 'Image' );

**error:** **Fatal error** : Class 'SiteTree' not found in **/Applications/MAMP/htdocs/trevorpan/mysite/code/Page.php** on line **12**

If the 3.x SS site uses a gallery, should it be dumped while upgrading the overall site and a new 4.0 gallery version added?

My confusion comes from the upgrade notes https://docs.silverstripe.org/en/4/upgrading/ specifically here:

_The `Page` and `PageController` classes *must* be defined in the global namespace (or without a namespace)._ <

The upgrader tool changed this file-to be honest I don't know enough to positively change much, just trying to follow directions. Would you remove the namespace completely? Is that an easy fix?

The manual seems to be explicit in globals, just state "global" ..._class_


Much appreciated,


PS-not sure what's happening with the formatting

@trevorpan that GalleryPage extends Page\Page part should just be GalleryPage extends Page because Page should be in the global namespace (i.e. not namespaced). I think an exercise that would be useful for you is to separately install a fresh version of SS4 from the installer. That will give you a local example to look at and compare which has the Page class and config files etc. set up using SS4 conventions. Not sure what has happened with your pasted code either - did you escape it with backticks?

Hi Jono,

Great idea on looking at a fresh copy of SS4.

After this site is updated I’ll feel like I accomplished a lot.

Appreciate your thoughts,


Page_Controller was the naming convention used in Silverstripe 3. In Silverstripe 4, it should be called ‘PageController’

If you’re using a gallery add-on, and it was written for SS3, then there’s a good chance you’ll have problems. Taking it out of the equation would be a sensible way to go for now. Get the main site code updated, and then look at an updated version of the add-on.


Hi DorsetDigital,

Thank you for the tips.

Do you generally put a underscore like this … “_Gallery” to make the folder inaccessible while you update the rest of the code? I tried this and a lot of errors occurred.

`Warning : require_once(/Applications/MAMP/htdocs/trevorpan/gallery/_config.php): failed to open stream: No such file or directory in /Applications/MAMP/htdocs/trevorpan/framework/core/manifest/ClassLoader.php on line 57

Fatal error : require_once(): Failed opening required ‘/Applications/MAMP/htdocs/trevorpan/gallery/_config.php’ (include_path=’.:/Applications/MAMP/htdocs/trevorpan/framework:/Applications/MAMP/htdocs/trevorpan/framework/parsers:/Applications/MAMP/htdocs/trevorpan/framework/thirdparty:.:/usr/local/pear/lib/php:/Applications/MAMP/bin/php/php7.1.12/lib/php’) in /Applications/MAMP/htdocs/trevorpan/framework/core/manifest/ClassLoader.php on line 57`

If you know of a guide on this I can check out please share, I know alot of my questions are pretty basic. Trying get started in developing.

Best regards,

if you want to make a folder inaccessible to the manifest builder, put a file named “_manifest_exclude” into that folder; the name is without any file extension.

1 Like