Search code examples
typo3fluidextbaseview-helperstypo3-9.x

TYPO3 9.2.1 Create ViewHelper in Composer Mode


I'm trying to create a ViewHelper with a TYPO3 which was installed in composer mode and a site package which was generated with the sitepackagebuilder.

The autoloading should be configured correctly, nevertheless the only thing I'm getting is an error message, that the ViewHelper cannot be found:

#1407060572: Fluid parse error in template Standard_action_Default_9cc8c1fca58b49310db5d43052e614cefdb1c728, line 5 at character 6. Error: The ViewHelper "<foobar:some>" could not be resolved. Based on your spelling, the system would load the class "Foo\Bar\ViewHelpers\SomeViewHelper", however this class does not exist. (error code 1407060572). Template source chunk: <foobar:some /> (More information)

TYPO3Fluid\Fluid\Core\Parser\Exception thrown in file
/var/www/html/vendor/typo3fluid/fluid/src/Core/Parser/TemplateParser.php in line 157.

Steps To Reproduce

  1. install TYPO3 in composer mode (newest version 9.2.1)
  2. create a site package with https://sitepackagebuilder.com - simple configuration, 'foo' as company name and 'bar' as extension key (see screenshot below)
  3. create a simple class SomeViewHelper under Classes/ViewHelpers/
  4. modify the template under Page/Default to contain the SomeViewHelper (following the example from docs.typo3.org)

    {namespace foobar=Foo\Bar\ViewHelpers} <foobar:some />

  5. create a new root page in TYPO3 with simple content and include the bar extension (Template > Includes)

The autoloading of the code should be handled by the composer.json/ext_emconf.php files which are generated by the sitepackagebuilder.

Screenshot

site package builder configuration

Code

SomeViewHelper.php

<?php
namespace Foo\Bar\ViewHelpers;


use TYPO3\CMS\Fluid\Core\ViewHelper\AbstractViewHelper;

class SomeViewHelper extends AbstractViewHelper
{
    public function render() {
        return 'Hello World';
    }
}

Page/Default.html

<f:layout name="Default" />
<f:section name="Main">

    {namespace foobar=Foo\Bar\ViewHelpers}
    <foobar:some />

    <f:cObject typoscriptObjectPath="lib.dynamicContent" data="{colPos: '0'}" />

</f:section>

also declaring the namespace at the top of the document did not help

<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
      xmlns:foobar="http://typo3.org/ns/Foo/Bar/ViewHelpers">
<f:layout name="Default" />
<f:section name="Main">

    <foobar:some />

    <f:cObject typoscriptObjectPath="lib.dynamicContent" data="{colPos: '0'}" />

</f:section>
</html>

composer.json

{
    "name": "foo/bar",
    "type": "typo3-cms-extension",
    "description": "",
    "homepage": "https://www.foo.com",
    "license": ["GPL-2.0-or-later"],
    "keywords": ["TYPO3 CMS"],
    "version": "1.0.0",
    "require": {
        "typo3/cms-core": "^8.7 || ^9.0",
        "typo3/cms-rte-ckeditor": "^8.7 || ^9.0",
        "typo3/cms-fluid-styled-content": "^8.7 || ^9.0"
    },
    "autoload": {
        "psr-4": {
            "Foo\\Bar\\": "Classes/"
        }
    }
}

ext_emconf.php

<?php

/**
 * Extension Manager/Repository config file for ext "bar".
 */
$EM_CONF[$_EXTKEY] = [
    'title' => 'Bar',
    'description' => '',
    'category' => 'templates',
    'constraints' => [
        'depends' => [
            'typo3' => '8.7.0-9.5.99',
            'fluid_styled_content' => '8.7.0-9.5.99',
            'rte_ckeditor' => '8.7.0-9.5.99'
        ],
        'conflicts' => [
        ],
    ],
    'autoload' => [
        'psr-4' => [
            'Foo\\Bar\\' => 'Classes'
        ],
    ],
    'state' => 'stable',
    'uploadfolder' => 0,
    'createDirs' => '',
    'clearCacheOnLoad' => 1,
    'author' => 'John Doe',
    'author_email' => '[email protected]',
    'author_company' => 'foo',
    'version' => '1.0.0',
];

Solution

  • Assuming that you started with the sitepackagegenerator provided by Benjamin Kott and installed Typo3 in composer mode the following happens:


    The sitepackage's TypoScript part is configured via the Typo3 backend so the loading of the TypoScript as well as templates is independent of the php autoloading.

    The autoload configuration specified under public/typo3conf/ext/<extension> in composer.json and ext_emconf.php is ignored by composer because composer does not know about these extensions, but composer will still show your extension in the list of extensions:

    The following extensions have been added to the generated PackageStates.php file: core, extbase, fluid, frontend, fluid_styled_content, install, setup, rte_ckeditor, about, adminpanel, backend, belog, beuser, documentation, extensionmanager, felogin, filelist, form, impexp, info, recordlist, redirects, reports, saltedpasswords, scheduler, sys_note, t3editor, tstemplate, viewpage, <extension>
    

    Even if the autoloading is configured correctly composer cannot show any informatiom about your extension:

    composer info foo/bar
    
      [InvalidArgumentException]  
      Package foo/bar not found   
    

    So while this is confusing all you have to do is include individual extensions like sitepackages (add the following to the end of your root composer.json - where you also specified things like "require": { "typo3/minimal": "^9.3" }):

    ,
    "autoload": {
      "psr-4": {
        "Foo\\Bar\\": "public/typo3conf/ext/<extension>/Classes/"
      }
    }
    

    After that the example posted in the question should work as expected and the result of <foobar:some /> should be Hello World.

    <html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
          xmlns:foobar="http://typo3.org/ns/Foo/Bar/ViewHelpers">
    <f:layout name="Default" />
    <f:section name="Main">
    
        <foobar:some />
    
        <f:cObject typoscriptObjectPath="lib.dynamicContent" data="{colPos: '0'}" />
    
    </f:section>
    </html>