PHP Fatal error: Class 'PageController' not found

Upgrading from silverstripe 3.65 to 4.0.0. Following the upgrade guide.

When trying to migrate assets using the following:
./vendor/bin/sake dev/tasks/MigrateFileTask

I get the following error message:
PHP Fatal error: Class ‘PageController’ not found in /Users/awebsite/vendor/silverstripe/errorpage/src/ErrorPageController.php on line 12

I’ve stripped out all mysite files and used default Page.php and PageController.php to eliminate any old code issues

Also removed all additional modules in composer. Here is my composer file:
{
“name”: “silverstripe/installer”,
“require”: {
“silverstripe/recipe-plugin”: “^1”,
“silverstripe/recipe-cms”: “1.0.0@stable”,
“silverstripe-themes/simple”: “~3.2.0”
},
“prefer-stable”: true,
“minimum-stability”: “dev”,
“extra”: {
“project-files-installed”: [
“.htaccess”,
“index.php”,
“install-frameworkmissing.html”,
“install.php”,
“mysite/.htaccess”,
“mysite/_config.php”,
“mysite/_config/mysite.yml”,
“mysite/code/Page.php”,
“mysite/code/PageController.php”,
“web.config”
],
“public-files-installed”: [
“.htaccess”,
“index.php”,
“install-frameworkmissing.html”,
“install.php”,
“web.config”
]
}
}

This is stopping from getting old 3x assets files working. Any help / pointers appreciated.

Thanks

Do you have a PageController class in the root namespace, extending ContentController? Because that’s what’s required for an SS4 installation to work, Page and PageController in the root namespace

Could you provide an example?

But I did manage to work around this. Was able to run /dev/tasks/MigrateFileTask successfully in the browser.

Thanks

OK I’ve worked all this out correctly now. The below solution may help others:

  1. Add name spaced file composer.json to mysite root (will be different for silverstripe 4.1)
    {
    “name”: “silverstripe/myproject”,
    “description”: “Code,
    “license”: “BSD-3-Clause”,
    “authors”: [
    {
    “name”: “Your Name”,
    “email”: "email@someemail.com
    }
    ],
    “require”: {
    “silverstripe/recipe-cms”: “^1.0”
    },
    “autoload”: {
    “psr-4”: {
    “SilverStripe\MyProject\”: “mysite/”
    }
    }
    }

  2. in code folder, say Page.php

<?php namespace SilverStripe\MyProject; use Page; use PageController; ... 3. If upgrading from 3.x, and have existing table names, you will need this piece of code to map the old table names. private static $table_name = 'ContactUsPage'; Thanks

[Add name spaced file composer.json to mysite root (will be different for silverstripe 4.1)]

Hi outdoorsnz, when performing in terminal:

./vendor/bin/sake dev/tasks/MigrateFileTask

I’m getting an error in my IDE that says, “Cannot declare class SilverStripe\trevorpan\Page because the name is already in use.”

It happens intermittently with the PageController class, too. When you say silverstripe/myproject I’m typing the folder name in htdocs “trevorpan” (my own website) would this be correct?

I’ve added a composer.json file as you say:

{
“name”: “silverstripe/trevorpan”,
“description”: “Code,
“license”: “BSD-3-Clause”,
“authors”: [
{
“name”: “Your Name”,
“email”: "email@someemail.com”
}
],
“require”: {
“silverstripe/recipe-cms”: “^1.0”
},
“autoload”: {
“psr-4”: {
“SilverStripe\trevorpan\”: “mysite/”
}
}
}

This is the page.php file:

?php

namespace SilverStripe\trevorpan;

use Page;

use PageController;

use SilverStripe\CMS\Model\SiteTree;

use PackageTextField;

use DropdownField;

use UploadField;

use ContentController;

use Requirements;  

class Page extends SiteTree {

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

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;
}

private static $table_name = "MyDataObject";
//private static $db = [];
//private static $has_one = [];

}

class PageController 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() {
	parent::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
	Requirements::themedCSS('reset');
	Requirements::themedCSS('layout');
	Requirements::themedCSS('typography');
	Requirements::themedCSS('form');
}

}

thank you,
Trevor

Hi @trevorpan, I’m new to namespacing (like most people) but if I understand correctly you don’t need to namespace any of your custom project code. Doing so just makes more work for yourself, and the Page and PageController classes need to be in the global namespace anyway - which basically means they must not be namespaced! If you’re publishing a module that would be a different story, module code should be namespaced to avoid conflicts and give developers choices about how they use your code.

You also don’t need to add a ‘use’ line for any classes that are within the namespace you’re working in, so if you’re working in the global space, you won’t need to import any classes of your own making. To put a class in the global namespace, you just need to omit the namespace declaration. If I’m right about this stuff, then your Page.php file might look more like this:

<?php

use SilverStripe\AssetAdmin\Forms\UploadField;
use SilverStripe\CMS\Model\SiteTree;
use SilverStripe\Forms\DropdownField;
use SilverStripe\View\Requirements;

class Page extends SiteTree { ... }

Hi @trevorpan and @JonoM,

Sorry my post was little incorrect and I should have updated it.

I namespaced every file in mysite folder EXCEPT Page.php and PageController.php. Namespacing those two blew my project to bits.

You don’t have to namespace at all, but is a good idea since most code snippets now will be namespaced.

Hopefully you have made backups as you go, as I found once I namespaced page.php and pagecontroller.php and then remove the namespace, then I couldn’t go back. But maybe something was cached.

Also your code must be quite old, as you need to change public static to private static…

Read through the 4.0 upgrade notes.
https://docs.silverstripe.org/en/4/changelogs/4.0.0/

Also very important if upgrading, mapping old database table names, otherwise they will get renamed to namedspaced name etc. Create a yaml upgrade.yml in mysite/_config and in that:

SilverStripe\ORM\DatabaseAdmin:
classname_value_remapping:
MyOldTableName: MyProject\CoffeeBeans\MyOldTableName

Hope that helps.

Regards
Scott

@JonoM,

From the ‘page’ post the other week, I took out page, like you mentioned.

I’ll give your new suggestions a try!

The namespacing came from the upgrade tool. I figured if the tool did it it was a good thing.

Thank you,
Trevor

outdoorsnz
Yea, the code might be five years old. The developer who originally did it sadly went out of business. I thought it would be fun to learn PHP so I took some community classes and bought a few books and am giving it my best!

I’m going down the upgrading notes, one by one.

Is that the best way to do it? Or would you go through all of it, whether or not each item is fixed and change logs then fine tune? Having a hard time knowing how to tackle the overall project.(upgrading)

Best regards,

Trevor

Hi Treavor.

5 years is quite a long time in silverstripe development lifecycle. You would need to find out the version you currently have, and work your way through the change logs. i.e. to jump straight to the latest 4 branch might mean you have to edit lots of code and lots of bugs.

But yes working through one by one is the way to do it. Otherwise you might find it is actually easier to start afresh redesign / reengineer your website.

Regards
Scott