Use Custom Classes in Package

I try to use a custom class in a package but I fail. I read the documentation here: https://documentation.concretecms.org/9-x/developers/security/adding-custom-code-to-packages
But it doesn’t work when I follow this article.

My package’s name is “fhs”, the custom class is “Shortcuts”, stored in the file /packages/fhs/src/Shortcuts.php with namespace “Concrete\Package\Fhs”. I try to use it with “Concrete\Package\Fhs\Shortcuts”.

My first problem is, that I don’t understand the phrase
“Just add this boolean to your package’s controller.php:
$pkgAutoloaderMapCoreExtensions = true;”
in the documentation.

What does “add this boolean to your … controller.php” mean? As a property (public)? Or in the on_start()-function? Or elsewhere? I made it a public property and a variable in the on_start()-function but none of them worked.

I also tried to use my class with “Src” in the namespace, but no.

I also read this post:

and tried what was recommended there, but it didn’t work either.

There must be something I didn’t understand from the documentation. I remember sucessfully using my own classes in earlier versions of ConcreteCms (or rather Concrete5).

My code:

/packages/fhs/src/Shortcuts.php

<?php
namespace Concrete\Package\Fhs;
class Shortcuts {
    public static function render($content) {
        return $content;
    }
}

/packages/fhs/controller.php

...
use Concrete\Package\Fhs\Shortcuts;
...
    public function on_start() {
        $this->pkg = $this;
        $this->registerAssets();
        echo Shortcuts::render('Hollebolle');
...

OUTPUT:
Error
Class “Concrete\Package\Fhs\Shortcuts” not found

So lets say this is your package’s controller

<?php
namespace Concrete\Package\Fhs;

defined('C5_EXECUTE') or die('Access denied.');

use Concrete\Core\Package\Package;

class Controller extends Package
{
    protected $pkgHandle = 'fhs';
    protected $appVersionRequired = '9.0';
    protected $pkgVersion = '0.9';
    
    /**
     * @var bool disable legacy namespacing. Remove \Src from package namespace.
     */
    protected $pkgAutoloaderMapCoreExtensions = true;
    
    /**
     * let's map your "src" folder to "Fhs" so your class inside it uses "Fhs" as namespace.
     */
    protected $pkgAutoloaderRegistries = [
        'src => '\Fhs',
    ];

    public function getPackageName()
    {
        return t('FHS');
    }

    public function getPackageDescription()
    {
        return t('Does what FHS does');
    }

    /**
     * the rest of your package controller goes below
     **/
    
}

To be honest I’m not even sure both $pkgAutoloaderMapCoreExtensions and $pkgAutoloaderRegistries are required, but it works for me.

So now your class /packages/fhs/src/Shortcuts.php should be:

<?php
namespace Fhs;
class Shortcuts {
    public static function render($content) {
        return $content;
    }
}

You see the namespace is Fhs because that’s what we defined in the controller with $pkgAutoloaderRegistries

So in your package’s controller you will do:

use Fhs\Shortcuts;

If instead your class had been in /packages/fhs/src/SomeFolder/Shortcuts.php then the namespace would have been

namespace Fhs\SomeFolder;

I hope this helps

$pkgAutoloaderMapCoreExtensions is only necessary when you want to avoid \Src as part of the automatically generated namespace and you are not otherwise mapping the namespace with $pkgAutoloaderRegistries.

If you use $pkgAutoloaderMapCoreExtensions, then the autoload mappings are going to be whatever is specified in that array.

Using $pkgAutoloaderMapCoreExtensions simply changes the automatic mapping from \Concrete\Package\Src\Fhs\Shortcuts to \Concrete\Package\Fhs\Shortcuts. But for this to work, you also have to move /packages/fhs/src/Shortcuts.php to /packages/fhs/src/Concrete/Shortcuts.php.

I’ve tried reworking that page to make this issue clearer. Let me know if I’ve missed anything or if there is still some confusion.