Search code examples
phptypo3typo3-9.xtypo3-extensions

TYPO3 Controller Class could not be found. Where do I link it?


I am developing an extension for TYPO3 v9.5.9, and have written all of my code, however when I try using the extension I get an error message saying

Class Secsign\Secsign\Controller\SecsignController does not exist. Reflection failed.

enter image description here

<?php
namespace Secsign\Secsign\Controller;

$apiPath = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('secsign') . 'Resources/Public/SecSignIDApi/phpApi/SecSignIDApi.php';
require_once($apiPath);

use AuthSession;
use SecSignIDApi;
use \TYPO3\CMS\Core\Utility\GeneralUtility;


/**
 * SecsignController
 */
class SecsignController extends ActionController
{...}

The controller does exist, but for some reason it can't be found. Where does this error occur? How do I fix it? Any hints are welcome.

The composer.json file looks like this:

{
    "name": "secsign/secsign",
    "type": "typo3-cms-extension",
    "description": "This extension allows users to authenticate using their smart phone running the SecSign App.",
    "authors": [
        {
            "name": "SecSign Technologies Inc.",
            "role": "Developer"
        }
    ],
    "require": {
        "typo3/cms-core": "^9.5"
    },
    "autoload": {
        "psr-4": {
            "Secsign\\Secsign\\": "Classes",
            "TYPO3\\CMS\\Secsign\\": "public/typo3conf/ext/secsign/Classes/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Secsign\\Secsign\\Tests\\": "Tests"
        }
    },
    "replace": {
        "secsign/secsign": "self.version",
        "typo3-ter/secsign": "self.version"
    }
}

Solution

  • There are 2 Ways how you can solve this:

    1. Load your Extension via the project composer.json

    Create a folder for your custom Extensions, I named it here Extensions and move all your custom Extensions into this folder. Your public/typo3conf/ext/ folder should now hold only Extensions loaded by composer and can be cleared at any time since a simple composer i will bring all Extensions back.

    └── projectRoot
        ├── Extensions
        │   └── secsign
        │       └── Classes
        ├── composer.json
        └── public
            └── typo3conf
                └── ext
                    └── secsign(symlink_by_composer)
    

    Add this to your project composer.json:

      "repositories": {
        "0": {
          "type": "composer",
          "url": "https://composer.typo3.org/"
        },
        "1": {
          "type": "path",
          "url": "./Extensions/*",
          "options": {
            "symlink": true
          }
        }
      },
    
      ...
    
      "require": {
        "secsign/secsign": "*",
        ...
      },
    

    Remove the second line from the autoload in your Extensions composer.json

    public/Extensions/secsign/composer.json:

      "autoload": {
        "psr-4": {
          "Secsign\\Secsign\\": "Classes/"
        }
      },
    

    Now composer loads your project composer.json, finds your Extension, symlinks it into typo3conf/ext/ and reads your extensions composer.json and executes it.

    Loading all Ext into your project: When your done with all this changes, just do a composer update. This will load all your third party extensions into projectRoot/public/typo3conf/ext/ and symlink your custom extensions from secsign -> ../../../Extensions/secsign

    Adding more custom Extensions: Just add your custom extension into Extension/, make sure it has a valid composer.json and include it with

    composer req secsign/one-more-ext
    

    2. Add your Classes to your project composer.json

    Leave your Extension where it is, don't care about your extensions composer.json and just add your Classes to your project composer.json:

      "autoload": {
        "psr-4": {
          "Secsign\\Secsign\\": "htdocs/typo3conf/ext/secsign/Classes/"
        }
      },
    

    Now composer autoloads the classes from your projects composer.json, your Extensions composer.json is not even executed.

    Final

    1. seems to be easier, but there are several reasons to go for 1.