Why does the Page Class does not find my custom class which is in another namespace?


#1

4.3

Question:

Why does the Page Class does not find my custom classes?
I wrote an addon -> Schrattenholz\ContentObject which includes a class called ContentObject
Now I want to add a has_many relation from Page to ContentObject.

<?php

namespace {

        use SilverStripe\CMS\Model\SiteTree;
	use Schrattenholz\ContentObject\ContentObject;

    class Page extends SiteTree
    {
        private static $db = [];

        private static $has_one = ['SidebarObjects'=>ContentObject::class,];
    }
}

But I get the following error:

has_one relation Page.SidebarObjects references class Schrattenholz\ContentObject\ContentObject which doesn't exist

It works fine If I create a new class inherting from Page which is in the same namespace

namespace Schrattenholz\ContentObject;
use Page;
	
class StandardPage extends Page
    {
        private static $db = [];
	private static $has_many = [
		'SidebarObjects'=>ContentObject::class,
	];
    }

Guess a comprehensive missunderstanding…?
Thanks in advance.


#2

Is the DataObject code in your addon? If so, have you included the relevant PSR-4 autoloader lines in the composer.json for your addon?


#3

Oh no I didn’t could you give me an example on how it has to look like?
Do the addon has to be on github?


#4

OK,… I just took a composer.json from another addon as an example.
I ended up with this code, but the error still appears.

{
“name”: “schrattenholz/contentobject”,
“description”: “contentobjets”,
“type”: “silverstripe-module”,
“keywords”: [“silverstripe”, “contentobject”],
“license”: “BSD-3-Clause”,
“authors”: [
{
“name”: “Fabian Schrattenholz”,
“email”: "fabian@schrattenholz.de"
}
],
“autoload”: {
“psr-4”: {
“Schrattenholz\ContentObject\”: “src/”
}
}
}


#6

I still get the error I post the whole setting. Am I missing anything?

path to module:
siteroot/vendor/schrattenholz/contentobject

siteroot/vendor/schrattenholz/contentobject/src/ContentObject.php

namespace Schrattenholz\ContentObject;
use Page;
use SilverStripe\ORM\DataObject;
class ContentObject extends DataObject{
	private static $has_one=[
		'Page'=>Page::class
	];
}

siteroot/vendor/schrattenholz/contentobject/src/composer.json


{
    "name": "schrattenholz/contentobject",
    "description": "contentobjets",
    "type": "silverstripe-module",
    "keywords": ["silverstripe", "contentobject"],
    "license": "BSD-3-Clause",
    "authors": [
        {
            "name": "Fabian Schrattenholz",
            "email": "fabian@schrattenholz.de"
        }
    ],
	"autoload": {
	  "psr-4": {
		"Schrattenholz\\ContentObject\\": "src/"
	  }
	}
}

siteroot/app/src/Page.php

namespace {
    use SilverStripe\CMS\Model\SiteTree;
	use Schrattenholz\ContentObject\ContentObject;

    class Page extends SiteTree
    {
        private static $db = [];

        private static $has_one = ['SidebarObjects'=>ContentObject::class,];
    }
}

the error:

Uncaught Exception InvalidArgumentException: “has_one relation Page.SidebarObjects references class Schrattenholz\ContentObject\ContentObject which doesn’t exist”


#5

You’ll probably need to escape the namespace, eg:

"autoload": {
  "psr-4": {
    "Schrattenholz\\ContentObject\\": "src/"
  }
}

That setup assumes your class is in the src directory in your module.

Make sure you run a dev/build?flush after any of these changes.


#7

Since your code is in the vendor directory, this probably should be changed to:

"type": "silverstripe-vendormodule"

Run a dev/build?flush again and see if that cures it


#8

Hej DorsetDigital,

it s working now. I was migrating a SS3 site.
I set up a plane site to test the module. I took ContentObjects [“ContentObjects”=>ContentObject::class] as the ReferenceName and it worked. I copied that code to my ss3 site and it worked too. So it dependened on the naming of the relation. Any idea why?

Thanks all lot for your help